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})}