jobiqo-cl
Version:
[](https://circleci.com/gh/jobiqo/jobiqo-cl)
150 lines (144 loc) • 5.06 kB
JavaScript
import React__default, { useEffect } from 'react';
import styled from 'styled-components';
import FocusTrap from '../../../../../node_modules/focus-trap-react/dist/focus-trap-react.js';
import { motion } from '../../../../../node_modules/framer-motion/dist/framer-motion.es.js';
/**
* @file index.tsx
*
* @fileoverview Renders a drawer in a position defined by props. Can be used for sidenavs or mobile drops.
*/
const ESCAPE_KEY = 27;
const StyledOverlay = styled.div `
z-index: 1300;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100vw;
height: 100vh;
z-index: 100;
position: fixed;
touch-action: none;
-webkit-tap-highlight-color: transparent;
background-color: ${props => props.theme.navigation.mobile.sidenav.overlay.background};
`;
const variants = {
left: {
open: {
x: '0%',
opacity: 1,
transition: { ease: 'easeIn', duration: 0.3, staggerChildren: 0.5 },
},
closed: {
x: '-150%',
opacity: 0,
transition: { ease: 'easeOut', duration: 0.5, staggerChildren: 0.5 },
},
},
right: {
open: {
x: '0%',
opacity: 1,
transition: { ease: 'easeIn', duration: 0.3, staggerChildren: 0.5 },
},
closed: {
x: '200%',
opacity: 0,
transition: { ease: 'easeOut', duration: 0.5, staggerChildren: 0.5 },
},
},
bottom: {
open: {
y: '0%',
opacity: 1,
transition: { ease: 'easeIn', duration: 0.3, staggerChildren: 0.5 },
},
closed: {
y: '100%',
opacity: 0,
transition: { ease: 'easeOut', duration: 0.5, staggerChildren: 0.5 },
},
},
top: {
open: {
y: '0%',
opacity: 1,
transition: { ease: 'easeIn', duration: 0.3, staggerChildren: 0.5 },
},
closed: {
y: '-100%',
opacity: 0,
transition: { ease: 'easeOut', duration: 0.5, staggerChildren: 0.5 },
},
},
};
const StyledSideNavBlock = styled(motion.div) `
overflow: auto;
position: fixed;
${props => (props.position === 'right' ? `right: 0;` : `left:0;`)}
${props => (props.position === 'top' ? `top: 0;` : `bottom: 0;`)}
width: 100%;
${props => props.position === 'left' || props.position === 'right'
? `
top: 0;
max-width: ${props.theme.navigation.mobile.sidenav.maxWidth};
`
: `
min-height: ${props.full === 'true' ? `100%` : props.theme.tabs.minHeight};
`}
${props => (props.height ? `height: ${props.height};` : `max-height: 100vh;`)}
z-index: 101;
box-shadow: ${props => props.theme.navigation.mobile.sidenav.boxShadow};
background-color: ${props => props.theme.navigation.mobile.sidenav.background};
.focus-area {
height: 100%;
}
`;
/**
* Handle keyboard escape manually because we want to hide the navbar when key is pressed. Not only
* remove the focus trap.
*
* @event {SyntheticKeyboardEvent}
* The event called by the keydown.
*/
const handleKeyDown = (event, hideFn, onToggle) => {
switch (event.keyCode) {
case ESCAPE_KEY:
hideFn(onToggle);
break;
}
};
/**
* Will hide the sidenav by toggling isOpen state or calling onProps in case of a controlled
* element.
*/
const hide = onToggle => {
onToggle(false);
};
/**
* A component that can be toggle on and off on a position defined by the user via props. Can be used for
* sidebar navigation or mobile drop (show from bottom).
*/
const Drawer = ({ children, height, full = false, isOpen = false, position = 'left', onToggle, }) => {
const [activeTrap, setActiveTrap] = React__default.useState(false);
// When the isOpen prop gets changed make sure to set or unset
// mouse traps accordingly.
useEffect(() => {
if (isOpen) {
setActiveTrap(true);
}
else {
setActiveTrap(false);
}
}, [isOpen]);
const sidenav = (React__default.createElement(StyledSideNavBlock, { "data-testid": "sidenav", onKeyDown: e => handleKeyDown(e, hide, onToggle), variants: variants[position], initial: "closed", position: position, height: height, full: full === true ? 'true' : 'false', animate: isOpen ? 'open' : 'closed' }, activeTrap ? (React__default.createElement(FocusTrap, { className: "focus-area", focusTrapOptions: {
clickOutsideDeactivates: true,
escapeDeactivates: false,
onDeactivate: () => setActiveTrap(false),
} }, children)) : (false)));
return (React__default.createElement("div", { role: "navigation" },
sidenav,
isOpen && React__default.createElement(StyledOverlay, { "data-testid": "sidenav-overlay", isOpen: isOpen, onClick: e => hide(onToggle) })));
};
export { Drawer, StyledOverlay, StyledSideNavBlock };