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