Add top nav links to nav drawer
Luke Karrys committed
Oct 16, 2023 at 16:20 UTC
b336b1b7de54f0675efbdc0ba3e12a208ba46345
6 files changed
+90
-88
content/nav.yml
+2
-2
@@ -276,8 +276,8 @@
276
url: /policies/security
277
- title: Replication and web crawler policy
278
url: /policies/crawlers
279
-- title: Threats and Mitigations
280
- shortName: threats and mitigations
279
+- title: Threats and mitigations
280
+ shortName: Threats and mitigations
281
url: /threats-and-mitigations
282
- title: npm CLI
283
shortName: CLI
src/components/header.js
+56
-54
@@ -1,5 +1,5 @@
1
import React from 'react'
2
-import {Box, Link} from '@primer/react'
2
+import {Box, Link, ThemeProvider} from '@primer/react'
3
import {Link as GatsbyLink} from 'gatsby'
4
import styled from 'styled-components'
5
import MobileSearch from './mobile-search'
@@ -15,18 +15,20 @@ const NpmHeaderBar = styled(Box)`
15
background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
16
`
17
18
-const NpmLogo = ({size, style}) => (
19
- <svg
20
- height={size}
21
- width={size}
22
- viewBox="0 0 700 700"
23
- fill="currentColor"
24
- style={{color: NPM_RED, ...style}}
25
- aria-hidden="true"
26
- >
27
- <polygon fill={NPM_RED} points="0,700 700,700 700,0 0,0" />
28
- <polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
29
- </svg>
18
+const NpmLogo = ({size, ...props}) => (
19
+ <Box {...props} role="banner">
20
+ <svg
21
+ height={size}
22
+ width={size}
23
+ viewBox="0 0 700 700"
24
+ fill="currentColor"
25
+ style={{color: NPM_RED}}
26
+ aria-hidden="true"
27
+ >
28
+ <polygon fill={NPM_RED} points="0,700 700,700 700,0 0,0" />
29
+ <polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
30
+ </svg>
31
+ </Box>
32
)
33
34
function Header() {
@@ -34,57 +36,57 @@ function Header() {
36
const search = useSearch()
37
38
return (
37
- <Box sx={{top: 0, position: 'sticky', zIndex: 1}} role="banner">
38
- <NpmHeaderBar />
39
- <Box
40
- as="header"
41
- sx={{
42
- display: 'flex',
43
- height: HEADER_HEIGHT - HEADER_BAR,
44
- px: [3, null, null, 4],
45
- alignItems: 'center',
46
- justifyContent: 'space-between',
47
- bg: 'canvas.default',
48
- border: '1px solid',
49
- borderColor: 'border.muted',
50
- }}
51
- >
52
- <Box sx={{display: 'flex', alignItems: 'center'}}>
53
- <Link
54
- as={GatsbyLink}
55
- to="/"
56
- sx={{
57
- mr: 4,
58
- fontWeight: 'bold',
59
- color: 'fg.default',
60
- display: 'flex',
61
- alignItems: 'center',
62
- }}
63
- >
64
- <NpmLogo size="32" sx={{mr: '16px'}} />
65
- {siteMetadata.title}
66
- </Link>
67
- <Box sx={{display: ['none', null, null, 'block'], ml: 4}}>
68
- <Search {...search} />
39
+ <ThemeProvider colorMode="night" nightScheme="dark_dimmed">
40
+ <Box sx={{top: 0, position: 'sticky', zIndex: 1}}>
41
+ <NpmHeaderBar />
42
+ <Box
43
+ as="header"
44
+ sx={{
45
+ display: 'flex',
46
+ height: HEADER_HEIGHT - HEADER_BAR,
47
+ px: [3, null, null, 4],
48
+ alignItems: 'center',
49
+ justifyContent: 'space-between',
50
+ bg: 'canvas.default',
51
+ border: '1px solid',
52
+ borderColor: 'border.muted',
53
+ }}
54
+ >
55
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
56
+ <Link
57
+ as={GatsbyLink}
58
+ to="/"
59
+ sx={{
60
+ mr: 4,
61
+ fontWeight: 'bold',
62
+ color: 'fg.default',
63
+ display: 'flex',
64
+ alignItems: 'center',
65
+ }}
66
+ >
67
+ <NpmLogo size="32" sx={{mr: '16px'}} />
68
+ {siteMetadata.title}
69
+ </Link>
70
+ <Box sx={{display: ['none', null, null, 'block'], ml: 4}}>
71
+ <Search {...search} />
72
+ </Box>
73
</Box>
70
- </Box>
71
- <Box sx={{display: 'flex'}}>
72
- <Box sx={{display: ['none', null, null, 'block']}}>
73
- <Box sx={{display: 'flex', alignItems: 'center', color: 'gray.2'}}>
74
+ <Box sx={{display: 'flex'}}>
75
+ <Box sx={{display: ['none', null, null, 'flex'], alignItems: 'center'}}>
76
{headerNavItems.map((item, index) => (
77
<Link key={index} href={item.url} sx={{display: 'block', ml: 4}}>
78
{item.title}
79
</Link>
80
))}
81
</Box>
80
- </Box>
81
- <Box sx={{display: ['flex', null, null, 'none']}}>
82
- <MobileSearch {...search} />
83
- <NavDrawer />
82
+ <Box sx={{display: ['flex', null, null, 'none']}}>
83
+ <MobileSearch {...search} />
84
+ <NavDrawer />
85
+ </Box>
86
</Box>
87
</Box>
88
</Box>
87
- </Box>
89
+ </ThemeProvider>
90
)
91
}
92
src/components/mobile-search.js
+13
-2
@@ -6,6 +6,7 @@ import {FocusOn} from 'react-focus-on'
6
import TextInput from './text-input'
7
import SearchResults from './search-results'
8
import useSiteMetadata from '../hooks/use-site-metadata'
9
+import {HEADER_BAR, HEADER_HEIGHT} from '../constants'
10
11
function MobileSearch({onDismiss, ...props}) {
12
const siteMetadata = useSiteMetadata()
@@ -21,7 +22,7 @@ function MobileSearch({onDismiss, ...props}) {
22
<Box
23
sx={{
24
position: 'fixed',
24
- top: '10px', // TODO: use constant
25
+ top: `${HEADER_BAR}px`,
26
left: 0,
27
right: 0,
28
bottom: 0,
@@ -45,7 +46,17 @@ function MobileSearch({onDismiss, ...props}) {
46
onClick={handleDismiss}
47
/>
48
<Box sx={{display: 'flex', flexDirection: 'column', height: isOpen ? '100%' : 'auto'}}>
48
- <Box sx={{display: 'flex', bg: 'canvas.default', color: 'fg.default', p: 3, flex: '0 0 auto'}}>
49
+ <Box
50
+ sx={{
51
+ display: 'flex',
52
+ bg: 'canvas.default',
53
+ color: 'fg.default',
54
+ height: `${HEADER_HEIGHT - HEADER_BAR}px`,
55
+ flex: '0 0 auto',
56
+ px: 3,
57
+ alignItems: 'center',
58
+ }}
59
+ >
60
<motion.div
61
initial={{scaleX: 0.1}}
62
animate={{scaleX: 1}}
src/components/nav-drawer.js
-23
@@ -6,7 +6,6 @@ import Drawer from './drawer'
6
import NavItems from './nav-items'
7
import useSiteMetadata from '../hooks/use-site-metadata'
8
import {useIsMobile} from '../hooks/use-breakpoint'
9
-import headerNavItems from '../../content/header-nav.yml'
9
10
const useDrawerIsOpen = () => {
11
const isMobile = useIsMobile()
@@ -77,28 +76,6 @@ function NavDrawer() {
76
<NavItems />
77
</Box>
78
</Box>
80
- <Box
81
- sx={{flexDirection: 'column', flex: '1 0 auto', color: 'fg.default', bg: 'canvas.default', display: 'flex'}}
82
- >
83
- {headerNavItems.map((item, index) => (
84
- <Box
85
- key={item.title}
86
- sx={{
87
- borderWidth: 0,
88
- borderRadius: 0,
89
- borderTopWidth: index !== 0 ? 1 : 0,
90
- borderColor: 'border.muted',
91
- px: 4,
92
- py: 3,
93
- borderStyle: 'solid',
94
- }}
95
- >
96
- <Link key={index} href={item.url} sx={{color: 'inherit', display: 'block'}}>
97
- {item.title}
98
- </Link>
99
- </Box>
100
- ))}
101
- </Box>
79
</Box>
80
</Drawer>
81
</>
src/components/nav-items.js
+19
-6
@@ -5,6 +5,7 @@ import {LinkExternalIcon} from '@primer/octicons-react'
5
import * as getNav from '../util/get-nav'
6
import {useLocation, usePageContext} from '../layout'
7
import VisuallyHidden from './visually-hidden'
8
+import headerNavItems from '../../content/header-nav.yml'
9
10
const NavItem = ({item, path}) => {
11
const href = getNav.getLocation(item.url)
@@ -31,6 +32,15 @@ const NavItems = ({items, path}) => (
32
</>
33
)
34
35
+const ExternalNavItem = ({title, href, ...props}) => (
36
+ <NavList.Item {...props}>
37
+ {title}
38
+ <NavList.TrailingVisual>
39
+ <LinkExternalIcon />
40
+ </NavList.TrailingVisual>
41
+ </NavList.Item>
42
+)
43
+
44
const Navigation = () => {
45
const location = useLocation()
46
const {repositoryUrl} = usePageContext()
@@ -45,12 +55,15 @@ const Navigation = () => {
55
<NavList aria-label="Site">
56
<NavItems items={items} path={path} />
57
<NavList.Divider />
48
- <NavList.Item href={repositoryUrl}>
49
- GitHub
50
- <NavList.TrailingVisual>
51
- <LinkExternalIcon />
52
- </NavList.TrailingVisual>
53
- </NavList.Item>
58
+ {headerNavItems.map(item => (
59
+ <ExternalNavItem
60
+ key={item.title}
61
+ title={item.title}
62
+ href={item.url}
63
+ sx={{display: ['flex', null, null, 'none']}}
64
+ />
65
+ ))}
66
+ <ExternalNavItem title="GitHub" href={repositoryUrl} />
67
</NavList>
68
</>
69
)
src/components/sidebar.js
-1
@@ -43,7 +43,6 @@ const Sidebar = () => (
43
sx={{
44
borderWidth: 0,
45
borderRightWidth: 1,
46
- borderRadius: 0,
46
height: '100%',
47
borderStyle: 'solid',
48
borderColor: 'border.subtle',