fix: move all mdx components to one file
Luke Karrys committed
Oct 15, 2023 at 13:11 UTC
f907dd252a516386c5b613b016db4808f1dc5206
43 files changed
+571
-631
.eslintrc.js
+7
-18
@@ -12,28 +12,17 @@ module.exports = {
12
'plugin:import/recommended',
13
'prettier',
14
],
15
+ settings: {
16
+ import: {
17
+ ignore: ['^theme$'],
18
+ },
19
+ },
20
rules: {
21
'react/prop-types': 'off',
22
+ // our theme use exports which dont work with import/no-unresolved
23
+ 'import/no-unresolved': ['error', {ignore: ['^theme$']}],
24
},
25
overrides: [
19
- // {
20
- // files: ['**/src/**/*.js'],
21
- // // env: {
22
- // // commonjs: false,
23
- // // browser: true,
24
- // // },
25
- // // parserOptions: {
26
- // // sourceType: 'module',
27
- // // },
28
- // },
29
- // {
30
- // files: ['**/gatsby-*.js'],
31
- // // env: {node: true},
32
- // },
33
- // {
34
- // files: ['**/test/*', '**/__tests__/*'],
35
- // env: {jest: true},
36
- // },
26
{
27
files: ['src/shared.js'],
28
rules: {
.gitignore
+2
-1
@@ -24,6 +24,7 @@
24
!/CONTRIBUTING.md
25
!/docs/
26
!/gatsby-*.js
27
+!/jest*.js
28
!/lib/
29
!/LICENSE*
30
!/map.js
@@ -33,7 +34,7 @@
34
!/release-please-config.json
35
!/scripts/
36
!/SECURITY.md
36
-!/src/
37
+!/src
38
!/static/
39
!/tap-snapshots/
40
!/test/
content/index.mdx
+1
-1
@@ -3,7 +3,7 @@ title: npm Documentation
3
edit_on_github: false
4
---
5
6
-import HeroLayout from 'theme/src/layout-hero'
6
+import HeroLayout from 'theme/layout/hero.js'
7
export default HeroLayout
8
9
<Index depth='1' />
jest-preprocess.js
renamed
jest-setup.js
renamed
jest.config.js
renamed
scripts/template-oss/index.js
+2
-1
@@ -38,12 +38,13 @@ module.exports = {
38
devDependencies: [],
39
},
40
allowPaths: [
41
+ '/src',
42
'/.reuse/',
42
- '/src/',
43
'/static/',
44
'/content/',
45
'/LICENSE*',
46
'/gatsby-*.js',
47
+ '/jest*.js',
48
'/CODE_OF_CONDUCT.md',
49
'/CONTRIBUTING.md',
50
'/CONTENT-MODEL.md',
src/shared.js
+1
-3
@@ -1,7 +1,5 @@
1
import React from 'react'
2
-import {Link} from '@primer/react'
3
-import Screenshot from 'theme/src/mdx/screenshot'
4
-import Note from 'theme/src/mdx/note'
2
+import {Link, Note, Screenshot} from 'theme'
3
4
const shared = {
5
/* User login */
theme/.gitignore
-1
@@ -12,7 +12,6 @@
12
!/CHANGELOG*
13
!/docs/
14
!/gatsby-*.js
15
-!/jest*.js
15
!/lib/
16
!/LICENSE*
17
!/map.js
theme/gatsby-config.js
+1
-1
@@ -53,7 +53,7 @@ module.exports = ({icon}) => ({
53
options: {
54
extensions: ['.mdx', '.md'],
55
defaultLayouts: {
56
- default: require.resolve('./src/layout-default.js'),
56
+ default: require.resolve('./src/layout/default.js'),
57
},
58
},
59
},
theme/package.json
+4
-1
@@ -7,7 +7,10 @@
7
"type": "git"
8
},
9
"private": true,
10
- "main": "index.js",
10
+ "exports": {
11
+ ".": "./src/mdx/index.js",
12
+ "./layout/*.js": "./src/layout/*.js"
13
+ },
14
"license": "MIT",
15
"scripts": {
16
"test": "jest",
theme/scripts/template-oss/index.js
+1
-1
@@ -1,4 +1,4 @@
1
module.exports = {
2
...require('../../../scripts/template-oss'),
3
- allowPaths: ['/src', '/gatsby-*.js', '/jest*.js'],
3
+ allowPaths: ['/src', '/gatsby-*.js'],
4
}
theme/src/components/contributors.js
+3
-4
@@ -1,6 +1,5 @@
1
-import {Avatar, Link, Text, Tooltip} from '@primer/react'
1
+import {Box, Avatar, Link, Text, Tooltip} from '@primer/react'
2
import React from 'react'
3
-import Flex from '../components/flex'
3
4
const pluralize = (word, count) => `${word}${count === 1 ? '' : 's'}`
5
@@ -23,7 +22,7 @@ const format = d => `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`
22
function Contributors({logins, latestCommit}) {
23
return (
24
<div>
26
- <Flex alignItems="center">
25
+ <Box display="flex" alignItems="center">
26
<Text mr={2}>
27
{logins.length} {pluralize('contributor', logins.length)}
28
</Text>
@@ -35,7 +34,7 @@ function Contributors({logins, latestCommit}) {
34
</Tooltip>
35
</Link>
36
))}
38
- </Flex>
37
+ </Box>
38
{latestCommit ? (
39
<Text fontSize={1} color="gray.7" mt={1}>
40
Last edited by <Link href={`https://github.com/${latestCommit.login}`}>{latestCommit.login}</Link> on{' '}
theme/src/components/flex.js
deleted
-6
@@ -1,6 +0,0 @@
1
-import React from 'react'
2
-import {Box} from '@primer/react'
3
-
4
-const Flex = props => <Box display="flex" {...props} />
5
-
6
-export default Flex
theme/src/components/header.js
+11
-11
@@ -6,7 +6,6 @@ import MobileSearch from './mobile-search'
6
import NavDrawer from './nav-drawer'
7
import Search from './search'
8
import NpmLogo from './npm-logo'
9
-import Flex from './flex'
9
import useSearch from '../hooks/use-search'
10
import useSiteMetadata from '../hooks/use-site-metadata'
11
import headerNavItems from '../header-nav.yml'
@@ -33,14 +32,15 @@ function Header({location, repositoryUrl}) {
32
return (
33
<Box position="sticky" role="banner">
34
<NpmHeaderBar />
36
- <Flex
35
+ <Box
36
+ display="flex"
37
height={HEADER_HEIGHT}
38
px={[3, null, null, 4]}
39
alignItems="center"
40
justifyContent="space-between"
41
bg="#333333"
42
>
43
- <Flex alignItems="center">
43
+ <Box display="flex" alignItems="center">
44
<Link as={GatsbyLink} to="/" style={titleStyle} sx={{mr: 4}}>
45
<NpmLogo size="32" style={logoStyle} />
46
{siteMetadata.title}
@@ -48,30 +48,30 @@ function Header({location, repositoryUrl}) {
48
<Box display={['none', null, null, 'block']} ml={4}>
49
<Search {...search} />
50
</Box>
51
- </Flex>
52
- <Flex>
51
+ </Box>
52
+ <Box display="flex">
53
<Box display={['none', null, null, 'block']}>
54
<HeaderNavItems items={headerNavItems} />
55
</Box>
56
- <Flex display={['flex', null, null, 'none']}>
56
+ <Box display={['flex', null, null, 'none']}>
57
<MobileSearch {...search} />
58
<NavDrawer location={location} repositoryUrl={repositoryUrl} />
59
- </Flex>
60
- </Flex>
61
- </Flex>
59
+ </Box>
60
+ </Box>
61
+ </Box>
62
</Box>
63
)
64
}
65
66
function HeaderNavItems({items}) {
67
return (
68
- <Flex alignItems="center" color="gray.2">
68
+ <Box display="flex" alignItems="center" color="gray.2">
69
{items.map((item, index) => (
70
<Link key={index} href={item.url} sx={{display: 'block', color: 'inherit', ml: 4}}>
71
{item.title}
72
</Link>
73
))}
74
- </Flex>
74
+ </Box>
75
)
76
}
77
theme/src/components/mobile-search.js
+7
-7
@@ -3,7 +3,6 @@ import {Box} 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'
6
-import Flex from './flex'
6
import DarkButton from './dark-button'
7
import DarkTextInput from './dark-text-input'
8
import SearchResults from './search-results'
@@ -35,8 +34,8 @@ function MobileSearch({onDismiss, ...props}) {
34
zIndex={-1}
35
onClick={handleDismiss}
36
/>
38
- <Flex flexDirection="column" height={isOpen ? '100%' : 'auto'}>
39
- <Flex bg="gray.9" color="white" p={3} flex="0 0 auto">
37
+ <Box display="flex" flexDirection="column" height={isOpen ? '100%' : 'auto'}>
38
+ <Box display="flex" bg="gray.9" color="white" p={3} flex="0 0 auto">
39
<motion.div
40
initial={{scaleX: 0.1}}
41
animate={{scaleX: 1}}
@@ -55,8 +54,9 @@ function MobileSearch({onDismiss, ...props}) {
54
<DarkButton ml={3} aria-label="Cancel" onClick={handleDismiss}>
55
<XIcon />
56
</DarkButton>
58
- </Flex>
59
- <Flex
57
+ </Box>
58
+ <Box
59
+ display="flex"
60
{...getMenuProps({
61
bg: 'white',
62
py: isOpen ? 1 : 0,
@@ -69,8 +69,8 @@ function MobileSearch({onDismiss, ...props}) {
69
})}
70
>
71
{isOpen ? <SearchResults {...{results, getItemProps, highlightedIndex}} /> : null}
72
- </Flex>
73
- </Flex>
72
+ </Box>
73
+ </Box>
74
</Box>
75
</FocusOn>
76
)
theme/src/components/nav-drawer.js
+21
-12
@@ -1,12 +1,11 @@
1
import React from 'react'
2
-import {Link} from '@primer/react'
2
+import {Box, Link} from '@primer/react'
3
import BorderBox from './border-box'
4
import {XIcon, ThreeBarsIcon} from '@primer/octicons-react'
5
import {Link as GatsbyLink} from 'gatsby'
6
import DarkButton from './dark-button'
7
import Drawer from './drawer'
8
import NavItems from './nav-items'
9
-import Flex from './flex'
9
import navItems from '../nav.yml'
10
import headerNavItems from '../header-nav.yml'
11
import useSiteMetadata from '../hooks/use-site-metadata'
@@ -37,35 +36,45 @@ function NavDrawer({location, repositoryUrl}) {
36
<ThreeBarsIcon />
37
</DarkButton>
38
<Drawer isOpen={isOpen} onDismiss={setClose}>
40
- <Flex
39
+ <Box
40
+ display="flex"
41
flexDirection="column"
42
height="100%"
43
bg="gray.0"
44
style={{overflow: 'auto', WebkitOverflowScrolling: 'touch'}}
45
>
46
- <Flex flexDirection="column" flex="1 0 auto" color="gray.7" bg="gray.0">
46
+ <Box display="flex" flexDirection="column" flex="1 0 auto" color="gray.7" bg="gray.0">
47
<BorderBox borderWidth={0} borderRadius={0} borderBottomWidth={1} borderColor="gray.7">
48
- <Flex py={3} pl={4} pr={3} alignItems="center" justifyContent="space-between" color="gray.1" bg="gray.9">
48
+ <Box
49
+ display="flex"
50
+ py={3}
51
+ pl={4}
52
+ pr={3}
53
+ alignItems="center"
54
+ justifyContent="space-between"
55
+ color="gray.1"
56
+ bg="gray.9"
57
+ >
58
<Link as={GatsbyLink} to="/" sx={{display: 'inline-block', color: 'inherit'}}>
59
{siteMetadata.title}
60
</Link>
61
<DarkButton aria-label="Close" onClick={setClose}>
62
<XIcon />
63
</DarkButton>
55
- </Flex>
64
+ </Box>
65
</BorderBox>
66
{navItems.length > 0 ? (
58
- <Flex flexDirection="column">
67
+ <Box display="flex" flexDirection="column">
68
<NavItems location={location} items={navItems} repositoryUrl={repositoryUrl} />
60
- </Flex>
69
+ </Box>
70
) : null}
62
- </Flex>
71
+ </Box>
72
{headerNavItems.length > 0 ? (
64
- <Flex flexDirection="column" flex="1 0 auto" color="gray.1" bg="gray.9">
73
+ <Box display="flex" flexDirection="column" flex="1 0 auto" color="gray.1" bg="gray.9">
74
<HeaderNavItems items={headerNavItems} />
66
- </Flex>
75
+ </Box>
76
) : null}
68
- </Flex>
77
+ </Box>
78
</Drawer>
79
</>
80
)
theme/src/components/nav-items.js
+8
-9
@@ -4,7 +4,6 @@ import {Box, StyledOcticon, Link, themeGet} from '@primer/react'
4
import {LinkExternalIcon} from '@primer/octicons-react'
5
import styled from 'styled-components'
6
import BorderBox from './border-box'
7
-import Flex from './flex'
7
import NavHierarchy from '../util/nav-hierarchy'
8
9
const getActiveProps = className => props => {
@@ -90,12 +89,12 @@ function topLevelItems(items, path) {
89
90
return (
91
<BorderBox key={item.title} borderWidth={0} borderRadius={0} borderTopWidth={1} py={3} px={4} role="listitem">
93
- <Flex flexDirection="column">
92
+ <Box display="flex" flexDirection="column">
93
<TopLevelLink to={item.url} key={item.title}>
94
{item.title}
95
</TopLevelLink>
96
{secondLevelItems(children, path)}
98
- </Flex>
97
+ </Box>
98
</BorderBox>
99
)
100
})}
@@ -109,7 +108,7 @@ function secondLevelItems(items, path) {
108
}
109
110
return (
112
- <Flex flexDirection="column" mt={2} role="list">
111
+ <Box display="flex" flexDirection="column" mt={2} role="list">
112
{items.map(item => {
113
const children = NavHierarchy.isActiveUrl(path, item.url)
114
? NavHierarchy.getHierarchy(item, {path, hideVariants: true})
@@ -128,7 +127,7 @@ function secondLevelItems(items, path) {
127
</Box>
128
)
129
})}
131
- </Flex>
130
+ </Box>
131
)
132
}
133
@@ -138,7 +137,7 @@ function thirdLevelItems(items) {
137
}
138
139
return (
141
- <Flex flexDirection="column" mt={2} role="list">
140
+ <Box display="flex" flexDirection="column" mt={2} role="list">
141
{items.map(item => (
142
<Box key={item.title} role="listitem">
143
<ThirdLevelLink key={item.url} to={item.url}>
@@ -146,7 +145,7 @@ function thirdLevelItems(items) {
145
</ThirdLevelLink>
146
</Box>
147
))}
149
- </Flex>
148
+ </Box>
149
)
150
}
151
@@ -159,10 +158,10 @@ function NavItems({location, repositoryUrl}) {
158
{topLevelItems(items, path)}
159
<BorderBox borderWidth={0} borderTopWidth={1} borderRadius={0} py={5} px={4}>
160
<Link href={repositoryUrl} sx={{color: 'inherit'}}>
162
- <Flex justifyContent="space-between" alignItems="center" color="gray.5">
161
+ <Box display="flex" justifyContent="space-between" alignItems="center" color="gray.5">
162
GitHub
163
<StyledOcticon icon={LinkExternalIcon} color="gray.5" />
165
- </Flex>
164
+ </Box>
165
</Link>
166
</BorderBox>
167
</>
theme/src/components/search-results.js
+4
-4
@@ -1,6 +1,5 @@
1
import React from 'react'
2
-import {Text} from '@primer/react'
3
-import Flex from './flex'
2
+import {Box, Text} from '@primer/react'
3
import useSiteMetadata from '../hooks/use-site-metadata'
4
import NavHierarchy from '../util/nav-hierarchy'
5
@@ -16,7 +15,8 @@ function SearchResults({results, getItemProps, highlightedIndex}) {
15
}
16
17
return results.map((item, index) => (
19
- <Flex
18
+ <Box
19
+ display="flex"
20
key={item.path}
21
{...getItemProps({
22
item,
@@ -33,7 +33,7 @@ function SearchResults({results, getItemProps, highlightedIndex}) {
33
{getBreadcrumbs(siteMetadata.shortName, item.path).join(' / ')}
34
</Text>
35
{item.title}
36
- </Flex>
36
+ </Box>
37
))
38
}
39
theme/src/components/sidebar.js
+2
-3
@@ -1,6 +1,5 @@
1
import {Box} from '@primer/react'
2
import React from 'react'
3
-import Flex from './flex'
3
import {HEADER_HEIGHT} from './header'
4
import NavItems from './nav-items'
5
import BorderBox from './border-box'
@@ -18,9 +17,9 @@ function Sidebar({location, repositoryUrl}) {
17
role="navigation"
18
>
19
<BorderBox borderWidth={0} borderRightWidth={1} borderRadius={0} height="100%" style={{overflow: 'auto'}}>
21
- <Flex flexDirection="column" role="list">
20
+ <Box display="flex" flexDirection="column" role="list">
21
<NavItems location={location} items={navItems} repositoryUrl={repositoryUrl} />
23
- </Flex>
22
+ </Box>
23
</BorderBox>
24
</Box>
25
)
theme/src/components/variant-select.js
+23
-25
@@ -8,41 +8,27 @@ import NavHierarchy from '../util/nav-hierarchy'
8
// second folder acts as a variant. If you use <VariantSelect root="/docs">
9
// then you'll get a selection for the different variants (v1.0, v2.0).
10
11
-function VariantSelect(props) {
11
+const VariantSelect = ({variantPages, path}) => {
12
const [open, setOpen] = React.useState(false)
13
- const path = NavHierarchy.getPath(props.location.pathname)
14
- const vp = NavHierarchy.getVariantAndPage(props.root, path)
15
-
16
- if (!vp) {
17
- return null
18
- }
19
-
20
- const variantPages = NavHierarchy.getVariantsForPage(props.root, vp.page)
21
- const items = []
22
- let selectedItem = variantPages[0]
23
-
24
- if (variantPages.length === 0) {
25
- return null
26
- }
27
-
28
- function anchorClickHandler(event, url) {
13
+ const anchorClickHandler = React.useCallback((event, url) => {
14
event.preventDefault()
15
window.location.href = `${url}?v=true`
31
- }
16
+ }, [])
17
33
- function onItemEnterKey(event, url) {
18
+ const onItemEnterKey = React.useCallback((event, url) => {
19
if (event.key === 'Enter') {
20
window.location.href = `${url}?v=true`
21
}
37
- }
22
+ }, [])
23
39
- for (const [index, match] of variantPages.entries()) {
24
+ let selectedItem = variantPages[0]
25
+ const items = variantPages.map((match, index) => {
26
let active = false
27
if (match.page.url === path) {
28
selectedItem = match
29
active = true
30
}
45
- items.push(
31
+ return (
32
<ActionList.Item
33
onKeyDown={e => onItemEnterKey(e, match.page.url)}
34
onClick={e => anchorClickHandler(e, match.page.url)}
@@ -51,9 +37,9 @@ function VariantSelect(props) {
37
active={active}
38
>
39
{match.variant.title}
54
- </ActionList.Item>,
40
+ </ActionList.Item>
41
)
56
- }
42
+ })
43
44
return (
45
<>
@@ -75,4 +61,16 @@ function VariantSelect(props) {
61
)
62
}
63
78
-export default VariantSelect
64
+const VariantSelectLocation = ({root, location}) => {
65
+ const path = NavHierarchy.getPath(location.pathname)
66
+ const vp = NavHierarchy.getVariantAndPage(root, path)
67
+ const variantPages = vp ? NavHierarchy.getVariantsForPage(root, vp.page) : []
68
+
69
+ if (!variantPages.length) {
70
+ return null
71
+ }
72
+
73
+ return <VariantSelect variantPages={variantPages} path={path} />
74
+}
75
+
76
+export default VariantSelectLocation
theme/src/hooks/use-scroll-size.js
new
+37
@@ -0,0 +1,37 @@
1
+import {createRef, useState, useEffect} from 'react'
2
+
3
+/**
4
+ * Resize the scroll handle to the size of the code contents, since the former has to be positioned absolutely.
5
+ */
6
+const useScrollSize = () => {
7
+ const scrollRef = createRef()
8
+ const paddingRef = createRef()
9
+ const [size, setSize] = useState({})
10
+
11
+ useEffect(() => {
12
+ const scrollNode = scrollRef.current
13
+ const paddingNode = paddingRef.current
14
+
15
+ if (!scrollNode || !paddingNode || typeof size.width !== 'undefined') {
16
+ return
17
+ }
18
+
19
+ const parent = scrollNode.parentElement
20
+ const button = paddingNode.firstChild
21
+
22
+ parent.style.position = 'relative'
23
+ const parentStyle = getComputedStyle(parent)
24
+ const paddingTop = parseInt(parentStyle.paddingTop, 10)
25
+ const paddingBottom = parseInt(parentStyle.paddingBottom, 10)
26
+ const paddingRight = parseInt(parentStyle.paddingRight, 10)
27
+
28
+ setSize({
29
+ height: parent.clientHeight - paddingTop - paddingBottom,
30
+ width: parent.scrollWidth - paddingRight + button.clientWidth,
31
+ })
32
+ }, [scrollRef, paddingRef, size])
33
+
34
+ return {scrollRef, paddingRef, size}
35
+}
36
+
37
+export default useScrollSize
theme/src/layout-hero.js
deleted
-31
@@ -1,31 +0,0 @@
1
-import React from 'react'
2
-import {Box} from '@primer/react'
3
-import Container from './components/container'
4
-import Head from './components/head'
5
-import Header from './components/header'
6
-import Hero from './components/hero'
7
-import Sidebar from './components/sidebar'
8
-import Flex from './components/flex'
9
-import * as Slugger from './hooks/use-slugger'
10
-
11
-function HeroLayout({children, pageContext, location}) {
12
- return (
13
- <Slugger.Provider>
14
- <Flex flexDirection="column" minHeight="100vh">
15
- <Head />
16
- <Header location={location} repositoryUrl={pageContext.repositoryUrl} />
17
- <Flex flex="1 1 auto" flexDirection="row" role="main">
18
- <Box display={['none', null, null, 'block']}>
19
- <Sidebar repositoryUrl={pageContext.repositoryUrl} location={location} />
20
- </Box>
21
- <Box width="100%">
22
- <Hero />
23
- <Container>{children}</Container>
24
- </Box>
25
- </Flex>
26
- </Flex>
27
- </Slugger.Provider>
28
- )
29
-}
30
-
31
-export default HeroLayout
theme/src/layout/default.js
renamed
+22
-22
@@ -1,30 +1,30 @@
1
import React from 'react'
2
import {Box, Heading, StyledOcticon, Text, Details} from '@primer/react'
3
import {ChevronDownIcon, ChevronRightIcon} from '@primer/octicons-react'
4
-import Head from './components/head'
5
-import Header, {HEADER_HEIGHT} from './components/header'
6
-import PageFooter from './components/page-footer'
7
-import Sidebar from './components/sidebar'
8
-import TableOfContents from './components/table-of-contents'
9
-import VariantSelect from './components/variant-select'
10
-import BorderBox from './components/border-box'
11
-import Flex from './components/flex'
12
-import * as Slugger from './hooks/use-slugger'
13
-import NavHierarchy from './util/nav-hierarchy'
4
+import Head from '../components/head'
5
+import Header, {HEADER_HEIGHT} from '../components/header'
6
+import PageFooter from '../components/page-footer'
7
+import Sidebar from '../components/sidebar'
8
+import TableOfContents from '../components/table-of-contents'
9
+import VariantSelect from '../components/variant-select'
10
+import BorderBox from '../components/border-box'
11
+import * as Slugger from '../hooks/use-slugger'
12
+import NavHierarchy from '../util/nav-hierarchy'
13
14
function Layout({children, pageContext, location}) {
16
- const {title, description} = pageContext.frontmatter
15
+ const {repositoryUrl, editUrl, contributors, frontmatter, tableOfContents} = pageContext
16
+ const {title, description} = frontmatter
17
18
const variantRoot = NavHierarchy.getVariantRoot(location.pathname)
19
20
return (
21
<Slugger.Provider>
22
- <Flex flexDirection="column" minHeight="100vh">
22
+ <Box display="flex" flexDirection="column" minHeight="100vh">
23
<Head title={title} description={description} />
24
- <Header repositoryUrl={pageContext.repositoryUrl} location={location} />
25
- <Flex flex="1 1 auto" flexDirection="row" css={{zIndex: 0}} role="main">
24
+ <Header repositoryUrl={repositoryUrl} location={location} />
25
+ <Box display="flex" flex="1 1 auto" flexDirection="row" css={{zIndex: 0}} role="main">
26
<Box display={['none', null, null, 'block']}>
27
- <Sidebar repositoryUrl={pageContext.repositoryUrl} location={location} />
27
+ <Sidebar repositoryUrl={repositoryUrl} location={location} />
28
</Box>
29
<Box
30
display="grid"
@@ -60,7 +60,7 @@ function Layout({children, pageContext, location}) {
60
</Box>
61
) : null}
62
</Box>
63
- {pageContext.tableOfContents ? (
63
+ {tableOfContents ? (
64
<Box
65
display={['none', null, 'block']}
66
css={{gridArea: 'table-of-contents', overflow: 'auto'}}
@@ -75,11 +75,11 @@ function Layout({children, pageContext, location}) {
75
<Text display="inline-block" fontWeight="bold" mb={1} id="table-of-content-label">
76
Table of contents
77
</Text>
78
- <TableOfContents items={pageContext.tableOfContents} labelId="table-of-content-label" />
78
+ <TableOfContents items={tableOfContents} labelId="table-of-content-label" />
79
</Box>
80
) : null}
81
<Box css={{gridArea: 'content'}}>
82
- {pageContext.tableOfContents ? (
82
+ {tableOfContents ? (
83
<Box display={['block', null, 'none']} mb={3}>
84
<Details>
85
{({open}) => (
@@ -93,7 +93,7 @@ function Layout({children, pageContext, location}) {
93
Table of contents
94
</Text>
95
<Box pt={1}>
96
- <TableOfContents items={pageContext.tableOfContents} />
96
+ <TableOfContents items={tableOfContents} />
97
</Box>
98
</>
99
)}
@@ -101,11 +101,11 @@ function Layout({children, pageContext, location}) {
101
</Box>
102
) : null}
103
{children}
104
- <PageFooter editUrl={pageContext.editUrl} contributors={pageContext.contributors} />
104
+ <PageFooter editUrl={editUrl} contributors={contributors} />
105
</Box>
106
</Box>
107
- </Flex>
108
- </Flex>
107
+ </Box>
108
+ </Box>
109
</Slugger.Provider>
110
)
111
}
theme/src/layout/hero.js
new
+28
@@ -0,0 +1,28 @@
1
+import React from 'react'
2
+import {Box} from '@primer/react'
3
+import Container from '../components/container'
4
+import Head from '../components/head'
5
+import Header from '../components/header'
6
+import Hero from '../components/hero'
7
+import Sidebar from '../components/sidebar'
8
+import * as Slugger from '../hooks/use-slugger'
9
+
10
+const HeroLayout = ({children, location, pageContext: {repositoryUrl}}) => (
11
+ <Slugger.Provider>
12
+ <Box display="flex" flexDirection="column" minHeight="100vh">
13
+ <Head />
14
+ <Header location={location} repositoryUrl={repositoryUrl} />
15
+ <Box display="flex" flex="1 1 auto" flexDirection="row" role="main">
16
+ <Box display={['none', null, null, 'block']}>
17
+ <Sidebar repositoryUrl={repositoryUrl} location={location} />
18
+ </Box>
19
+ <Box width="100%">
20
+ <Hero />
21
+ <Container>{children}</Container>
22
+ </Box>
23
+ </Box>
24
+ </Box>
25
+ </Slugger.Provider>
26
+)
27
+
28
+export default HeroLayout
theme/src/mdx/blockquote.js
deleted
-19
@@ -1,19 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const Blockquote = styled.blockquote`
5
- margin: 0 0 ${themeGet('space.3')};
6
- padding: 0 ${themeGet('space.3')};
7
- color: ${themeGet('colors.gray.5')};
8
- border-left: 0.25em solid ${themeGet('colors.gray.2')};
9
-
10
- > :first-child {
11
- margin-top: 0;
12
- }
13
-
14
- > :last-child {
15
- margin-bottom: 0;
16
- }
17
-`
18
-
19
-export default Blockquote
theme/src/mdx/code.js
+19
-41
@@ -1,46 +1,11 @@
1
+import React from 'react'
2
import {Box, Text} from '@primer/react'
3
import Highlight, {defaultProps} from 'prism-react-renderer'
4
import githubTheme from 'prism-react-renderer/themes/github'
4
-import React, {useState, useEffect} from 'react'
5
import ClipboardCopy from '../components/clipboard-copy'
6
-import BorderBox from '../components/border-box'
6
+import useScrollSize from '../hooks/use-scroll-size'
7
8
-/**
9
- * Resize the scroll handle to the size of the code contents, since the former has to be positioned absolutely.
10
- */
11
-const useScrollSize = () => {
12
- const scrollRef = React.createRef()
13
- const paddingRef = React.createRef()
14
- const [size, setSize] = useState({})
15
-
16
- useEffect(() => {
17
- const scrollNode = scrollRef.current
18
- const paddingNode = paddingRef.current
19
-
20
- if (!scrollNode || !paddingNode || typeof size.width !== 'undefined') {
21
- return
22
- }
23
-
24
- const parent = scrollNode.parentElement
25
- const button = paddingNode.firstChild
26
-
27
- parent.style.position = 'relative'
28
- const parentStyle = getComputedStyle(parent)
29
- const paddingTop = parseInt(parentStyle.paddingTop, 10)
30
- const paddingBottom = parseInt(parentStyle.paddingBottom, 10)
31
- const paddingRight = parseInt(parentStyle.paddingRight, 10)
32
-
33
- setSize({
34
- height: parent.clientHeight - paddingTop - paddingBottom,
35
- width: parent.scrollWidth - paddingRight + button.clientWidth,
36
- })
37
- }, [scrollRef, paddingRef, size])
38
-
39
- return {scrollRef, paddingRef, size}
40
-}
41
-
42
-function Code({className: parentClass, children}) {
43
- const language = parentClass ? parentClass.replace(/language-/, '') : ''
8
+function Code({className: language = '', children}) {
9
const code = children.trim()
10
const {scrollRef, paddingRef, size} = useScrollSize()
11
@@ -51,9 +16,22 @@ function Code({className: parentClass, children}) {
16
<ClipboardCopy value={code} />
17
</Box>
18
</div>
54
- <Highlight {...defaultProps} code={code} language={language} theme={githubTheme}>
19
+ <Highlight {...defaultProps} code={code} language={language.replace(/language-/, '')} theme={githubTheme}>
20
{({className, style, tokens, getLineProps, getTokenProps}) => (
56
- <BorderBox tabIndex={0} as="pre" className={className} mt={0} mb={3} p={3} border={0} style={{...style, overflow: 'auto'}}>
21
+ <Box
22
+ tabIndex={0}
23
+ borderWidth={1}
24
+ borderStyle="solid"
25
+ borderColor="border.default"
26
+ borderRadius={2}
27
+ as="pre"
28
+ className={className}
29
+ mt={0}
30
+ mb={3}
31
+ p={3}
32
+ border={0}
33
+ style={{...style, overflow: 'auto'}}
34
+ >
35
{/* This is the scroll handle, it is supposed to be focused with keyboard and scroll a wide codebox horizontally */}
36
<div aria-hidden="true" style={{visibility: 'hidden', position: 'absolute', ...size}} ref={scrollRef} />
37
{tokens.map((line, i) => (
@@ -63,7 +41,7 @@ function Code({className: parentClass, children}) {
41
))}
42
</div>
43
))}
66
- </BorderBox>
44
+ </Box>
45
)}
46
</Highlight>
47
</Box>
theme/src/mdx/description-list.js
deleted
-21
@@ -1,21 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const DescriptionList = styled.dl`
5
- padding: 0;
6
-
7
- dt {
8
- padding: 0;
9
- margin-top: ${themeGet('space.3')};
10
- font-size: 1em;
11
- font-style: italic;
12
- font-weight: ${themeGet('fontWeights.bold')};
13
- }
14
-
15
- dd {
16
- padding: 0 ${themeGet('space.3')};
17
- margin: 0 0 ${themeGet('space.3')};
18
- }
19
-`
20
-
21
-export default DescriptionList
theme/src/mdx/heading.js
deleted
-73
@@ -1,73 +0,0 @@
1
-import {Heading, Link, themeGet} from '@primer/react'
2
-import {LinkIcon} from '@primer/octicons-react'
3
-import React from 'react'
4
-import textContent from 'react-addons-text-content'
5
-import styled from 'styled-components'
6
-import {HEADER_HEIGHT} from '../components/header'
7
-import {useSlugger} from '../hooks/use-slugger'
8
-
9
-const StyledHeading = styled(Heading)`
10
- margin-top: ${themeGet('space.4')};
11
- margin-bottom: ${themeGet('space.3')};
12
- scroll-margin-top: ${HEADER_HEIGHT + 24}px;
13
-
14
- & .octicon-link {
15
- visibility: hidden;
16
- }
17
-
18
- &:hover .octicon-link,
19
- &:focus-within .octicon-link {
20
- visibility: visible;
21
- }
22
-`
23
-
24
-function MarkdownHeading({children, ...props}) {
25
- const slugger = useSlugger()
26
- const text = children ? textContent(children) : ''
27
- const id = text ? slugger.slug(text) : ''
28
-
29
- return (
30
- <StyledHeading id={id} {...props}>
31
- <Link href={`#${id}`} sx={{p: 2, ml: -32, color: 'gray.8'}} aria-label={`${text} permalink`}>
32
- <LinkIcon className="octicon-link" verticalAlign="middle" />
33
- </Link>
34
- {children}
35
- </StyledHeading>
36
- )
37
-}
38
-
39
-const StyledH1 = styled(StyledHeading).attrs({as: 'h1'})`
40
- padding-bottom: ${themeGet('space.1')};
41
- font-size: ${themeGet('fontSizes.5')};
42
- border-bottom: 1px solid ${themeGet('colors.gray.2')};
43
-`
44
-
45
-const StyledH2 = styled(StyledHeading).attrs({as: 'h2'})`
46
- padding-bottom: ${themeGet('space.1')};
47
- font-size: ${themeGet('fontSizes.4')};
48
- border-bottom: 1px solid ${themeGet('colors.gray.2')};
49
-`
50
-
51
-const StyledH3 = styled(StyledHeading).attrs({as: 'h3'})`
52
- font-size: ${themeGet('fontSizes.3')};
53
-`
54
-
55
-const StyledH4 = styled(StyledHeading).attrs({as: 'h4'})`
56
- font-size: ${themeGet('fontSizes.2')};
57
-`
58
-
59
-const StyledH5 = styled(StyledHeading).attrs({as: 'h5'})`
60
- font-size: ${themeGet('fontSizes.1')};
61
-`
62
-
63
-const StyledH6 = styled(StyledHeading).attrs({as: 'h6'})`
64
- font-size: ${themeGet('fontSizes.1')};
65
- color: ${themeGet('colors.gray.5')};
66
-`
67
-
68
-export const H1 = props => <MarkdownHeading as={StyledH1} {...props} />
69
-export const H2 = props => <MarkdownHeading as={StyledH2} {...props} />
70
-export const H3 = props => <MarkdownHeading as={StyledH3} {...props} />
71
-export const H4 = props => <MarkdownHeading as={StyledH4} {...props} />
72
-export const H5 = props => <MarkdownHeading as={StyledH5} {...props} />
73
-export const H6 = props => <MarkdownHeading as={StyledH6} {...props} />
theme/src/mdx/horizontal-rule.js
deleted
-12
@@ -1,12 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const HorizontalRule = styled.hr`
5
- height: ${themeGet('space.1')};
6
- padding: 0;
7
- margin: ${themeGet('space.4')} 0;
8
- background-color: ${themeGet('colors.gray.2')};
9
- border: 0;
10
-`
11
-
12
-export default HorizontalRule
theme/src/mdx/image.js
deleted
-10
@@ -1,10 +0,0 @@
1
-import {themeGet} from '@primer/react'
2
-import styled from 'styled-components'
3
-
4
-const Image = styled.img`
5
- max-width: 100%;
6
- box-sizing: content-box;
7
- background-color: ${themeGet('colors.white')};
8
-`
9
-
10
-export default Image
theme/src/mdx/index.js
+277
-41
@@ -1,50 +1,286 @@
1
import React from 'react'
2
-import {useLocation} from '@reach/router' // eslint-disable-line import/no-unresolved
3
-import {Box, Link} from '@primer/react'
4
-import {Link as GatsbyLink} from 'gatsby'
5
-import NavHierarchy from '../util/nav-hierarchy'
6
-
7
-function showHierarchy(items, props, depth = 1) {
8
- let hierarchy
9
-
10
- if (props.depth && depth > props.depth) {
11
- return null
12
- }
13
-
14
- return (
15
- <Box as="ul">
16
- {items.map(item => (
17
- <Box as="li" key={item.url}>
18
- <Link as={GatsbyLink} key={item.title} to={item.url}>
19
- {item.title}
20
- </Link>
21
- {item.description != null ? (
22
- <>
23
- <Box style={{fontSize: '0.85em', marginBottom: '0.5em'}}>{item.description}</Box>
24
- </>
25
- ) : null}
26
- {(hierarchy = NavHierarchy.getHierarchy(item, props)) != null
27
- ? showHierarchy(hierarchy, props, depth + 1)
28
- : null}
29
- </Box>
30
- ))}
31
- </Box>
32
- )
2
+import {Box, Heading, themeGet, Text, Link as PrimerLink} from '@primer/react'
3
+import styled from 'styled-components'
4
+import {withPrefix} from 'gatsby'
5
+import {LinkIcon} from '@primer/octicons-react'
6
+import textContent from 'react-addons-text-content'
7
+import Code from './code'
8
+import NavHierarchy from './nav-hierarchy'
9
+import {HEADER_HEIGHT} from '../components/header'
10
+import {useSlugger} from '../hooks/use-slugger'
11
+
12
+const required = (prop, name) => {
13
+ if (!prop) {
14
+ throw new Error(`${name} prop is required`)
15
+ }
16
+ return prop
17
+}
18
+
19
+export const Link = props => {
20
+ return <PrimerLink {...props} underline={true} />
21
}
22
35
-function Index(props) {
36
- const location = useLocation()
37
- const path = NavHierarchy.getLocation(location.pathname)
38
- const root = (props.root ? props.root : path).replace(/\/+$/g, '')
23
+export {Code, NavHierarchy as Index}
24
+
25
+export const Pre = ({children}) => children
26
+
27
+const SkipLinkBase = props => (
28
+ <PrimerLink {...props} href="#skip-nav" sx={{backgroundColor: 'blue.6', color: 'white', p: 3, fontSize: 1}}>
29
+ Skip to content
30
+ </PrimerLink>
31
+)
32
+
33
+export const SkipLink = styled(SkipLinkBase)`
34
+ z-index: 20;
35
+ width: auto;
36
+ height: auto;
37
+ clip: auto;
38
+ position: absolute;
39
+ overflow: hidden;
40
40
- const rootItem = NavHierarchy.getItem(root)
41
- const hierarchy = NavHierarchy.getHierarchy(rootItem, props)
41
+ // The following rules are to ensure that the element
42
+ // is visually hidden, unless it has focus. This is the recommended
43
+ // way to hide content from:
44
+ // https://webaim.org/techniques/css/invisiblecontent/#techniques
45
43
- if (!hierarchy) {
44
- throw new Error(`could not find entry for ${root}`)
46
+ &:not(:focus) {
47
+ clip: rect(1px, 1px, 1px, 1px);
48
+ clip-path: inset(50%);
49
+ height: 1px;
50
+ width: 1px;
51
+ margin: -1px;
52
+ padding: 0;
53
}
54
+`
55
+
56
+const StyledHeading = styled(Heading)`
57
+ margin-top: ${themeGet('space.4')};
58
+ margin-bottom: ${themeGet('space.3')};
59
+ scroll-margin-top: ${HEADER_HEIGHT + 24}px;
60
+
61
+ & .octicon-link {
62
+ visibility: hidden;
63
+ }
64
+
65
+ &:hover .octicon-link,
66
+ &:focus-within .octicon-link {
67
+ visibility: visible;
68
+ }
69
+`
70
+
71
+const Headings = {
72
+ Markdown: ({children, ...props}) => {
73
+ const slugger = useSlugger()
74
+ const text = children ? textContent(children) : ''
75
+ const id = text ? slugger.slug(text) : ''
76
47
- return showHierarchy(hierarchy, props)
77
+ return (
78
+ <StyledHeading id={id} {...props}>
79
+ <PrimerLink href={`#${id}`} sx={{p: 2, ml: -32, color: 'gray.8'}} aria-label={`${text} permalink`}>
80
+ <LinkIcon className="octicon-link" verticalAlign="middle" />
81
+ </PrimerLink>
82
+ {children}
83
+ </StyledHeading>
84
+ )
85
+ },
86
+ h1: styled(StyledHeading).attrs({as: 'h1'})`
87
+ padding-bottom: ${themeGet('space.1')};
88
+ font-size: ${themeGet('fontSizes.5')};
89
+ border-bottom: 1px solid ${themeGet('colors.gray.2')};
90
+ `,
91
+ h2: styled(StyledHeading).attrs({as: 'h2'})`
92
+ padding-bottom: ${themeGet('space.1')};
93
+ font-size: ${themeGet('fontSizes.4')};
94
+ border-bottom: 1px solid ${themeGet('colors.gray.2')};
95
+ `,
96
+ h3: styled(StyledHeading).attrs({as: 'h3'})`
97
+ font-size: ${themeGet('fontSizes.3')};
98
+ `,
99
+ h4: styled(StyledHeading).attrs({as: 'h4'})`
100
+ font-size: ${themeGet('fontSizes.2')};
101
+ `,
102
+ h5: styled(StyledHeading).attrs({as: 'h5'})`
103
+ font-size: ${themeGet('fontSizes.1')};
104
+ `,
105
+ h6: styled(StyledHeading).attrs({as: 'h6'})`
106
+ font-size: ${themeGet('fontSizes.1')};
107
+ color: ${themeGet('colors.gray.5')};
108
+ `,
109
+ wrap(as) {
110
+ return props => <Headings.Markdown as={Headings[as]} {...props} />
111
+ },
112
}
113
50
-export default Index
114
+export const H1 = Headings.wrap('h1')
115
+export const H2 = Headings.wrap('h2')
116
+export const H3 = Headings.wrap('h3')
117
+export const H4 = Headings.wrap('h4')
118
+export const H5 = Headings.wrap('h5')
119
+export const H6 = Headings.wrap('h6')
120
+
121
+export const Blockquote = styled.blockquote`
122
+ margin: 0 0 ${themeGet('space.3')};
123
+ padding: 0 ${themeGet('space.3')};
124
+ color: ${themeGet('colors.gray.5')};
125
+ border-left: 0.25em solid ${themeGet('colors.gray.2')};
126
+
127
+ > :first-child {
128
+ margin-top: 0;
129
+ }
130
+
131
+ > :last-child {
132
+ margin-bottom: 0;
133
+ }
134
+`
135
+
136
+export const DescriptionList = styled.dl`
137
+ padding: 0;
138
+
139
+ dt {
140
+ padding: 0;
141
+ margin-top: ${themeGet('space.3')};
142
+ font-size: 1em;
143
+ font-style: italic;
144
+ font-weight: ${themeGet('fontWeights.bold')};
145
+ }
146
+
147
+ dd {
148
+ padding: 0 ${themeGet('space.3')};
149
+ margin: 0 0 ${themeGet('space.3')};
150
+ }
151
+`
152
+
153
+export const HorizontalRule = styled.hr`
154
+ height: ${themeGet('space.1')};
155
+ padding: 0;
156
+ margin: ${themeGet('space.4')} 0;
157
+ background-color: ${themeGet('colors.gray.2')};
158
+ border: 0;
159
+`
160
+
161
+export const Image = styled.img`
162
+ max-width: 100%;
163
+ box-sizing: content-box;
164
+ background-color: ${themeGet('colors.white')};
165
+`
166
+
167
+export const InlineCode = styled.code`
168
+ padding: 0.2em 0.4em;
169
+ font-family: ${themeGet('fonts.mono')};
170
+ font-size: 85%;
171
+ background-color: ${themeGet('colors.gray.1')};
172
+ border-radius: ${themeGet('radii.1')};
173
+`
174
+
175
+export const UnorderedList = styled.ul`
176
+ padding-left: 2em;
177
+
178
+ ul,
179
+ ol {
180
+ margin-top: 0;
181
+ margin-bottom: 0;
182
+ }
183
+
184
+ li {
185
+ word-wrap: break-all;
186
+ }
187
+
188
+ li > p {
189
+ margin-top: ${themeGet('space.3')};
190
+ }
191
+
192
+ li + li {
193
+ margin-top: ${themeGet('space.1')};
194
+ }
195
+`
196
+
197
+export const OrderedList = UnorderedList.withComponent('ol')
198
+
199
+export const Paragraph = styled.p`
200
+ margin: 0 0 ${themeGet('space.3')};
201
+`
202
+
203
+export const Table = styled.table`
204
+ display: block;
205
+ width: 100%;
206
+ margin: 0 0 ${themeGet('space.3')};
207
+ overflow: auto;
208
+
209
+ th {
210
+ font-weight: ${themeGet('fontWeights.bold')};
211
+ }
212
+
213
+ th,
214
+ td {
215
+ padding: ${themeGet('space.2')} ${themeGet('space.3')};
216
+ border: 1px solid ${themeGet('colors.gray.2')};
217
+ }
218
+
219
+ tr {
220
+ background-color: ${themeGet('colors.white')};
221
+ border-top: 1px solid ${themeGet('colors.gray.2')};
222
+
223
+ &:nth-child(2n) {
224
+ background-color: ${themeGet('colors.gray.1')};
225
+ }
226
+ }
227
+
228
+ img {
229
+ background-color: transparent;
230
+ }
231
+`
232
+
233
+export const Note = ({children}) => (
234
+ <Box
235
+ borderWidth={1}
236
+ borderStyle="solid"
237
+ borderRadius={0}
238
+ borderColor="blue.1"
239
+ backgroundColor="blue.0"
240
+ px={3}
241
+ py={2}
242
+ my={4}
243
+ >
244
+ {React.Children.toArray(children).map((child, index, list) =>
245
+ React.cloneElement(child, {
246
+ style: index === list.length - 1 ? {marginBottom: '0'} : null,
247
+ }),
248
+ )}
249
+ </Box>
250
+)
251
+
252
+export const Prompt = ({children}) => (
253
+ <Box
254
+ as="pre"
255
+ mt={0}
256
+ mb={3}
257
+ p={3}
258
+ border={0}
259
+ style={{
260
+ color: 'rgb(57, 58, 52)',
261
+ backgroundColor: 'rgb(246, 248, 250)',
262
+ overflow: 'auto',
263
+ }}
264
+ >
265
+ <Text fontFamily="mono" fontSize={1}>
266
+ {children}
267
+ </Text>
268
+ </Box>
269
+)
270
+
271
+export const PromptReply = ({children}) => <strong>{children}</strong>
272
+
273
+export const Screenshot = props => (
274
+ <div>
275
+ <img
276
+ src={withPrefix(required(props.src, 'src'))}
277
+ alt={required(props.alt, 'alt')}
278
+ style={{
279
+ border: 'solid 1px #999999',
280
+ marginTop: '15px',
281
+ maxWidth: 'min(100%, 525px)',
282
+ maxHeight: '300px',
283
+ }}
284
+ />
285
+ </div>
286
+)
theme/src/mdx/inline-code.js
deleted
-12
@@ -1,12 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const InlineCode = styled.code`
5
- padding: 0.2em 0.4em;
6
- font-family: ${themeGet('fonts.mono')};
7
- font-size: 85%;
8
- background-color: ${themeGet('colors.gray.1')};
9
- border-radius: ${themeGet('radii.1')};
10
-`
11
-
12
-export default InlineCode
theme/src/mdx/list.js
deleted
-26
@@ -1,26 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const List = styled.ul`
5
- padding-left: 2em;
6
-
7
- ul,
8
- ol {
9
- margin-top: 0;
10
- margin-bottom: 0;
11
- }
12
-
13
- li {
14
- word-wrap: break-all;
15
- }
16
-
17
- li > p {
18
- margin-top: ${themeGet('space.3')};
19
- }
20
-
21
- li + li {
22
- margin-top: ${themeGet('space.1')};
23
- }
24
-`
25
-
26
-export default List
theme/src/mdx/nav-hierarchy.js
new
+48
@@ -0,0 +1,48 @@
1
+import React from 'react'
2
+import {useLocation} from '@reach/router' // eslint-disable-line import/no-unresolved
3
+import {Box, Link} from '@primer/react'
4
+import {Link as GatsbyLink} from 'gatsby'
5
+import NavHierarchy from '../util/nav-hierarchy'
6
+
7
+function showHierarchy(items, props, depth = 1) {
8
+ let hierarchy
9
+
10
+ if (props.depth && depth > props.depth) {
11
+ return null
12
+ }
13
+
14
+ return (
15
+ <Box as="ul">
16
+ {items.map(item => (
17
+ <Box as="li" key={item.url}>
18
+ <Link as={GatsbyLink} key={item.title} to={item.url}>
19
+ {item.title}
20
+ </Link>
21
+ {item.description != null ? (
22
+ <Box style={{fontSize: '0.85em', marginBottom: '0.5em'}}>{item.description}</Box>
23
+ ) : null}
24
+ {(hierarchy = NavHierarchy.getHierarchy(item, props)) != null
25
+ ? showHierarchy(hierarchy, props, depth + 1)
26
+ : null}
27
+ </Box>
28
+ ))}
29
+ </Box>
30
+ )
31
+}
32
+
33
+function Index(props) {
34
+ const location = useLocation()
35
+ const path = NavHierarchy.getLocation(location.pathname)
36
+ const root = (props.root ? props.root : path).replace(/\/+$/g, '')
37
+
38
+ const rootItem = NavHierarchy.getItem(root)
39
+ const hierarchy = NavHierarchy.getHierarchy(rootItem, props)
40
+
41
+ if (!hierarchy) {
42
+ throw new Error(`could not find entry for ${root}`)
43
+ }
44
+
45
+ return showHierarchy(hierarchy, props)
46
+}
47
+
48
+export default Index
theme/src/mdx/note.js
deleted
-16
@@ -1,16 +0,0 @@
1
-import React from 'react'
2
-import BorderBox from '../components/border-box'
3
-
4
-function Note({children}) {
5
- return (
6
- <BorderBox borderWidth={1} borderRadius={0} borderColor="blue.1" backgroundColor="blue.0" px={3} py={2} my={4}>
7
- {React.Children.toArray(children).map((child, index, list) =>
8
- React.cloneElement(child, {
9
- style: index === list.length - 1 ? {marginBottom: '0'} : null,
10
- }),
11
- )}
12
- </BorderBox>
13
- )
14
-}
15
-
16
-export default Note
theme/src/mdx/paragraph.js
deleted
-8
@@ -1,8 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const Paragraph = styled.p`
5
- margin: 0 0 ${themeGet('space.3')};
6
-`
7
-
8
-export default Paragraph
theme/src/mdx/prompt-reply.js
deleted
-7
@@ -1,7 +0,0 @@
1
-import React from 'react'
2
-
3
-function PromptReply({children}) {
4
- return <strong>{children}</strong>
5
-}
6
-
7
-export default PromptReply
theme/src/mdx/prompt.js
deleted
-26
@@ -1,26 +0,0 @@
1
-import React from 'react'
2
-import {Text} from '@primer/react'
3
-import BorderBox from '../components/border-box'
4
-
5
-function Prompt({children}) {
6
- return (
7
- <BorderBox
8
- as="pre"
9
- mt={0}
10
- mb={3}
11
- p={3}
12
- border={0}
13
- style={{
14
- color: 'rgb(57, 58, 52)',
15
- backgroundColor: 'rgb(246, 248, 250)',
16
- overflow: 'auto',
17
- }}
18
- >
19
- <Text fontFamily="mono" fontSize={1}>
20
- {children}
21
- </Text>
22
- </BorderBox>
23
- )
24
-}
25
-
26
-export default Prompt
theme/src/mdx/screenshot.js
deleted
-29
@@ -1,29 +0,0 @@
1
-import React from 'react'
2
-import {withPrefix} from 'gatsby'
3
-
4
-function Screenshot(props) {
5
- if (!props.src) {
6
- throw new Error('src is required')
7
- }
8
-
9
- if (!props.alt) {
10
- throw new Error('alt text is required')
11
- }
12
-
13
- return (
14
- <div>
15
- <img
16
- src={withPrefix(props.src)}
17
- alt={props.alt}
18
- style={{
19
- border: 'solid 1px #999999',
20
- marginTop: '15px',
21
- maxWidth: 'min(100%, 525px)',
22
- maxHeight: '300px',
23
- }}
24
- />
25
- </div>
26
- )
27
-}
28
-
29
-export default Screenshot
theme/src/mdx/table.js
deleted
-34
@@ -1,34 +0,0 @@
1
-import styled from 'styled-components'
2
-import {themeGet} from '@primer/react'
3
-
4
-const Table = styled.table`
5
- display: block;
6
- width: 100%;
7
- margin: 0 0 ${themeGet('space.3')};
8
- overflow: auto;
9
-
10
- th {
11
- font-weight: ${themeGet('fontWeights.bold')};
12
- }
13
-
14
- th,
15
- td {
16
- padding: ${themeGet('space.2')} ${themeGet('space.3')};
17
- border: 1px solid ${themeGet('colors.gray.2')};
18
- }
19
-
20
- tr {
21
- background-color: ${themeGet('colors.white')};
22
- border-top: 1px solid ${themeGet('colors.gray.2')};
23
-
24
- &:nth-child(2n) {
25
- background-color: ${themeGet('colors.gray.1')};
26
- }
27
- }
28
-
29
- img {
30
- background-color: transparent;
31
- }
32
-`
33
-
34
-export default Table
theme/src/page-element.js
+9
-39
@@ -1,6 +1,7 @@
1
-import {BaseStyles, Link} from '@primer/react'
1
import React from 'react'
3
-import styled, {createGlobalStyle} from 'styled-components'
2
+import {BaseStyles} from '@primer/react'
3
+import {createGlobalStyle} from 'styled-components'
4
+import {SkipLink} from './mdx'
5
6
const GlobalStyle = createGlobalStyle`
7
::placeholder {
@@ -8,43 +9,12 @@ const GlobalStyle = createGlobalStyle`
9
}
10
`
11
11
-const SkipLinkBase = props => (
12
- <Link {...props} href="#skip-nav" sx={{backgroundColor: 'blue.6', color: 'white', p: 3, fontSize: 1}}>
13
- Skip to content
14
- </Link>
12
+const PageElement = ({element}) => (
13
+ <BaseStyles>
14
+ <GlobalStyle />
15
+ <SkipLink />
16
+ {element}
17
+ </BaseStyles>
18
)
19
17
-const SkipLink = styled(SkipLinkBase)`
18
- z-index: 20;
19
- width: auto;
20
- height: auto;
21
- clip: auto;
22
- position: absolute;
23
- overflow: hidden;
24
-
25
- // The following rules are to ensure that the element
26
- // is visually hidden, unless it has focus. This is the recommended
27
- // way to hide content from:
28
- // https://webaim.org/techniques/css/invisiblecontent/#techniques
29
-
30
- &:not(:focus) {
31
- clip: rect(1px, 1px, 1px, 1px);
32
- clip-path: inset(50%);
33
- height: 1px;
34
- width: 1px;
35
- margin: -1px;
36
- padding: 0;
37
- }
38
-`
39
-
40
-function PageElement({element}) {
41
- return (
42
- <BaseStyles>
43
- <GlobalStyle />
44
- <SkipLink />
45
- {element}
46
- </BaseStyles>
47
- )
48
-}
49
-
20
export default PageElement
theme/src/root-element.js
+33
-55
@@ -1,63 +1,41 @@
1
import React from 'react'
2
import {MDXProvider} from '@mdx-js/react'
3
-import {Link, SSRProvider, ThemeProvider, theme} from '@primer/react'
4
-import Blockquote from './mdx/blockquote'
5
-import Code from './mdx/code'
6
-import DescriptionList from './mdx/description-list'
7
-import {H1, H2, H3, H4, H5, H6} from './mdx/heading'
8
-import HorizontalRule from './mdx/horizontal-rule'
9
-import Image from './mdx/image'
10
-import InlineCode from './mdx/inline-code'
11
-import List from './mdx/list'
12
-import Paragraph from './mdx/paragraph'
13
-import Table from './mdx/table'
14
-import Index from './mdx/index'
15
-import Note from './mdx/note'
16
-import Prompt from './mdx/prompt'
17
-import PromptReply from './mdx/prompt-reply'
18
-import Screenshot from './mdx/screenshot'
19
-
20
-function UnderlinedLink(props) {
21
- return <Link {...props} underline={true} />
22
-}
23
-
24
-console.log(theme)
3
+import {SSRProvider, ThemeProvider} from '@primer/react'
4
+import * as Components from './mdx'
5
6
const components = {
27
- a: UnderlinedLink,
28
- pre: props => props.children,
29
- code: Code,
30
- inlineCode: InlineCode,
31
- table: Table,
32
- img: Image,
33
- p: Paragraph,
34
- hr: HorizontalRule,
35
- blockquote: Blockquote,
36
- h1: H1,
37
- h2: H2,
38
- h3: H3,
39
- h4: H4,
40
- h5: H5,
41
- h6: H6,
42
- ul: List,
43
- ol: List.withComponent('ol'),
44
- dl: DescriptionList,
45
- Index,
46
- Note,
47
- Prompt,
48
- PromptReply,
49
- Screenshot,
50
- Link: UnderlinedLink,
7
+ a: Components.Link,
8
+ pre: Components.Pre,
9
+ code: Components.Code,
10
+ inlineCode: Components.InlineCode,
11
+ table: Components.Table,
12
+ img: Components.Image,
13
+ p: Components.Paragraph,
14
+ hr: Components.HorizontalRule,
15
+ blockquote: Components.Blockquote,
16
+ h1: Components.H1,
17
+ h2: Components.H2,
18
+ h3: Components.H3,
19
+ h4: Components.H4,
20
+ h5: Components.H5,
21
+ h6: Components.H6,
22
+ ul: Components.UnorderedList,
23
+ ol: Components.OrderedList,
24
+ dl: Components.DescriptionList,
25
+ Index: Components.Index,
26
+ Note: Components.Note,
27
+ Prompt: Components.Prompt,
28
+ PromptReply: Components.PromptReply,
29
+ Screenshot: Components.Screenshot,
30
+ Link: Components.Link,
31
}
32
53
-function RootElement({element}) {
54
- return (
55
- <SSRProvider>
56
- <MDXProvider components={components}>
57
- <ThemeProvider>{element}</ThemeProvider>
58
- </MDXProvider>
59
- </SSRProvider>
60
- )
61
-}
33
+const RootElement = ({element}) => (
34
+ <SSRProvider>
35
+ <MDXProvider components={components}>
36
+ <ThemeProvider>{element}</ThemeProvider>
37
+ </MDXProvider>
38
+ </SSRProvider>
39
+)
40
41
export default RootElement