chore: convert box to native components, transform ignore patterns, remove themeget, remove octicon (#1843)

<!-- What / Why --> <!-- Describe the request in detail. What it does and why it's being changed. --> ## References <!-- Examples: Related to #0 Depends on #0 Blocked by #0 Fixes #0 Closes #0 -->

Michael Smith committed Jan 13, 2026 at 09:12 UTC f0e16df500ea5646aacbf597fbe45148d7cde9bc
20 files changed +258 -237
.eslintrc.js
+16 -7
@@ -90,7 +90,8 @@ module.exports = {
90 'dfn',
91 'dialog',
92 'dir',
93 - 'div',
93 + // ok because Box is deprecated and styles are provided via CSS modules
94 + // 'div',
95 'dl',
96 'dt',
97 'element',
@@ -110,12 +111,15 @@ module.exports = {
111 'h5',
112 'h6',
113 'head',
113 - 'header',
114 + // ok because Box is deprecated and styles are provided via CSS modules
115 + // 'header',
116 'hgroup',
117 'hr',
118 // used in head
119 // 'html',
120 'i',
121 + // ok because Box is deprecated and styles are provided via CSS modules
122 + // 'iframe',
123 'input',
124 'ins',
125 'isindex',
@@ -126,13 +130,15 @@ module.exports = {
130 // ok because there is no mdx replacement and styles are provided via parent ul/ol
131 // 'li',
132 'listing',
129 - 'main',
133 + // ok because Box is deprecated and styles are provided via CSS modules
134 + // 'main',
135 'map',
136 'mark',
137 'menu',
138 'menuitem',
139 'meter',
135 - 'nav',
140 + // ok because Box is deprecated and styles are provided via CSS modules
141 + // 'nav',
142 'noembed',
143 'noscript',
144 'object',
@@ -140,10 +146,12 @@ module.exports = {
146 'optgroup',
147 'option',
148 'output',
143 - 'p',
149 + // ok because Box is deprecated and styles are provided via CSS modules
150 + // 'p',
151 'param',
152 'plaintext',
146 - 'pre',
153 + // ok because Box is deprecated and styles are provided via CSS modules
154 + // 'pre',
155 'progress',
156 'q',
157 'rp',
@@ -181,7 +189,8 @@ module.exports = {
189 'track',
190 'tt',
191 'u',
184 - 'ul',
192 + // ok because Box is deprecated and styles are provided via CSS modules
193 + // 'ul',
194 'var',
195 'video',
196 'wbr',
jest.config.js
+3
@@ -4,6 +4,9 @@ module.exports = {
4 transform: {
5 '^.+\\.jsx?$': `<rootDir>/jest-preprocess.js`,
6 },
7 + transformIgnorePatterns: [
8 + 'node_modules/(?!(@primer/react|@primer/octicons-react|@primer/behaviors|@lit-labs|@lit|@github)/)',
9 + ],
10 moduleNameMapper: {
11 '.+\\.(css|styl|less|sass|scss)$': `identity-obj-proxy`,
12 },
src/components/header.js
+27 -26
@@ -1,5 +1,4 @@
1 import React from 'react'
2 -import {Box} from '@primer/react'
2 import styled from 'styled-components'
3 import * as Search from './search'
4 import NavDrawer from './nav-drawer'
@@ -12,7 +11,7 @@ import SiteTitle from './site-title'
11
12 import * as styles from './header.module.css'
13
15 -const NpmHeaderBar = styled(Box)`
14 +const NpmHeaderBar = styled.div`
15 height: ${HEADER_BAR}px;
16 background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
17 `
@@ -21,30 +20,32 @@ function Header() {
20 const search = useSearch()
21
22 return (
24 - <DarkTheme style={{zIndex: Z_INDEX.HEADER}} className={styles.DarkTheme}>
25 - <NpmHeaderBar />
26 - <Box as="header" className={styles.headerBox}>
27 - <Box className={styles.Box}>
28 - <SiteTitle logo={true} className={styles.SiteTitle} />
29 - <Box className={styles.searchDesktop}>
30 - <Search.Desktop {...search} />
31 - </Box>
32 - </Box>
33 - <Box className={styles.Box_1}>
34 - <Box className={styles.navDesktop}>
35 - {headerNavItems.map((item, index) => (
36 - <Link key={index} href={item.url} className={styles.Link}>
37 - {item.title}
38 - </Link>
39 - ))}
40 - </Box>
41 - <Box className={styles.navMobile}>
42 - <Search.Mobile {...search} />
43 - <NavDrawer />
44 - </Box>
45 - </Box>
46 - </Box>
47 - </DarkTheme>
23 + <div className={styles.stickyHeader} style={{zIndex: Z_INDEX.HEADER}}>
24 + <DarkTheme>
25 + <NpmHeaderBar />
26 + <header className={styles.headerBox}>
27 + <div className={styles.Box}>
28 + <SiteTitle logo={true} className={styles.SiteTitle} />
29 + <div className={styles.searchDesktop}>
30 + <Search.Desktop {...search} />
31 + </div>
32 + </div>
33 + <div className={styles.Box_1}>
34 + <div className={styles.navDesktop}>
35 + {headerNavItems.map((item, index) => (
36 + <Link key={index} href={item.url} className={styles.Link}>
37 + {item.title}
38 + </Link>
39 + ))}
40 + </div>
41 + <div className={styles.navMobile}>
42 + <Search.Mobile {...search} />
43 + <NavDrawer />
44 + </div>
45 + </div>
46 + </header>
47 + </DarkTheme>
48 + </div>
49 )
50 }
51
src/components/header.module.css
+1 -1
@@ -7,7 +7,7 @@
7 display: flex;
8 }
9
10 -.DarkTheme {
10 +.stickyHeader {
11 top: 0;
12 position: sticky;
13 }
src/components/nav-drawer.js
+12 -14
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {Button, Box} from '@primer/react'
2 +import {Button} from '@primer/react'
3 import {XIcon, ThreeBarsIcon} from '@primer/octicons-react'
4 import NavItems from './nav-items'
5 import {useIsMobile} from '../hooks/use-breakpoint'
@@ -17,7 +17,7 @@ const Drawer = ({isOpen, onDismiss, children}) => (
17 // These event handlers fix a bug that caused links below the fold
18 // to be unclickable in macOS Safari.
19 // Reference: https://github.com/theKashey/react-focus-lock/issues/79
20 - <Box
20 + <div
21 onMouseDown={event => event.preventDefault()}
22 onKeyDown={event => event.target.focus()}
23 onClick={event => event.target.focus()}
@@ -25,9 +25,8 @@ const Drawer = ({isOpen, onDismiss, children}) => (
25 tabIndex="0"
26 >
27 <FocusOn returnFocus={true} onEscapeKey={onDismiss}>
28 - <Box
28 + <motion.div
29 key="overlay"
30 - as={motion.div}
30 initial={{opacity: 0}}
31 animate={{opacity: 1}}
32 exit={{opacity: 0}}
@@ -35,10 +34,9 @@ const Drawer = ({isOpen, onDismiss, children}) => (
34 onClick={onDismiss}
35 className={styles.Box}
36 />
38 - <Box
37 + <motion.div
38 style={{top: `${HEADER_BAR}px`}}
39 key="drawer"
41 - as={motion.div}
40 initial={{x: '100%'}}
41 animate={{x: 0}}
42 exit={{x: '100%'}}
@@ -46,9 +44,9 @@ const Drawer = ({isOpen, onDismiss, children}) => (
44 className={styles.Box_1}
45 >
46 {children}
49 - </Box>
47 + </motion.div>
48 </FocusOn>
51 - </Box>
49 + </div>
50 ) : null}
51 </AnimatePresence>
52 )
@@ -69,19 +67,19 @@ function NavDrawer() {
67 <ThreeBarsIcon />
68 </Button>
69 <LightTheme as={Drawer} isOpen={open} onDismiss={() => setOpen(false)}>
72 - <Box style={{WebkitOverflowScrolling: 'touch'}} className={styles.Box_2}>
73 - <Box className={styles.Box_3}>
70 + <div style={{WebkitOverflowScrolling: 'touch'}} className={styles.Box_2}>
71 + <div className={styles.Box_3}>
72 <DarkTheme style={{height: `${HEADER_HEIGHT}px`}} className={styles.DarkTheme}>
73 <SiteTitle />
74 <Button aria-label="Close" onClick={() => setOpen(false)}>
75 <XIcon />
76 </Button>
77 </DarkTheme>
80 - <Box className={styles.Box_4}>
78 + <div className={styles.Box_4}>
79 <NavItems />
82 - </Box>
83 - </Box>
84 - </Box>
80 + </div>
81 + </div>
82 + </div>
83 </LightTheme>
84 </>
85 )
src/components/nav-items.js
+3 -3
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {Box, NavList} from '@primer/react'
2 +import {NavList} from '@primer/react'
3 import {LinkExternalIcon} from '@primer/octicons-react'
4 import Link from './link'
5 import * as getNav from '../util/get-nav'
@@ -65,9 +65,9 @@ const Navigation = () => {
65 <NavItems items={items} path={pathname} />
66 <NavList.Divider />
67 {headerNavItems.map(item => (
68 - <Box key={item.title} className={styles.headerNavItem}>
68 + <div key={item.title} className={styles.headerNavItem}>
69 <ExternalNavItem title={item.title} href={item.url} />
70 - </Box>
70 + </div>
71 ))}
72 <ExternalNavItem title="GitHub" href={repositoryUrl} />
73 </NavList>
src/components/page-footer.js
+8 -9
@@ -1,6 +1,5 @@
1 import React from 'react'
2 -import {Box, Avatar, Text} from '@primer/react'
3 -import {Octicon} from '@primer/react/deprecated'
2 +import {Avatar, Text} from '@primer/react'
3 import {Tooltip} from '@primer/react/next'
4 import {PencilIcon} from '@primer/octicons-react'
5 import Link from './link'
@@ -34,7 +33,7 @@ const Contributors = ({contributors = [], latestCommit}) => {
33
34 return (
35 <>
37 - <Box className={styles.Box}>
36 + <div className={styles.Box}>
37 <Text className={styles.Text}>
38 {contributors.length} {pluralize('contributor', contributors.length)}
39 </Text>
@@ -45,7 +44,7 @@ const Contributors = ({contributors = [], latestCommit}) => {
44 </Link>
45 </Tooltip>
46 ))}
48 - </Box>
47 + </div>
48 {latestCommit ? (
49 <Text className={styles.Text_1}>
50 Last edited by{' '}
@@ -70,17 +69,17 @@ const PageFooter = () => {
69 }
70
71 return (
73 - <Box className={styles.Box_1}>
74 - <Box className={styles.Box_2}>
72 + <div className={styles.Box_1}>
73 + <div className={styles.Box_2}>
74 {editUrl ? (
75 <Link href={editUrl}>
77 - <Octicon icon={PencilIcon} className={styles.Text} />
76 + <PencilIcon className={styles.Text} />
77 Edit this page on GitHub
78 </Link>
79 ) : null}
80 <Contributors contributors={contributors} latestCommit={latestCommit} />
82 - </Box>
83 - </Box>
81 + </div>
82 + </div>
83 )
84 }
85
src/components/search.js
+20 -23
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {Button, ActionList, Box, Text} from '@primer/react'
2 +import {Button, ActionList, Text} from '@primer/react'
3 import {XIcon, SearchIcon} from '@primer/octicons-react'
4 import {AnimatePresence, motion} from 'framer-motion'
5 import {FocusOn} from 'react-focus-on'
@@ -19,9 +19,9 @@ const SearchResults = ({results, getItemProps, highlightedIndex}) => {
19 if (!results || results.length === 0) {
20 announce('No results')
21 return (
22 - <Box aria-live="polite" className={styles.Box}>
22 + <div aria-live="polite" className={styles.Box}>
23 No results
24 - </Box>
24 + </div>
25 )
26 }
27
@@ -47,7 +47,7 @@ const SearchResults = ({results, getItemProps, highlightedIndex}) => {
47 to={item.path}
48 active={highlightedIndex === index}
49 >
50 - <Box
50 + <div
51 aria-label={`${item.title}${hierarchy.length ? ` in ${hierarchy.map(s => s.shortName || s.title).join(' / ')}` : ` in ${siteMetadata.shortName}`}, ${index + 1} of ${results.length}`}
52 className={styles.Box_1}
53 >
@@ -55,7 +55,7 @@ const SearchResults = ({results, getItemProps, highlightedIndex}) => {
55 {hierarchy.length ? hierarchy.map(s => s.shortName || s.title).join(' / ') : siteMetadata.shortName}
56 </Text>
57 <Text>{item.title}</Text>
58 - </Box>
58 + </div>
59 </ActionList.Item>
60 )
61 })}
@@ -68,21 +68,21 @@ export const Desktop = props => {
68 const {getInputProps, getMenuProps, resultsOpen, ...rest} = props
69
70 return (
71 - <Box className={styles.Box_2}>
71 + <div className={styles.Box_2}>
72 <TextInput
73 placeholder={`Search ${siteMetadata.title}`}
74 aria-label={`Search ${siteMetadata.title}`}
75 className={styles.TextInput}
76 {...getInputProps()}
77 />
78 - <Box className={styles.Box_3} {...getMenuProps()}>
78 + <div className={styles.Box_3} {...getMenuProps()}>
79 {resultsOpen ? (
80 <LightTheme className={styles.LightTheme}>
81 <SearchResults {...rest} />
82 </LightTheme>
83 ) : null}
84 - </Box>
85 - </Box>
84 + </div>
85 + </div>
86 )
87 }
88
@@ -118,16 +118,15 @@ export const Mobile = ({
118 <AnimatePresence>
119 {isMobileSearchOpen ? (
120 <FocusOn returnFocus={true} onEscapeKey={() => resetAndClose(true)}>
121 - <Box
121 + <div
122 style={{
123 top: `${HEADER_BAR}px`,
124 zIndex: Z_INDEX.SEARCH_OVERLAY,
125 }}
126 className={styles.Box_4}
127 >
128 - <Box
128 + <motion.div
129 key="search-backdrop"
130 - as={motion.div}
130 initial={{opacity: 0}}
131 animate={{opacity: 1}}
132 transition={{type: 'tween'}}
@@ -135,13 +134,13 @@ export const Mobile = ({
134 className={styles.Box_5}
135 {...getCloseAnimation({opacity: 0})}
136 />
138 - <Box
137 + <div
138 style={{
139 height: resultsOpen ? '100%' : 'auto',
140 }}
141 className={styles.Box_6}
142 >
144 - <Box
143 + <div
144 style={{
145 height: `${HEADER_HEIGHT}px`,
146 zIndex: Z_INDEX.SEARCH_OVERLAY + 1,
@@ -156,7 +155,7 @@ export const Mobile = ({
155 transition={{type: 'tween', ease: 'easeOut', duration: 0.2}}
156 style={{width: '100%', originX: '100%'}}
157 >
159 - <Box className={styles.Box_8} />
158 + <div className={styles.Box_8} />
159 <TextInput
160 leadingVisual={SearchIcon}
161 placeholder={`Search ${siteMetadata.title}`}
@@ -165,18 +164,16 @@ export const Mobile = ({
164 {...getInputProps()}
165 />
166 </motion.div>
168 - <Box
167 + <motion.div
168 key="button-blocker"
170 - as={motion.div}
169 initial={{opacity: 0}}
170 animate={{opacity: 1}}
171 {...getCloseAnimation({scaleX: 0})}
172 transition={{type: 'tween', ease: 'easeOut', duration: 0.2}}
173 className={styles.Box_9}
174 />
177 - <Box
175 + <motion.div
176 key="button"
179 - as={motion.div}
177 initial={{opacity: 0}}
178 animate={{opacity: 1}}
179 {...getCloseAnimation({opacity: 0})}
@@ -185,8 +182,8 @@ export const Mobile = ({
182 <Button aria-label="Cancel" onClick={() => resetAndClose(false)} className={styles.Button_1}>
183 <XIcon />
184 </Button>
188 - </Box>
189 - </Box>
185 + </motion.div>
186 + </div>
187 <LightTheme
188 style={{
189 WebkitOverflowScrolling: 'touch',
@@ -196,8 +193,8 @@ export const Mobile = ({
193 >
194 {resultsOpen ? <SearchResults {...rest} /> : null}
195 </LightTheme>
199 - </Box>
200 - </Box>
196 + </div>
197 + </div>
198 </FocusOn>
199 ) : null}
200 </AnimatePresence>
src/components/sidebar.js
+6 -8
@@ -1,4 +1,3 @@
1 -import {Box} from '@primer/react'
1 import React from 'react'
2 import NavItems from './nav-items'
3 import {FULL_HEADER_HEIGHT} from '../constants'
@@ -30,20 +29,19 @@ function usePersistentScroll(id) {
29 }
30
31 const Sidebar = () => (
33 - <Box
34 - role="navigation"
32 + <nav
33 style={{
34 top: `${FULL_HEADER_HEIGHT}px`,
35 height: `calc(100vh - ${FULL_HEADER_HEIGHT}px)`,
36 }}
37 className={styles.Box}
38 >
41 - <Box {...usePersistentScroll('sidebar')} className={styles.Box_1}>
42 - <Box className={styles.Box_2}>
39 + <div {...usePersistentScroll('sidebar')} className={styles.Box_1}>
40 + <div className={styles.Box_2}>
41 <NavItems />
44 - </Box>
45 - </Box>
46 - </Box>
42 + </div>
43 + </div>
44 + </nav>
45 )
46
47 export default Sidebar
src/components/site-title.js
+2 -3
@@ -1,5 +1,4 @@
1 import React from 'react'
2 -import {Box} from '@primer/react'
2 import Link from './link'
3 import useSiteMetadata from '../hooks/use-site-metadata'
4
@@ -7,12 +6,12 @@ import * as styles from './site-title.module.css'
6 import {clsx} from 'clsx'
7
8 const NpmLogo = ({size, className}) => (
10 - <Box className={clsx(styles.Box, className)}>
9 + <div className={clsx(styles.Box, className)}>
10 <svg height={size} width={size} viewBox="0 0 700 700" fill="currentColor" aria-hidden="true">
11 <polygon fill="currentColor" points="0,700 700,700 700,0 0,0" />
12 <polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
13 </svg>
15 - </Box>
14 + </div>
15 )
16
17 const SiteTitle = ({logo, className}) => {
src/components/skip-nav.js
+9 -10
@@ -1,12 +1,11 @@
1 import React from 'react'
2 -import {Box, themeGet} from '@primer/react'
2 import styled from 'styled-components'
3 import Link from './link'
4 import {SCROLL_MARGIN_TOP, SKIP_TO_CONTENT_ID} from '../constants'
5
6 export const SkipLink = styled(Link)`
8 - color: ${themeGet('colors.accent.emphasis')};
9 - padding: ${themeGet('space.1')};
7 + color: var(--fgColor-accent);
8 + padding: 4px;
9 &:focus {
10 text-decoration: underline;
11 }
@@ -23,12 +22,12 @@ export const SkipBox = styled.div`
22 position: absolute;
23 transform: translateY(-100%);
24 transition: transform 0.3s;
26 - padding: ${themeGet('space.2')};
27 - background-color: ${themeGet('colors.canvas.default')};
28 - border: 1px solid ${themeGet('colors.accent.emphasis')};
25 + padding: 8px;
26 + background-color: var(--bgColor-default);
27 + border: 1px solid var(--fgColor-accent);
28 border-top: 0;
30 - font-size: ${themeGet('fontSizes.1')};
31 - border-radius: 0 0 ${themeGet('radii.2')} ${themeGet('radii.2')};
29 + font-size: 12px;
30 + border-radius: 0 0 6px 6px;
31
32
33 &:focus-within {
@@ -36,7 +35,7 @@ export const SkipBox = styled.div`
35 }
36
37 & > * {
39 - margin-right: ${themeGet('space.1')};
38 + margin-right: 4px;
39 }
40
41 & > *:last-child {
@@ -44,7 +43,7 @@ export const SkipBox = styled.div`
43 }
44 `
45
47 -const SkipNavBase = props => <Box id={SKIP_TO_CONTENT_ID} {...props} />
46 +const SkipNavBase = props => <div id={SKIP_TO_CONTENT_ID} {...props} />
47
48 export const SkipNav = styled(SkipNavBase)`
49 scroll-margin-top: ${SCROLL_MARGIN_TOP}px;
src/components/table-of-contents.js
+7 -7
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {Heading, Box, Details, useDetails, Button, NavList} from '@primer/react'
2 +import {Heading, Details, useDetails, Button, NavList} from '@primer/react'
3 import {ChevronDownIcon, ChevronRightIcon} from '@primer/octicons-react'
4 import usePage from '../hooks/use-page'
5
@@ -44,7 +44,7 @@ const withTableOfContents = Component => {
44 export const Mobile = withTableOfContents(({items}) => {
45 const {getDetailsProps, open} = useDetails({defaultOpen: true})
46 return (
47 - <Box className={styles.tocMobile}>
47 + <div className={styles.tocMobile}>
48 <Details {...getDetailsProps()} className={styles.Details}>
49 <Button
50 as="summary"
@@ -55,17 +55,17 @@ export const Mobile = withTableOfContents(({items}) => {
55 </Button>
56 <TableOfContents items={items} />
57 </Details>
58 - </Box>
58 + </div>
59 )
60 })
61
62 export const Desktop = withTableOfContents(({items}) => (
63 - <Box className={styles.tocDesktop}>
63 + <div className={styles.tocDesktop}>
64 <Heading as="h2" id="toc-heading" className={styles.Heading}>
65 Table of contents
66 </Heading>
67 - <Box className={styles.Box}>
67 + <div className={styles.Box}>
68 <TableOfContents aria-labelledby="toc-heading" items={items} className={styles.TableOfContents} />
69 - </Box>
70 - </Box>
69 + </div>
70 + </div>
71 ))
src/components/text-input.js
+5 -4
@@ -1,4 +1,4 @@
1 -import {TextInput as PrimerTextInput, themeGet} from '@primer/react'
1 +import {TextInput as PrimerTextInput} from '@primer/react'
2 import styled from 'styled-components'
3
4 const TextInput = styled(PrimerTextInput)`
@@ -7,12 +7,13 @@ const TextInput = styled(PrimerTextInput)`
7 * TODO: Update font-size of TextInput in @primer/react.
8 */
9 input {
10 - font-size: ${themeGet('fontSizes.2')} !important;
11 - color: ${themeGet('colors.fg.default')} !important;
10 + font-size: 16px !important;
11 + color: rgb(225, 228, 232) !important;
12 }
13
14 input::placeholder {
15 - color: ${themeGet('colors.fg.default')} !important;
15 + color: rgb(225, 228, 232) !important;
16 + opacity: 0.7;
17 }
18 `
19 export default TextInput
src/components/variant-select.js
+5 -5
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {ActionList, ActionMenu, Box} from '@primer/react'
2 +import {ActionList, ActionMenu} from '@primer/react'
3 import * as getNav from '../util/get-nav'
4 import usePage from '../hooks/use-page'
5 import {LinkNoUnderline} from './link'
@@ -52,9 +52,9 @@ const VariantMenu = ({title, latest, current, prerelease, legacy}) => {
52
53 return (
54 <>
55 - <Box as="p" id={labelId} className={styles.Box}>
55 + <p id={labelId} className={styles.Box}>
56 Select CLI Version:
57 - </Box>
57 + </p>
58 <ActionMenu anchorRef={anchorRef} open={open} onOpenChange={setOpen}>
59 <ActionMenu.Button aria-describedby={labelId} className={styles.menuButton}>
60 {title}
@@ -126,9 +126,9 @@ const useVariants = () => {
126 const VariantSelect = () => {
127 const variants = useVariants()
128 return variants ? (
129 - <Box className={styles.Box_1}>
129 + <div className={styles.Box_1}>
130 <VariantMenu {...variants} />
131 - </Box>
131 + </div>
132 ) : null
133 }
134
src/layout.js
+9 -9
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {Box, Heading, Text} from '@primer/react'
2 +import {Heading, Text} from '@primer/react'
3 import {h1 as H1} from './mdx'
4 import PageFooter from './components/page-footer'
5 import * as TableOfContents from './components/table-of-contents'
@@ -13,13 +13,13 @@ import {SkipNav} from './components/skip-nav'
13 import * as styles from './layout.module.css'
14 import {clsx} from 'clsx'
15
16 -const Container = ({className, ...props}) => <Box className={clsx(styles.Box, className)} {...props} />
16 +const Container = ({className, ...props}) => <div className={clsx(styles.Box, className)} {...props} />
17
18 const HeroLayout = ({children}) => {
19 const {title, description} = useSiteMetadata()
20
21 return (
22 - <Box as="main" className={styles.Box_1}>
22 + <main className={styles.Box_1}>
23 <DarkTheme className={styles.DarkTheme}>
24 <Container className={styles.Container}>
25 <Heading as="h1" className={styles.Heading}>
@@ -32,20 +32,20 @@ const HeroLayout = ({children}) => {
32 </DarkTheme>
33 <SkipNav />
34 <Container className={styles.Container}>{children}</Container>
35 - </Box>
35 + </main>
36 )
37 }
38
39 const DefaultLayout = ({children}) => {
40 const {title, description} = usePage().frontmatter
41 return (
42 - <Box className={styles.Box_2}>
42 + <div className={styles.Box_2}>
43 <Container as="main">
44 - <Box className={styles.Box_3}>
44 + <div className={styles.Box_3}>
45 <Breadcrumbs />
46 <H1 autolink={false}>{title}</H1>
47 - {description ? <Box className={styles.Box_4}>{description}</Box> : null}
48 - </Box>
47 + {description ? <div className={styles.Box_4}>{description}</div> : null}
48 + </div>
49 <SkipNav />
50 <VariantSelect />
51 <TableOfContents.Mobile />
@@ -53,7 +53,7 @@ const DefaultLayout = ({children}) => {
53 <PageFooter />
54 </Container>
55 <TableOfContents.Desktop />
56 - </Box>
56 + </div>
57 )
58 }
59
src/mdx/code.js
+15 -16
@@ -1,6 +1,5 @@
1 import React from 'react'
2 -import {Box, Text, Button, themeGet} from '@primer/react'
3 -import {Octicon} from '@primer/react/deprecated'
2 +import {Text, Button} from '@primer/react'
3 import {Highlight, themes, Prism} from 'prism-react-renderer'
4 import styled from 'styled-components'
5 import {CheckIcon, CopyIcon} from '@primer/octicons-react'
@@ -35,17 +34,17 @@ const ClipboardCopy = ({value, ...props}) => {
34 }}
35 className={clsx(styles.Button, props.className)}
36 >
38 - <Octicon icon={copied ? CheckIcon : CopyIcon} style={{color: copied ? '#1a7f37' : '#656d76'}} />
37 + {copied ? <CheckIcon fill="#1a7f37" /> : <CopyIcon fill="#656d76" />}
38 </Button>
39 )
40 }
41
42 export const InlineCode = styled.code`
43 padding: 0.2em 0.4em;
45 - font-family: ${themeGet('fonts.mono')};
44 + font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
45 font-size: 80%;
47 - background-color: ${themeGet('colors.neutral.muted')};
48 - border-radius: ${themeGet('radii.2')};
46 + background-color: var(--bgColor-neutral-muted, #afb8c133);
47 + border-radius: 6px;
48 `
49 const colorMap = {
50 'token comment': '#747458',
@@ -58,16 +57,16 @@ const colorMap = {
57 const MonoText = props => <Text className={styles.Text} {...props} />
58
59 const CodeBlock = ({children, code, className, style}) => (
61 - <Box className={styles.Box}>
62 - <Box style={style} className={styles.Box_1}>
60 + <div className={styles.Box}>
61 + <div style={style} className={styles.Box_1}>
62 {code ? <ClipboardCopy value={code} className={styles.ClipboardCopy} /> : null}
64 - <Box className={styles.Box_2}>
65 - <Box as="pre" className={clsx(className, styles.Box_3)} tabIndex={0}>
63 + <div className={styles.Box_2}>
64 + <pre className={clsx(className, styles.Box_3)} tabIndex={0}>
65 {children}
67 - </Box>
68 - </Box>
69 - </Box>
70 - </Box>
66 + </pre>
67 + </div>
68 + </div>
69 + </div>
70 )
71
72 function Code({className = '', prompt, children}) {
@@ -91,7 +90,7 @@ function Code({className = '', prompt, children}) {
90 {({className: highlightClassName, style, tokens, getLineProps, getTokenProps}) => (
91 <CodeBlock className={highlightClassName} style={style} code={code}>
92 {tokens.map((line, i) => (
94 - <Box key={i} {...getLineProps({line, key: i})}>
93 + <div key={i} {...getLineProps({line, key: i})}>
94 {line.map((token, key) => {
95 const tokenProps = getTokenProps({token, key})
96 const tokenStyle = colorMap[tokenProps.className]
@@ -100,7 +99,7 @@ function Code({className = '', prompt, children}) {
99
100 return <MonoText key={key} {...tokenProps} style={tokenStyle} />
101 })}
103 - </Box>
102 + </div>
103 ))}
104 </CodeBlock>
105 )}
src/mdx/components.js
+94 -75
@@ -1,8 +1,6 @@
1 import React from 'react'
2 -import {Box, Heading, themeGet} from '@primer/react'
3 -import {Octicon} from '@primer/react/deprecated'
2 +import {Heading} from '@primer/react'
3 import styled from 'styled-components'
5 -import {variant as styledVariant} from 'styled-system'
4 import {LinkIcon} from '@primer/octicons-react'
5 import textContent from 'react-addons-text-content'
6 import {SCROLL_MARGIN_TOP} from '../constants'
@@ -24,13 +22,13 @@ const required = (prop, name) => {
22 return prop
23 }
24
27 -export const Link = props => <SiteLink underline {...props} />
25 +export const Link = props => <SiteLink showUnderline {...props} />
26
27 const StyledHeading = styled(Heading)`
30 - margin-top: ${themeGet('space.4')};
31 - margin-bottom: ${themeGet('space.3')};
28 + margin-top: 24px;
29 + margin-bottom: 16px;
30 scroll-margin-top: ${SCROLL_MARGIN_TOP}px;
33 - line-height: ${themeGet('lineHeights.condensed')};
31 + line-height: 1.25;
32
33 @media (hover: hover) {
34 & .octicon-link {
@@ -48,7 +46,7 @@ const HeaderLink = ({autolink, children, ...props}) =>
46 autolink ? (
47 <LinkNoUnderline {...props} className={styles.LinkNoUnderline}>
48 {children}
51 - <Octicon icon={LinkIcon} className={clsx('octicon-link', styles.Octicon)} />
49 + <LinkIcon className={clsx('octicon-link', styles.Octicon)} />
50 </LinkNoUnderline>
51 ) : (
52 children
@@ -87,31 +85,31 @@ const Headings = {
85 )
86 },
87 h1: styled(StyledHeading).attrs({as: 'h1'})`
90 - padding-bottom: ${themeGet('space.2')};
91 - font-size: ${themeGet('fontSizes.6')};
92 - border-bottom: 1px solid ${themeGet('colors.border.default')};
88 + padding-bottom: 8px;
89 + font-size: 32px;
90 + border-bottom: 1px solid var(--borderColor-default, #d1d9e0);
91 margin-top: 0;
92 `,
93 h2: styled(StyledHeading).attrs({as: 'h2'})`
96 - padding-bottom: ${themeGet('space.2')};
97 - font-size: ${themeGet('fontSizes.4')};
98 - border-bottom: 1px solid ${themeGet('colors.border.default')};
99 - font-weight: ${themeGet('fontWeights.semibold')};
94 + padding-bottom: 8px;
95 + font-size: 20px;
96 + border-bottom: 1px solid var(--borderColor-default, #d1d9e0);
97 + font-weight: 600;
98 `,
99 h3: styled(StyledHeading).attrs({as: 'h3'})`
102 - font-size: ${themeGet('fontSizes.3')};
103 - font-weight: ${themeGet('fontWeights.semibold')};
100 + font-size: 16px;
101 + font-weight: 500;
102 `,
103 h4: styled(StyledHeading).attrs({as: 'h4'})`
106 - font-size: ${themeGet('fontSizes.2')};
107 - font-weight: ${themeGet('fontWeights.semibold')};
104 + font-size: 14px;
105 + font-weight: 500;
106 `,
107 h5: styled(StyledHeading).attrs({as: 'h5'})`
110 - font-size: ${themeGet('fontSizes.1')};
108 + font-size: 12px;
109 `,
110 h6: styled(StyledHeading).attrs({as: 'h6'})`
113 - font-size: ${themeGet('fontSizes.1')};
114 - color: ${themeGet('colors.fg.muted')};
111 + font-size: 12px;
112 + color: var(--fgColor-muted);
113 `,
114 wrap(as) {
115 return props => <Headings.Markdown as={Headings[as]} {...props} />
@@ -126,10 +124,10 @@ export const H5 = Headings.wrap('h4')
124 export const H6 = Headings.wrap('h5')
125
126 export const Blockquote = styled.blockquote`
129 - margin: 0 0 ${themeGet('space.3')};
130 - padding: 0 ${themeGet('space.3')};
131 - color: ${themeGet('colors.fg.muted')};
132 - border-left: 0.25em solid ${themeGet('colors.border.default')};
127 + margin: 0 0 16px;
128 + padding: 0 16px;
129 + color: var(--fgColor-muted);
130 + border-left: 0.25em solid var(--borderColor-default);
131
132 > :first-child {
133 margin-top: 0;
@@ -145,23 +143,23 @@ export const DescriptionList = styled.dl`
143
144 dt {
145 padding: 0;
148 - margin-top: ${themeGet('space.3')};
146 + margin-top: 16px;
147 font-size: 1em;
148 font-style: italic;
151 - font-weight: ${themeGet('fontWeights.bold')};
149 + font-weight: 600;
150 }
151
152 dd {
155 - padding: 0 ${themeGet('space.3')};
156 - margin: 0 0 ${themeGet('space.3')};
153 + padding: 0 16px;
154 + margin: 0 0 16px;
155 }
156 `
157
158 export const HorizontalRule = styled.hr`
161 - height: ${themeGet('borderWidths.1')};
159 + height: 1px;
160 padding: 0;
163 - margin: ${themeGet('space.4')} 0;
164 - background-color: ${themeGet('colors.border.default')};
161 + margin: 24px 0;
162 + background-color: var(--borderColor-muted, #d1d9e0);
163 border: 0;
164 `
165
@@ -179,67 +177,91 @@ export const UnorderedList = styled.ul`
177 }
178
179 li > p {
182 - margin-top: ${themeGet('space.3')};
180 + margin-top: 16px;
181 }
182
183 li + li {
186 - margin-top: ${themeGet('space.1')};
184 + margin-top: 4px;
185 }
186 `
187
188 export const OrderedList = UnorderedList.withComponent('ol')
189
190 export const Paragraph = styled.p`
193 - margin: 0 0 ${themeGet('space.3')};
191 + margin: 0 0 16px;
192 word-break: break-word;
193 `
194
195 export const Table = styled.table`
196 display: block;
197 width: 100%;
200 - margin: 0 0 ${themeGet('space.3')};
198 + margin: 0 0 16px;
199 overflow: auto;
200 border-collapse: separate;
201 border-spacing: 0px;
202
203 th {
206 - font-weight: ${themeGet('fontWeights.bold')};
207 - background-color: ${themeGet('colors.neutral.subtle')};
204 + font-weight: 600;
205 + background-color: var(--bgColor-neutral-muted, #afb8c133);
206 }
207
208 th,
209 td {
212 - padding: ${themeGet('space.2')} ${themeGet('space.3')};
213 - border-color: ${themeGet('colors.border.muted')};
210 + padding: 8px 16px;
211 + border-color: var(--borderColor-muted, #d0d7de);
212 border-style: solid;
213 border-width: 0;
216 - border-left-width: ${themeGet('borderWidths.1')};
217 - border-top-width: ${themeGet('borderWidths.1')};
214 + border-left-width: 1px;
215 + border-top-width: 1px;
216 + }
217 +
218 + td a {
219 + color: var(--fgColor-default, #1f2328);
220 + text-decoration: underline;
221 + }
222 +
223 + td a:hover {
224 + text-decoration: none;
225 + }
226 +
227 + td code a,
228 + td a code {
229 + color: var(--fgColor-default, #1f2328);
230 + text-decoration: underline;
231 + font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
232 + background-color: var(--bgColor-neutral-muted, #afb8c133);
233 + padding: 2px 6px;
234 + border-radius: 6px;
235 + }
236 +
237 + td code a:hover,
238 + td a code:hover {
239 + text-decoration: none;
240 }
241
242 tr:last-child td {
221 - border-bottom-width: ${themeGet('borderWidths.1')};
243 + border-bottom-width: 1px;
244 }
245
246 tr td:last-child,
247 tr th:last-child {
226 - border-right-width: ${themeGet('borderWidths.1')};
248 + border-right-width: 1px;
249 }
250
251 thead th:first-child {
230 - border-top-left-radius: ${themeGet('radii.2')};
252 + border-top-left-radius: 6px;
253 }
254
255 thead th:last-child {
234 - border-top-right-radius: ${themeGet('radii.2')};
256 + border-top-right-radius: 6px;
257 }
258
259 tbody tr:last-child td:last-child {
238 - border-bottom-right-radius: ${themeGet('radii.2')};
260 + border-bottom-right-radius: 6px;
261 }
262
263 tbody tr:last-child td:first-child {
242 - border-bottom-left-radius: ${themeGet('radii.2')};
264 + border-bottom-left-radius: 6px;
265 }
266
267 img {
@@ -249,34 +271,32 @@ export const Table = styled.table`
271 `
272
273 const StyledNote = styled.div`
252 - padding: ${themeGet('space.3')};
253 - margin-bottom: ${themeGet('space.3')};
254 - border-radius: ${themeGet('radii.2')};
255 - border-left: ${themeGet('radii.2')} solid;
274 + padding: 16px;
275 + margin-bottom: 16px;
276 + border-radius: 6px;
277 + border-left: 6px solid;
278
279 & *:last-child {
280 margin-bottom: 0;
281 }
282
261 - ${styledVariant({
262 - variants: {
263 - info: {
264 - borderColor: 'accent.muted',
265 - bg: 'accent.subtle',
266 - },
267 - warning: {
268 - borderColor: 'attention.muted',
269 - bg: 'attention.subtle',
270 - },
271 - danger: {
272 - borderColor: 'danger.muted',
273 - bg: 'danger.subtle',
274 - },
275 - },
276 - })}
283 + &[data-variant='info'] {
284 + border-left-color: var(--borderColor-accent-muted, #54aeff);
285 + background-color: var(--bgColor-accent-subtle, #ddf4ff);
286 + }
287 +
288 + &[data-variant='warning'] {
289 + border-left-color: var(--borderColor-attention-muted, #d4a72c);
290 + background-color: var(--bgColor-attention-subtle, #fff8c5);
291 + }
292 +
293 + &[data-variant='danger'] {
294 + border-left-color: var(--borderColor-danger-muted, #ff8182);
295 + background-color: var(--bgColor-danger-subtle, #ffebe9);
296 + }
297 `
298
279 -export const Note = ({variant = 'info', ...props}) => <StyledNote variant={variant} {...props} />
299 +export const Note = ({variant = 'info', ...props}) => <StyledNote data-variant={variant} {...props} />
300
301 export const Prompt = props => <Code prompt={true} {...props} />
302
@@ -288,17 +308,16 @@ export const Image = styled(RequiredImage)`
308 `
309
310 export const Screenshot = styled(RequiredImage)`
291 - margin-top: ${themeGet('space.3')};
292 - margin-bottom: ${themeGet('space.3')};
311 + margin-top: 16px;
312 + margin-bottom: 16px;
313 max-width: min(100%, 525px);
314 max-height: 300px;
295 - border: 1px solid ${themeGet('colors.border.default')};
315 + border: 1px solid var(--borderColor-default);
316 display: block;
317 `
318
319 export const YouTube = ({id}) => (
300 - <Box
301 - as="iframe"
320 + <iframe
321 title="YouTube video"
322 src={`https://www.youtube.com/embed/${id}`}
323 frameBorder="0"
src/mdx/nav-hierarchy.js
+5 -6
@@ -1,5 +1,4 @@
1 import React from 'react'
2 -import {Box} from '@primer/react'
2 import Link from '../components/link'
3 import * as getNav from '../util/get-nav'
4 import usePage from '../hooks/use-page'
@@ -10,15 +9,15 @@ const HierarchyItem = ({item, maxDepth, depth, hideVariants}) => {
9 const hierarchy = getNav.getHierarchy(item, null, {hideVariants})
10
11 return (
13 - <Box as="li" key={item.url}>
12 + <li key={item.url}>
13 <Link key={item.title} to={item.url}>
14 {item.title}
15 </Link>
17 - {item.description ? <Box className={styles.Box}>{item.description}</Box> : null}
16 + {item.description ? <div className={styles.Box}>{item.description}</div> : null}
17 {hierarchy ? (
18 <Hierarchy items={hierarchy} maxDepth={maxDepth} depth={depth + 1} hideVariants={hideVariants} />
19 ) : null}
21 - </Box>
20 + </li>
21 )
22 }
23
@@ -28,11 +27,11 @@ const Hierarchy = ({items, maxDepth, depth, hideVariants}) => {
27 }
28
29 return (
31 - <Box as="ul">
30 + <ul>
31 {items.map(item => (
32 <HierarchyItem key={item.url} item={item} maxDepth={maxDepth} depth={depth} hideVariants={hideVariants} />
33 ))}
35 - </Box>
34 + </ul>
35 )
36 }
37
src/page.js
+9 -9
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {BaseStyles, themeGet, Box} from '@primer/react'
2 +import {BaseStyles} from '@primer/react'
3 import {createGlobalStyle} from 'styled-components'
4 import Slugger from 'github-slugger'
5 import Header from './components/header'
@@ -30,8 +30,8 @@ const GlobalStyles = createGlobalStyle`
30 --z-index-search-overlay: ${Z_INDEX.SEARCH_OVERLAY};
31 }
32 body {
33 - color: ${themeGet('colors.fg.default')};
34 - background-color: ${themeGet('colors.canvas.default')};
33 + color: var(--fgColor-default);
34 + background-color: var(--bgColor-default);
35 }
36 `
37
@@ -51,15 +51,15 @@ const PageElement = ({element, props}) => {
51 <SkipLink href={`#${SKIP_TO_CONTENT_ID}`}>Skip to content</SkipLink>
52 </SkipBox>
53 <PageProvider value={page}>
54 - <Box className={styles.Box}>
54 + <div className={styles.Box}>
55 <Header />
56 - <Box className={styles.Box_1}>
57 - <Box className={styles.sidebarContainer}>
56 + <div className={styles.Box_1}>
57 + <div className={styles.sidebarContainer}>
58 <Sidebar />
59 - </Box>
59 + </div>
60 <Layout>{element}</Layout>
61 - </Box>
62 - </Box>
61 + </div>
62 + </div>
63 </PageProvider>
64 </BaseStyles>
65 )
src/theme.js
+2 -2
@@ -1,5 +1,5 @@
1 import React from 'react'
2 -import {ThemeProvider as Provider, theme, Box} from '@primer/react'
2 +import {ThemeProvider as Provider, theme} from '@primer/react'
3 import deepmerge from 'deepmerge'
4
5 export const NPM_RED = '#cb3837'
@@ -39,7 +39,7 @@ export const npmTheme = deepmerge(theme, {
39
40 export const ThemeProvider = props => <Provider theme={npmTheme} {...props} />
41
42 -export const Theme = React.forwardRef(function Theme({theme: colorMode, as = Box, ...props}, ref) {
42 +export const Theme = React.forwardRef(function Theme({theme: colorMode, as = 'div', ...props}, ref) {
43 return (
44 <Provider colorMode={colorMode} nightScheme="dark_dimmed">
45 {React.createElement(as, {...props, ref})}