Added options to control different ranges of breakpoints.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import React, {useCallback, useEffect, useState} from "react";
|
||||
import {ButtonStyling, ResponsiveButtonStyle, ResponsiveOptionsDropdown} from "./responsive-button.style.js";
|
||||
|
||||
const responsiveOptions = {
|
||||
desktop: [1920, 1800, 1680, 1440, 1360, 1280, 1024],
|
||||
tablet: [992, 768, 600],
|
||||
mobile: [480, 414, 375, 360],
|
||||
}
|
||||
|
||||
const defaultResponsiveOptions = {
|
||||
reset: '100%',
|
||||
desktop: responsiveOptions.desktop[0],
|
||||
tablet: responsiveOptions.tablet[1],
|
||||
mobile: responsiveOptions.mobile[2],
|
||||
}
|
||||
|
||||
export function ResponsiveButton({mode, active, onSelect}) {
|
||||
// active = true;
|
||||
const [state, setState] = useState({open: true, breakpoint: defaultResponsiveOptions[mode]});
|
||||
const updateState = (update) => {
|
||||
// update.open = true;
|
||||
setState(Object.assign({}, state, update));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const closeDropdown = (e) => isEscHit(e) ? updateState({open: false}) : null;
|
||||
|
||||
if (state.open) {
|
||||
document.addEventListener("keydown", closeDropdown);
|
||||
}
|
||||
|
||||
// Unsubscribe from ESC listener.
|
||||
return () => {
|
||||
document.removeEventListener("keydown", closeDropdown);
|
||||
}
|
||||
});
|
||||
|
||||
// Blur event / Outside click
|
||||
const outsideClickAction = async (e) => await isClickOutside(e) ? updateState({open: false}) : null;
|
||||
const handleBlur = useCallback(outsideClickAction, []);
|
||||
|
||||
return <ResponsiveButtonStyle tabIndex='0' onBlur={handleBlur}>
|
||||
<ButtonStyling data-mode={mode} data-active={active} onClick={() => select()}>{mode}</ButtonStyling>
|
||||
{active && state.open && responsiveOptions[mode] &&
|
||||
<ResponsiveOptionsDropdown>
|
||||
{responsiveOptions[mode].map((breakpoint) => {
|
||||
return <li>
|
||||
<a className={state.breakpoint === breakpoint ? 'active' : ''} onClick={() => select(breakpoint)}>{breakpoint}</a>
|
||||
</li>;
|
||||
})}
|
||||
</ResponsiveOptionsDropdown>
|
||||
}
|
||||
</ResponsiveButtonStyle>;
|
||||
|
||||
//
|
||||
// Actions
|
||||
//
|
||||
|
||||
function select(breakpoint = null) {
|
||||
// Click on option in Dropdown.
|
||||
if (breakpoint) {
|
||||
updateState({open: false, breakpoint});
|
||||
onSelect(breakpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
// Click on device button.
|
||||
if (!active) {
|
||||
onSelect(state.breakpoint)
|
||||
updateState({open: false});
|
||||
} else {
|
||||
updateState({open: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function update(state, update) {
|
||||
return Object.assign({}, state, update);
|
||||
}
|
||||
|
||||
export async function isClickOutside(e) {
|
||||
const currentTarget = e.currentTarget;
|
||||
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(!currentTarget.contains(document.activeElement));
|
||||
}, 100);
|
||||
})
|
||||
}
|
||||
|
||||
export function isEscHit(event) {
|
||||
return event.key === 'Escape'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
export const ButtonStyling = styled.button`
|
||||
--size: 1.5rem;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
background-image: url("/scripts/dist/toolbar/images/icon-desktop.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: calc(var(--size) - 0.15rem);
|
||||
background-position: center;
|
||||
background-color: initial;
|
||||
font-size: 1px;
|
||||
color: rgba(0, 0, 0, 0);
|
||||
line-height: 1;
|
||||
display: block;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 0.25rem;
|
||||
outline: none;
|
||||
|
||||
&[data-mode='tablet'] {
|
||||
background-image: url("/scripts/dist/toolbar/images/icon-tablet.svg");
|
||||
}
|
||||
|
||||
&[data-mode='mobile'] {
|
||||
background-image: url("/scripts/dist/toolbar/images/icon-mobile.svg");
|
||||
}
|
||||
|
||||
&[data-mode='reset'] {
|
||||
background-image: url("/scripts/dist/toolbar/images/icon-reset.svg");
|
||||
}
|
||||
|
||||
&[data-active='true'] {
|
||||
background-color: #CBD5E0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ResponsiveOptionsDropdown = styled.ul`
|
||||
list-style: none;
|
||||
padding: 4px;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
box-shadow: 2px 2px 4px 0 #ccc;
|
||||
border-radius: 4px;
|
||||
transform: translateX(-50%);
|
||||
left: 50%;
|
||||
margin: 0.25rem 0 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 2px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
color: #14181F;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #EDF2F7;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #cbd5e0;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const ResponsiveButtonStyle = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
Reference in New Issue
Block a user