dhei/classic-tokens
@reggi/path-to-regexp
dependabot/npm_and_yarn/main/copy-to-clipboard-4.0.2
dependabot/npm_and_yarn/main/eslint-10.4.0
dependabot/npm_and_yarn/main/npmcli/eslint-config-7.0.0
dependabot/npm_and_yarn/main/proc-log-7.0.0
dependabot/npm_and_yarn/npm_and_yarn-826852524d
dependabot/npm_and_yarn/npm_and_yarn-ab9a7f4bc2
deprecate-totp-2fa
dhei/classic-tokens
gat-bypass-2fa-docs
jpg619/fix-accessibility-content-flow
jpg619/version-bump-tar-2
kartykp/gat-bypass-2fa-docs
kartykp/upgrade-path-to-regex
main
maitxn/version-bump-tar
patch-1
reggi/cache-based-on-version
reggi/dev-engines
reggi/fix-transform-prettier
reggi/overrides
update-search-sensitivity
| 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 |