Style updates and misc fixes

Other fixes: - disable scroll behavior for cli version selections - close mobile search after successful navigation

Luke Karrys committed Oct 23, 2023 at 15:55 UTC 53dbeda756cc5ec1dcd458b683386b3a55c92656
18 files changed +244 -200
.eslintrc.js
+5 -3
@@ -46,7 +46,7 @@ module.exports = {
46 },
47 },
48 {
49 - files: ['*.mdx', 'shared.js'],
49 + files: ['*.mdx', 'shared.js', 'src/**/*.js'],
50 rules: {
51 'react/forbid-elements': [
52 'error',
@@ -109,7 +109,8 @@ module.exports = {
109 'header',
110 'hgroup',
111 'hr',
112 - 'html',
112 + // used in head
113 + // 'html',
114 'i',
115 'input',
116 'ins',
@@ -170,7 +171,8 @@ module.exports = {
171 'th',
172 'thead',
173 'time',
173 - 'title',
174 + // used in head
175 + // 'title',
176 'tr',
177 'track',
178 'tt',
gatsby-browser.js
+5
@@ -1,2 +1,7 @@
1 export {default as wrapPageElement} from './src/page'
2 export {default as wrapRootElement} from './src/root'
3 +
4 +export const shouldUpdateScroll = ({routerProps}) => {
5 + const {scrollUpdate = true} = routerProps.location.state ?? {}
6 + return scrollUpdate
7 +}
src/components/container.js deleted
-6
@@ -1,6 +0,0 @@
1 -import {Box} from '@primer/react'
2 -import React from 'react'
3 -
4 -const Container = ({children}) => <Box sx={{width: '100%', maxWidth: 960, p: 5, mx: 'auto'}}>{children}</Box>
5 -
6 -export default Container
src/components/drawer.js deleted
-61
@@ -1,61 +0,0 @@
1 -import React from 'react'
2 -import {Box} from '@primer/react'
3 -import {AnimatePresence, motion} from 'framer-motion'
4 -import {FocusOn} from 'react-focus-on'
5 -
6 -const Drawer = ({isOpen, onDismiss, children}) => (
7 - <AnimatePresence>
8 - {isOpen ? (
9 - // These event handlers fix a bug that caused links below the fold
10 - // to be unclickable in macOS Safari.
11 - // Reference: https://github.com/theKashey/react-focus-lock/issues/79
12 - <div
13 - onMouseDown={event => event.preventDefault()}
14 - onKeyDown={event => event.target.focus()}
15 - onClick={event => event.target.focus()}
16 - role="button"
17 - tabIndex="0"
18 - >
19 - <FocusOn returnFocus={true} onEscapeKey={onDismiss}>
20 - <Box
21 - sx={{
22 - position: 'fixed',
23 - top: 0,
24 - right: 0,
25 - bottom: 0,
26 - left: 0,
27 - bg: 'overlay.backdrop',
28 - }}
29 - key="overlay"
30 - as={motion.div}
31 - initial={{opacity: 0}}
32 - animate={{opacity: 1}}
33 - exit={{opacity: 0}}
34 - transition={{type: 'tween'}}
35 - onClick={onDismiss}
36 - />
37 - <Box
38 - sx={{
39 - position: 'fixed',
40 - top: 0,
41 - right: 0,
42 - bottom: 0,
43 - width: 300,
44 - zIndex: 1,
45 - }}
46 - key="drawer"
47 - as={motion.div}
48 - initial={{x: '100%'}}
49 - animate={{x: 0}}
50 - exit={{x: '100%'}}
51 - transition={{type: 'tween', duration: 0.2}}
52 - >
53 - {children}
54 - </Box>
55 - </FocusOn>
56 - </div>
57 - ) : null}
58 - </AnimatePresence>
59 -)
60 -
61 -export default Drawer
src/components/header.js
+3 -25
@@ -6,26 +6,16 @@ import NavDrawer from './nav-drawer'
6 import Link from './link'
7 import useSearch from '../hooks/use-search'
8 import {HEADER_HEIGHT, HEADER_BAR} from '../constants'
9 -import useSiteMetadata from '../hooks/use-site-metadata'
9 import headerNavItems from '../../content/header-nav.yml'
10 import {DarkTheme} from '../theme'
11 +import SiteTitle from './site-title'
12
13 const NpmHeaderBar = styled(Box)`
14 height: ${HEADER_BAR}px;
15 background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
16 `
17
18 -const NpmLogo = ({size, sx}) => (
19 - <Box sx={{...sx, color: 'logoBg'}} role="banner">
20 - <svg height={size} width={size} viewBox="0 0 700 700" fill="currentColor" aria-hidden="true">
21 - <polygon fill="currentColor" points="0,700 700,700 700,0 0,0" />
22 - <polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
23 - </svg>
24 - </Box>
25 -)
26 -
18 function Header() {
28 - const siteMetadata = useSiteMetadata()
19 const search = useSearch()
20
21 return (
@@ -35,7 +25,7 @@ function Header() {
25 as="header"
26 sx={{
27 display: 'flex',
38 - height: HEADER_HEIGHT,
28 + height: `${HEADER_HEIGHT}px`,
29 px: [3, null, null, 4],
30 alignItems: 'center',
31 justifyContent: 'space-between',
@@ -47,19 +37,7 @@ function Header() {
37 }}
38 >
39 <Box sx={{display: 'flex', alignItems: 'center'}}>
50 - <Link
51 - to="/"
52 - sx={{
53 - mr: 4,
54 - fontWeight: 'bold',
55 - color: 'fg.default',
56 - display: 'flex',
57 - alignItems: 'center',
58 - }}
59 - >
60 - <NpmLogo size="32" sx={{display: 'flex', mr: 3}} />
61 - {siteMetadata.title}
62 - </Link>
40 + <SiteTitle logo={true} sx={{mr: 4}} />
41 <Box sx={{display: ['none', null, null, 'block'], ml: 4}}>
42 <Search.Desktop {...search} />
43 </Box>
src/components/link.js
+12 -5
@@ -2,6 +2,16 @@ import React from 'react'
2 import {Link as PrimerLink} from '@primer/react'
3 import {Link as GatsbyLink} from 'gatsby'
4
5 +const omit = (obj, ...keys) => {
6 + const res = {}
7 + for (const k of Object.keys(obj)) {
8 + if (!keys.includes(k)) {
9 + res[k] = obj[k]
10 + }
11 + }
12 + return res
13 +}
14 +
15 const FALLBACK = `http://_${Math.random().toString().slice(2)}._${Math.random().toString().slice(2)}`
16
17 const getLocalPath = href => {
@@ -21,11 +31,8 @@ const getLocalPath = href => {
31 return null
32 }
33
24 -const GatsbyLinkWithoutSxProps = React.forwardRef(function GatsbyLinkWithoutSxProps(
25 - {sx, underline, hoverColor, muted, ...props},
26 - ref,
27 -) {
28 - return <GatsbyLink ref={ref} {...props} />
34 +const GatsbyLinkWithoutSxProps = React.forwardRef(function GatsbyLinkWithoutSxProps(props, ref) {
35 + return <GatsbyLink ref={ref} {...omit(props, 'sx', 'underline', 'hoverColor', 'muted')} />
36 })
37
38 const Link = React.forwardRef(function Link({to, href, ...props}, ref) {
src/components/nav-drawer.js
+75 -41
@@ -1,38 +1,85 @@
1 import React from 'react'
2 import {Button, Box} from '@primer/react'
3 import {XIcon, ThreeBarsIcon} from '@primer/octicons-react'
4 -import Link from './link'
5 -import Drawer from './drawer'
4 import NavItems from './nav-items'
7 -import useSiteMetadata from '../hooks/use-site-metadata'
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
11 -const useDrawerIsOpen = () => {
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()
13 - const [isOpen, setIsOpen] = React.useState(false)
14 - const setOpen = React.useCallback(() => setIsOpen(true), [])
15 - const setClose = React.useCallback(() => setIsOpen(false), [])
69 + const [open, setOpen] = React.useState(false)
70
71 React.useEffect(() => {
18 - if (!isMobile && isOpen) {
19 - setIsOpen(false)
72 + if (!isMobile && open) {
73 + setOpen(false)
74 }
21 - }, [isMobile, isOpen])
22 -
23 - return [isOpen, {setOpen, setClose}]
24 -}
25 -
26 -function NavDrawer() {
27 - const siteMetadata = useSiteMetadata()
28 - const [isOpen, {setOpen, setClose}] = useDrawerIsOpen()
75 + }, [isMobile, open])
76
77 return (
78 <>
32 - <Button aria-label="Menu" aria-expanded={isOpen} onClick={setOpen} sx={{ml: 3}}>
79 + <Button aria-label="Menu" aria-expanded={open} onClick={() => setOpen(true)} sx={{ml: 3}}>
80 <ThreeBarsIcon />
81 </Button>
35 - <LightTheme as={Drawer} isOpen={isOpen} onDismiss={setClose}>
82 + <LightTheme as={Drawer} isOpen={open} onDismiss={() => setOpen(false)}>
83 <Box
84 sx={{
85 display: 'flex',
@@ -54,32 +101,19 @@ function NavDrawer() {
101 >
102 <DarkTheme
103 sx={{
57 - borderWidth: 0,
58 - borderRadius: 0,
59 - borderBottomWidth: 1,
60 - borderColor: 'border.muted',
61 - borderStyle: 'solid',
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 >
66 - <Box
67 - sx={{
68 - py: 3,
69 - pl: 4,
70 - pr: 3,
71 - alignItems: 'center',
72 - justifyContent: 'space-between',
73 - display: 'flex',
74 - }}
75 - >
76 - <Link to="/" sx={{fontSize: 2, color: 'fg.default'}}>
77 - {siteMetadata.title}
78 - </Link>
79 - <Button aria-label="Close" onClick={setClose}>
80 - <XIcon />
81 - </Button>
82 - </Box>
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 />
src/components/nav-items.js
+1 -3
@@ -59,9 +59,7 @@ const Navigation = () => {
59
60 return (
61 <>
62 - <VisuallyHidden>
63 - <h3>Site navigation</h3>
64 - </VisuallyHidden>
62 + <VisuallyHidden as="h3">Site navigation</VisuallyHidden>
63 <NavList aria-label="Site">
64 <NavItems items={items} path={pathname} />
65 <NavList.Divider />
src/components/page-footer.js
+2 -2
@@ -29,7 +29,7 @@ const Contributors = ({contributors = [], latestCommit}) => {
29 }
30
31 return (
32 - <div>
32 + <>
33 <Box sx={{display: 'flex', alignItems: 'center'}}>
34 <Text sx={{mr: 2}}>
35 {contributors.length} {pluralize('contributor', contributors.length)}
@@ -48,7 +48,7 @@ const Contributors = ({contributors = [], latestCommit}) => {
48 <Link href={latestCommit.url}>{format(new Date(latestCommit.date))}</Link>
49 </Text>
50 ) : null}
51 - </div>
51 + </>
52 )
53 }
54
src/components/search-results.js
+8 -12
@@ -26,17 +26,17 @@ const SearchItem = ({item}) => {
26 )
27 }
28
29 +const Result = React.forwardRef(function Result({sx, ...props}, ref) {
30 + return <Box ref={ref} sx={{px: 3, py: 2, color: 'fg.default', fontSize: 1, ...sx}} {...props} />
31 +})
32 +
33 function SearchResults({results, getItemProps, highlightedIndex}) {
30 - if (results.length === 0) {
31 - return (
32 - <Text as="div" sx={{px: 3, py: 2, color: 'fg.default', fontSize: 1}}>
33 - No results
34 - </Text>
35 - )
34 + if (!results || results.length === 0) {
35 + return <Result>No results</Result>
36 }
37
38 return results.map((item, index) => (
39 - <Box
39 + <Result
40 {...getItemProps({item, index})}
41 as={LinkNoUnderline}
42 to={item.path}
@@ -45,15 +45,11 @@ function SearchResults({results, getItemProps, highlightedIndex}) {
45 display: 'flex',
46 flexDirection: 'column',
47 flex: '0 0 auto',
48 - px: 3,
49 - py: 2,
50 - color: 'fg.default',
51 - fontSize: 1,
48 bg: highlightedIndex === index ? 'neutral.muted' : 'transparent',
49 }}
50 >
51 <SearchItem item={item} />
56 - </Box>
52 + </Result>
53 ))
54 }
55
src/components/search.js
+17 -2
@@ -8,6 +8,7 @@ import SearchResults from './search-results'
8 import useSiteMetadata from '../hooks/use-site-metadata'
9 import {HEADER_BAR, HEADER_HEIGHT} from '../constants'
10 import {LightTheme} from '../theme'
11 +import useLocationChange from '../hooks/use-location-change'
12
13 export const Desktop = props => {
14 const siteMetadata = useSiteMetadata()
@@ -44,10 +45,24 @@ export const Desktop = props => {
45 )
46 }
47
47 -export const Mobile = props => {
48 +export const Mobile = ({
49 + reset,
50 + results,
51 + isOpen: resultsOpen,
52 + getInputProps,
53 + getItemProps,
54 + getMenuProps,
55 + highlightedIndex,
56 +}) => {
57 const [open, setOpen] = React.useState(false)
58 const siteMetadata = useSiteMetadata()
50 - const {reset, results, isOpen: resultsOpen, getInputProps, getItemProps, getMenuProps, highlightedIndex} = props
59 + const locationChange = useLocationChange()
60 +
61 + React.useEffect(() => {
62 + if (locationChange.change) {
63 + setOpen(false)
64 + }
65 + }, [locationChange])
66
67 // Fixes focus behavior on iOS where the input gets focus styles but not the
68 // actual focus after animating open.
src/components/site-title.js new
+36
@@ -0,0 +1,36 @@
1 +import React from 'react'
2 +import {Box} from '@primer/react'
3 +import Link from './link'
4 +import useSiteMetadata from '../hooks/use-site-metadata'
5 +
6 +const NpmLogo = ({size, sx}) => (
7 + <Box sx={{...sx, color: 'logoBg'}} role="banner">
8 + <svg height={size} width={size} viewBox="0 0 700 700" fill="currentColor" aria-hidden="true">
9 + <polygon fill="currentColor" points="0,700 700,700 700,0 0,0" />
10 + <polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
11 + </svg>
12 + </Box>
13 +)
14 +
15 +const SiteTitle = ({logo, sx}) => {
16 + const siteMetadata = useSiteMetadata()
17 +
18 + return (
19 + <Link
20 + to="/"
21 + sx={{
22 + fontWeight: 'bold',
23 + fontSize: 2,
24 + color: 'fg.default',
25 + display: 'flex',
26 + alignItems: 'center',
27 + ...sx,
28 + }}
29 + >
30 + {logo ? <NpmLogo size="32" sx={{display: 'flex', mr: 3}} /> : null}
31 + {siteMetadata.title}
32 + </Link>
33 + )
34 +}
35 +
36 +export default SiteTitle
src/components/table-of-contents.js
+25 -6
@@ -18,8 +18,8 @@ const TableOfContentsItems = ({items, depth}) => (
18 </>
19 )
20
21 -const TableOfContents = ({'aria-labelledby': ariaLabelledBy, items, depth = 1}) => (
22 - <NavList {...(depth === 1 ? {'aria-labelledby': ariaLabelledBy, sx: {ml: -2}} : {})}>
21 +const TableOfContents = ({'aria-labelledby': ariaLabelledBy, items, depth = 1, ...props}) => (
22 + <NavList aria-labelledby={ariaLabelledBy} {...props}>
23 <TableOfContentsItems items={items} depth={depth} />
24 </NavList>
25 )
@@ -35,9 +35,28 @@ const withTableOfContents = Component => {
35 export const Mobile = withTableOfContents(({items}) => {
36 const {getDetailsProps, open} = useDetails({defaultOpen: true})
37 return (
38 - <Box sx={{display: ['block', null, 'none'], mb: 3}}>
39 - <Details {...getDetailsProps()}>
40 - <Button as="summary" sx={{display: 'inline-flex'}} leadingIcon={open ? ChevronDownIcon : ChevronRightIcon}>
38 + <Box sx={{display: ['block', null, 'none'], mb: 3, mt: 4}}>
39 + <Details
40 + {...getDetailsProps()}
41 + sx={{
42 + borderStyle: 'solid',
43 + borderWidth: 1,
44 + borderColor: 'border.muted',
45 + borderRadius: 2,
46 + }}
47 + >
48 + <Button
49 + as="summary"
50 + sx={{
51 + borderTopWidth: 0,
52 + borderLeftWidth: 0,
53 + borderRightWidth: 0,
54 + borderBottomWidth: open ? 1 : 0,
55 + borderBottomLeftRadius: open ? 0 : 2,
56 + borderBottomRightRadius: open ? 0 : 2,
57 + }}
58 + leadingIcon={open ? ChevronDownIcon : ChevronRightIcon}
59 + >
60 Table of contents
61 </Button>
62 <TableOfContents items={items} />
@@ -68,7 +87,7 @@ export const Desktop = withTableOfContents(({items}) => (
87 overflowY: 'scroll',
88 }}
89 >
71 - <TableOfContents aria-labelledby="toc-heading" items={items} />
90 + <TableOfContents aria-labelledby="toc-heading" items={items} sx={{ml: -2}} />
91 </Box>
92 </Box>
93 ))
src/components/variant-select.js
+13 -19
@@ -3,38 +3,30 @@ import {ActionList, ActionMenu, Box} from '@primer/react'
3 import * as getNav from '../util/get-nav'
4 import usePage from '../hooks/use-page'
5 import {LinkNoUnderline} from './link'
6 +import useLocationChange from '../hooks/use-location-change'
7
8 const VariantItem = ({title, shortName, url, active}) => (
8 - <ActionList.Item as={LinkNoUnderline} to={url} id={shortName} active={active}>
9 + <ActionList.Item as={LinkNoUnderline} to={url} state={{scrollUpdate: false}} id={shortName} active={active}>
10 {title}
11 </ActionList.Item>
12 )
13
13 -const useVariantFocus = path => {
14 +const useVariantFocus = () => {
15 + const locationChange = useLocationChange()
16 const anchorRef = React.useRef(null)
15 - const pathRef = React.useRef(null)
17
18 React.useEffect(() => {
18 - const previousPath = pathRef.current
19 - pathRef.current = path
20 -
21 - if (getNav.didVariantChange(previousPath, path)) {
22 - const anchor = anchorRef.current
23 - const onBlur = () => {
24 - anchor.removeEventListener('blur', onBlur)
25 - anchor.focus()
26 - }
27 - anchor.addEventListener('blur', onBlur)
28 - return () => anchor.removeEventListener('blur', onBlur)
19 + if (locationChange.change && getNav.didVariantChange(locationChange.previous, locationChange.current)) {
20 + anchorRef.current.focus()
21 }
30 - }, [path])
22 + }, [locationChange])
23
24 return anchorRef
25 }
26
35 -const VariantMenu = ({title, latest, current, prerelease, legacy, path}) => {
27 +const VariantMenu = ({title, latest, current, prerelease, legacy}) => {
28 const [open, setOpen] = React.useState(false)
37 - const anchorRef = useVariantFocus(path)
29 + const anchorRef = useVariantFocus()
30 const labelId = 'label-versions-list-item'
31
32 return (
@@ -43,7 +35,9 @@ const VariantMenu = ({title, latest, current, prerelease, legacy, path}) => {
35 Select CLI Version:
36 </Box>
37 <ActionMenu anchorRef={anchorRef} open={open} onOpenChange={setOpen}>
46 - <ActionMenu.Button aria-describedby={labelId}>{title}</ActionMenu.Button>
38 + <ActionMenu.Button aria-describedby={labelId} sx={{width: ['100%', null, 'auto']}}>
39 + {title}
40 + </ActionMenu.Button>
41 <ActionMenu.Overlay width="auto" onEscape={() => setOpen(false)}>
42 <ActionList aria-labelledby={labelId}>
43 <ActionList.Group title="Current">
@@ -73,7 +67,7 @@ const useVariants = () => {
67 return null
68 }
69
76 - const result = {path, latest: null, current: null, prerelease: null, legacy: []}
70 + const result = {latest: null, current: null, prerelease: null, legacy: []}
71
72 for (const {variant, page} of variantPages) {
73 const item = {...variant, url: page.url, active: page.url === path}
src/hooks/use-location-change.js new
+19
@@ -0,0 +1,19 @@
1 +import React from 'react'
2 +import usePage from './use-page'
3 +
4 +const useLocationChange = () => {
5 + const {pathname} = usePage().location
6 + const pathRef = React.useRef(null)
7 + const [pathChange, setPathChange] = React.useState({change: false})
8 +
9 + React.useEffect(() => {
10 + if (pathRef.current && pathRef.current !== pathname) {
11 + setPathChange({change: true, current: pathname, previous: pathRef.current})
12 + }
13 + pathRef.current = pathname
14 + }, [pathname])
15 +
16 + return pathChange
17 +}
18 +
19 +export default useLocationChange
src/layout.js
+7 -6
@@ -5,19 +5,20 @@ import PageFooter from './components/page-footer'
5 import * as TableOfContents from './components/table-of-contents'
6 import VariantSelect from './components/variant-select'
7 import Breadcrumbs from './components/breadcrumbs'
8 -import Container from './components/container'
8 import useSiteMetadata from './hooks/use-site-metadata'
9 import usePage from './hooks/use-page'
10 import {DarkTheme} from './theme'
11 import {SkipNav} from './components/skip-nav'
12
13 +const Container = ({sx, ...props}) => <Box sx={{width: '100%', maxWidth: '960px', ...sx}} {...props} />
14 +
15 const HeroLayout = ({children}) => {
16 const {title, description} = useSiteMetadata()
17
18 return (
19 <Box as="main" sx={{width: '100%'}}>
19 - <DarkTheme sx={{bg: 'canvas.inset', py: 6}}>
20 - <Container>
20 + <DarkTheme sx={{bg: 'canvas.inset', py: [0, 4, 5, 6]}}>
21 + <Container sx={{p: 5, mx: 'auto'}}>
22 <Heading as="h1" sx={{color: 'fg.default', fontSize: 7, m: 0}}>
23 {title}
24 </Heading>
@@ -27,7 +28,7 @@ const HeroLayout = ({children}) => {
28 </Container>
29 </DarkTheme>
30 <SkipNav />
30 - <Container>{children}</Container>
31 + <Container sx={{p: 5, mx: 'auto'}}>{children}</Container>
32 </Box>
33 )
34 }
@@ -47,7 +48,7 @@ const DefaultLayout = ({children}) => {
48 }}
49 >
50 <TableOfContents.Desktop />
50 - <Box as="main" sx={{width: '100%', maxWidth: '960px'}}>
51 + <Container as="main">
52 <Box sx={{mb: 4}}>
53 <Breadcrumbs />
54 <H1 autolink={false}>{title}</H1>
@@ -58,7 +59,7 @@ const DefaultLayout = ({children}) => {
59 <TableOfContents.Mobile />
60 {children}
61 <PageFooter />
61 - </Box>
62 + </Container>
63 </Box>
64 )
65 }
src/mdx/code.js
+2 -2
@@ -112,11 +112,11 @@ function Code({className = '', prompt, children}) {
112 {({className: highlightClassName, style, tokens, getLineProps, getTokenProps}) => (
113 <CodeBlock className={highlightClassName} style={style} code={code}>
114 {tokens.map((line, i) => (
115 - <div key={i} {...getLineProps({line, key: i})}>
115 + <Box key={i} {...getLineProps({line, key: i})}>
116 {line.map((token, key) => (
117 <MonoText key={key} {...getTokenProps({token, key})} />
118 ))}
119 - </div>
119 + </Box>
120 ))}
121 </CodeBlock>
122 )}
src/theme.js
+14 -7
@@ -39,11 +39,18 @@ export const npmTheme = deepmerge(theme, {
39
40 export const ThemeProvider = props => <Provider theme={npmTheme} {...props} />
41
42 -export const Theme = ({theme: colorMode, as = Box, ...props}) => (
43 - <Provider colorMode={colorMode} nightScheme="dark_dimmed">
44 - {React.createElement(as, props)}
45 - </Provider>
46 -)
42 +export const Theme = React.forwardRef(function Theme({theme: colorMode, as = Box, ...props}, ref) {
43 + return (
44 + <Provider colorMode={colorMode} nightScheme="dark_dimmed">
45 + {React.createElement(as, {...props, ref})}
46 + </Provider>
47 + )
48 +})
49 +
50 +export const LightTheme = React.forwardRef(function LightTheme(props, ref) {
51 + return <Theme ref={ref} theme="light" {...props} />
52 +})
53
48 -export const LightTheme = props => <Theme theme="light" {...props} />
49 -export const DarkTheme = props => <Theme theme="dark" {...props} />
54 +export const DarkTheme = React.forwardRef(function DarkTheme(props, ref) {
55 + return <Theme ref={ref} theme="dark" {...props} />
56 +})