All files / src/components nav-drawer.js

0% Statements 0/20
0% Branches 0/16
0% Functions 0/9
0% Lines 0/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154                                                                                                                                                                                                                                                                                                                   
import {BorderBox, Flex, Link, Text} from '@primer/components'
import {ChevronDownIcon, ChevronUpIcon, XIcon} from '@primer/octicons-react'
import {Link as GatsbyLink} from 'gatsby'
import debounce from 'lodash.debounce'
import React from 'react'
import navItems from '../nav.yml'
import primerNavItems from '../primer-nav.yml'
import useSiteMetadata from '../use-site-metadata'
import DarkButton from './dark-button'
import Details from './details'
import Drawer from './drawer'
import NavItems from './nav-items'
 
export function useNavDrawerState(breakpoint) {
  // Handle string values from themes with units at the end
  if (typeof breakpoint === 'string') {
    breakpoint = parseInt(breakpoint, 10)
  }
  const [isOpen, setOpen] = React.useState(false)
 
  const onResize = React.useCallback(() => {
    if (window.innerWidth >= breakpoint) {
      setOpen(false)
    }
  }, [setOpen])
 
  const debouncedOnResize = React.useCallback(debounce(onResize, 250), [
    onResize,
  ])
 
  React.useEffect(() => {
    if (isOpen) {
      window.addEventListener('resize', debouncedOnResize)
      return () => {
        // cancel any debounced invocation of the resize handler
        debouncedOnResize.cancel()
        window.removeEventListener('resize', debouncedOnResize)
      }
    }
  }, [isOpen, debouncedOnResize])
 
  return [isOpen, setOpen]
}
 
function NavDrawer({isOpen, onDismiss}) {
  const siteMetadata = useSiteMetadata()
  return (
    <Drawer isOpen={isOpen} onDismiss={onDismiss}>
      <Flex
        flexDirection="column"
        height="100%"
        bg="gray.0"
        style={{overflow: 'auto', WebkitOverflowScrolling: 'touch'}}
      >
        <Flex flexDirection="column" flex="1 0 auto" color="gray.7" bg="gray.0">
          <BorderBox
            borderWidth={0}
            borderRadius={0}
            borderBottomWidth={1}
            borderColor="gray.7"
          >
            <Flex
              py={3}
              pl={4}
              pr={3}
              alignItems="center"
              justifyContent="space-between"
              color="gray.1"
              bg="gray.9"
            >
              <Link
                as={GatsbyLink}
                to="/"
                display="inline-block"
                color="inherit"
              >
                {siteMetadata.title}
              </Link>
              <DarkButton aria-label="Close" onClick={onDismiss}>
                <XIcon />
              </DarkButton>
            </Flex>
          </BorderBox>
          {navItems.length > 0 ? (
            <Flex flexDirection="column">
              <NavItems items={navItems} editOnGitHub={false} />
            </Flex>
          ) : null}
        </Flex>
        {primerNavItems.length > 0 ? (
          <Flex
            flexDirection="column"
            flex="1 0 auto"
            color="gray.1"
            bg="gray.9"
          >
            <PrimerNavItems items={primerNavItems} />
          </Flex>
        ) : null}
      </Flex>
    </Drawer>
  )
}
 
function PrimerNavItems({items}) {
  return items.map((item, index) => {
    return (
      <BorderBox
        key={item.title}
        borderWidth={0}
        borderRadius={0}
        borderTopWidth={index !== 0 ? 1 : 0}
        borderColor="gray.7"
        p={4}
      >
        {item.children ? (
          <Details key={index}>
            {({open, toggle}) => (
              <>
                <summary onClick={toggle} style={{cursor: 'pointer'}}>
                  <Flex alignItems="center" justifyContent="space-between">
                    <Text>{item.title}</Text>
                    {open ? <ChevronUpIcon /> : <ChevronDownIcon />}
                  </Flex>
                </summary>
                <Flex flexDirection="column" mt={2}>
                  {item.children.map((child) => (
                    <Link
                      key={child.title}
                      href={child.url}
                      py={1}
                      mt={2}
                      fontSize={1}
                      color="inherit"
                    >
                      {child.title}
                    </Link>
                  ))}
                </Flex>
              </>
            )}
          </Details>
        ) : (
          <Link key={index} href={item.url} color="inherit" display="block">
            {item.title}
          </Link>
        )}
      </BorderBox>
    )
  })
}
 
export default NavDrawer