Skip to content

Instantly share code, notes, and snippets.

@zebapy
Created July 31, 2020 15:05
Show Gist options
  • Select an option

  • Save zebapy/63b0a899ee7783e959480c7d587acc9c to your computer and use it in GitHub Desktop.

Select an option

Save zebapy/63b0a899ee7783e959480c7d587acc9c to your computer and use it in GitHub Desktop.
import React, { useState, useEffect, useRef } from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import styled, { keyframes } from 'styled-components';
import Router from 'next/router';
import { media } from 'components/style-utils';
import { Box } from 'components';
const fadeInDown = keyframes`
0% {
transform: translateY(-10px);
opacity: 0;
}
100% {
transform: none;
opacity: 1;
}
`;
const fadeInUp = keyframes`
0% {
transform: translateY(100%);
opacity: 0;
}
100% {
transform: none;
opacity: 1;
}
`;
const Menu = styled.div`
display: ${p => (p.isOpen ? 'block' : 'none')};
position: fixed;
bottom: 0;
right: 0;
width: 100%;
z-index: 10;
animation: ${fadeInUp} 0.2s linear;
${media.md`
position: absolute;
top: calc(100% + 10px);
width: auto;
animation: ${fadeInDown} .2s linear;
`};
`;
const Dropdown = ({ menu, children }) => {
const [isOpen, setOpen] = useState(false);
const dropdown = useRef();
const hide = () => {
setOpen(false);
};
const handleToggleClick = e => {
setOpen(s => !s);
};
const handleWindowClick = event => {
const node = findDOMNode(dropdown.current);
// https://github.com/Fauntleroy/react-simple-dropdown/blob/d42e408161e13cb846de58fada3784de66b3ebf0/src/components/Dropdown.jsx#L61
if (event.target !== node && !node.contains(event.target)) {
hide();
}
};
useEffect(() => {
window.addEventListener('click', handleWindowClick);
window.addEventListener('touchstart', handleWindowClick);
Router.events.on('routeChangeComplete', hide);
return () => {
window.removeEventListener('click', handleWindowClick);
window.removeEventListener('touchstart', handleWindowClick);
Router.events.off('routeChangeComplete', hide);
};
}, []);
return (
<Box position="relative" ref={dropdown}>
<Box
position="fixed"
top={0}
left={0}
display={[isOpen ? 'block' : 'none', null, 'none']}
bg="black"
opacity={0.5}
size="100%"
zIndex={1}
onClick={hide}
/>
{children({
toggle: handleToggleClick,
isOpen
})}
<Menu isOpen={isOpen}>{menu}</Menu>
</Box>
);
};
Dropdown.propTypes = {
menu: PropTypes.node.isRequired,
children: PropTypes.func.isRequired
};
export default Dropdown;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment