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
80 aria-label="Menu"
81 aria-expanded={open}
82 onClick={() => setOpen(true)}
83 sx={{
84 ml: 3,
85 '&:focus-visible': {
86 outline: '2px solid',
87 outlineColor: '-webkit-focus-ring-color',
88 outlineOffset: '1px',
89 },
90 }}
91 >
92 <ThreeBarsIcon />
93 </Button>
94 <LightTheme as={Drawer} isOpen={open} onDismiss={() => setOpen(false)}>
95 <Box
96 sx={{
97 display: 'flex',
98 flexDirection: 'column',
99 height: '100%',
100 bg: 'canvas.backdrop',
101 overflow: 'auto',
102 }}
103 style={{WebkitOverflowScrolling: 'touch'}}
104 >
105 <Box
106 sx={{
107 display: 'flex',
108 flexDirection: 'column',
109 flex: '1 0 auto',
110 color: 'fg.default',
111 bg: 'canvas.default',
112 }}
113 >
114 <DarkTheme
115 sx={{
116 color: 'fg.default',
117 bg: 'canvas.default',
118 height: `${HEADER_HEIGHT}px`,
119 px: 3,
120 alignItems: 'center',
121 justifyContent: 'space-between',
122 display: 'flex',
123 }}
124 >
125 <SiteTitle />
126 <Button aria-label="Close" onClick={() => setOpen(false)}>
127 <XIcon />
128 </Button>
129 </DarkTheme>
130 <Box sx={{display: 'flex', flexDirection: 'column'}}>
131 <NavItems />
132 </Box>
133 </Box>
134 </Box>
135 </LightTheme>
136 </>
137 )
138 }
139
140 export default NavDrawer