1 import React from 'react'
2 import {Button, Box} from '@primer/react'
3 import {XIcon, ThreeBarsIcon} from '@primer/octicons-react'
4 import NavItems from './nav-items'
5 import {useIsMobile} from '../hooks/use-breakpoint'
6 import {DarkTheme, LightTheme} from '../theme'
7 import {AnimatePresence, motion} from 'framer-motion'
8 import {FocusOn} from 'react-focus-on'
9 import {HEADER_BAR, HEADER_HEIGHT} from '../constants'
10 import SiteTitle from './site-title'
11
12 const Drawer = ({isOpen, onDismiss, children}) => (
13 <AnimatePresence>
14 {isOpen ? (
15 // These event handlers fix a bug that caused links below the fold
16 // to be unclickable in macOS Safari.
17 // Reference: https://github.com/theKashey/react-focus-lock/issues/79
18 <Box
19 onMouseDown={event => event.preventDefault()}
20 onKeyDown={event => event.target.focus()}
21 onClick={event => event.target.focus()}
22 role="button"
23 tabIndex="0"
24 >
25 <FocusOn returnFocus={true} onEscapeKey={onDismiss}>
26 <Box
27 sx={{
28 position: 'fixed',
29 top: 0,
30 right: 0,
31 bottom: 0,
32 left: 0,
33 bg: 'overlay.backdrop',
34 }}
35 key="overlay"
36 as={motion.div}
37 initial={{opacity: 0}}
38 animate={{opacity: 1}}
39 exit={{opacity: 0}}
40 transition={{type: 'tween'}}
41 onClick={onDismiss}
42 />
43 <Box
44 sx={{
45 position: 'fixed',
46 top: `${HEADER_BAR}px`,
47 right: 0,
48 bottom: 0,
49 width: 300,
50 zIndex: 1,
51 }}
52 key="drawer"
53 as={motion.div}
54 initial={{x: '100%'}}
55 animate={{x: 0}}
56 exit={{x: '100%'}}
57 transition={{type: 'tween', duration: 0.2}}
58 >
59 {children}
60 </Box>
61 </FocusOn>
62 </Box>
63 ) : null}
64 </AnimatePresence>
65 )
66
67 function NavDrawer() {
68 const isMobile = useIsMobile()
69 const [open, setOpen] = React.useState(false)
70
71 React.useEffect(() => {
72 if (!isMobile && open) {
73 setOpen(false)
74 }
75 }, [isMobile, open])
76
77 return (
78 <>
79 <Button aria-label="Menu" aria-expanded={open} onClick={() => setOpen(true)} sx={{ml: 3}}>
80 <ThreeBarsIcon />
81 </Button>
82 <LightTheme as={Drawer} isOpen={open} onDismiss={() => setOpen(false)}>
83 <Box
84 sx={{
85 display: 'flex',
86 flexDirection: 'column',
87 height: '100%',
88 bg: 'canvas.backdrop',
89 overflow: 'auto',
90 }}
91 style={{WebkitOverflowScrolling: 'touch'}}
92 >
93 <Box
94 sx={{
95 display: 'flex',
96 flexDirection: 'column',
97 flex: '1 0 auto',
98 color: 'fg.default',
99 bg: 'canvas.default',
100 }}
101 >
102 <DarkTheme
103 sx={{
104 color: 'fg.default',
105 bg: 'canvas.default',
106 height: `${HEADER_HEIGHT}px`,
107 px: 3,
108 alignItems: 'center',
109 justifyContent: 'space-between',
110 display: 'flex',
111 }}
112 >
113 <SiteTitle />
114 <Button aria-label="Close" onClick={() => setOpen(false)}>
115 <XIcon />
116 </Button>
117 </DarkTheme>
118 <Box sx={{display: 'flex', flexDirection: 'column'}}>
119 <NavItems />
120 </Box>
121 </Box>
122 </Box>
123 </LightTheme>
124 </>
125 )
126 }
127
128 export default NavDrawer