@primer/doctocat-nextjs 0.7.0 → 0.7.1-rc.bf9f37a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/components/content/caption/Caption.module.css +6 -0
- package/components/content/caption/Caption.tsx +7 -2
- package/components/content/dos-and-donts/DosAndDonts.module.css +5 -1
- package/components/content/dos-and-donts/DosAndDonts.tsx +3 -15
- package/components/layout/nav-drawer/Drawer.module.css +19 -0
- package/components/layout/nav-drawer/Drawer.tsx +6 -9
- package/components/layout/root-layout/Theme.module.css +35 -0
- package/components/layout/root-layout/Theme.tsx +17 -32
- package/components/layout/sidebar/Sidebar.module.css +8 -0
- package/components/layout/sidebar/Sidebar.tsx +8 -9
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @primer/doctocat-nextjs
|
|
2
2
|
|
|
3
|
+
## 0.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#68](https://github.com/primer/doctocat-nextjs/pull/68) [`b75584e`](https://github.com/primer/doctocat-nextjs/commit/b75584edb6936a70ea94925fc743989422cc3d9a) Thanks [@janmaarten-a11y](https://github.com/janmaarten-a11y)! - Improve screen reader accessibility by updating sidebar navigation heading hierarchy. The sidebar title now uses a semantic `<Heading>` component with visually hidden text to clarify it's a navigation area, and is properly connected to the `<NavList>` via `aria-labelledby`.
|
|
8
|
+
|
|
3
9
|
## 0.7.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React, {PropsWithChildren} from 'react'
|
|
2
|
-
import
|
|
2
|
+
import styles from './Caption.module.css'
|
|
3
3
|
|
|
4
4
|
export function Caption(props: PropsWithChildren) {
|
|
5
|
-
|
|
5
|
+
const {children, ...rest} = props
|
|
6
|
+
return (
|
|
7
|
+
<span className={styles.Caption} {...rest}>
|
|
8
|
+
{children}
|
|
9
|
+
</span>
|
|
10
|
+
)
|
|
6
11
|
}
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
color: var(--base-color-scale-white-0);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
.header {
|
|
43
|
+
color: var(--fgColor-onEmphasis, var(--color-fg-on-emphasis));
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
.content {
|
|
43
47
|
display: flex;
|
|
44
48
|
flex-direction: column;
|
|
@@ -55,6 +59,6 @@
|
|
|
55
59
|
|
|
56
60
|
.indentedContent {
|
|
57
61
|
margin: 0;
|
|
58
|
-
border-left: 4px solid;
|
|
62
|
+
border-left: 4px solid var(--brand-color-border-default);
|
|
59
63
|
padding-left: 1rem;
|
|
60
64
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {Box} from '@primer/react'
|
|
3
2
|
import clsx from 'clsx'
|
|
4
3
|
import styles from './DosAndDonts.module.css'
|
|
5
4
|
|
|
@@ -39,22 +38,11 @@ type DoDontBaseProps = {
|
|
|
39
38
|
export function DoDontBase({children, title, indented, className, ...rest}: React.PropsWithChildren<DoDontBaseProps>) {
|
|
40
39
|
return (
|
|
41
40
|
<div className={clsx(`exclude-from-prose`, styles.doDontBase, className)} {...rest}>
|
|
42
|
-
<
|
|
43
|
-
className={styles.header}
|
|
44
|
-
sx={{
|
|
45
|
-
color: 'var(--fgColor-onEmphasis, var(--color-fg-on-emphasis))',
|
|
46
|
-
}}
|
|
47
|
-
>
|
|
41
|
+
<div className={styles.header}>
|
|
48
42
|
<span className={styles.headerText}>{title}</span>
|
|
49
|
-
</
|
|
43
|
+
</div>
|
|
50
44
|
<div className={styles.content}>
|
|
51
|
-
{indented ?
|
|
52
|
-
<blockquote className={styles.indentedContent} style={{borderLeftColor: 'var(--brand-color-border-default)'}}>
|
|
53
|
-
{children}
|
|
54
|
-
</blockquote>
|
|
55
|
-
) : (
|
|
56
|
-
children
|
|
57
|
-
)}
|
|
45
|
+
{indented ? <blockquote className={styles.indentedContent}>{children}</blockquote> : children}
|
|
58
46
|
</div>
|
|
59
47
|
</div>
|
|
60
48
|
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.DrawerOverlay {
|
|
2
|
+
position: fixed;
|
|
3
|
+
inset: 0;
|
|
4
|
+
background: rgba(0, 0, 0, 0.5);
|
|
5
|
+
z-index: 1;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.DrawerPanel {
|
|
9
|
+
position: fixed;
|
|
10
|
+
top: 0;
|
|
11
|
+
right: 0;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
width: 300px;
|
|
14
|
+
background: var(--brand-color-canvas-default, var(--color-canvas-default));
|
|
15
|
+
z-index: 1;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, {PropsWithChildren} from 'react'
|
|
2
|
-
import {Box} from '@primer/react'
|
|
3
2
|
import {AnimatePresence, motion} from 'framer-motion'
|
|
4
3
|
import {FocusOn} from 'react-focus-on'
|
|
4
|
+
import styles from './Drawer.module.css'
|
|
5
5
|
|
|
6
6
|
type Drawer = {
|
|
7
7
|
isOpen: boolean
|
|
@@ -22,29 +22,26 @@ export function Drawer({isOpen, onDismiss, children}: PropsWithChildren<Drawer>)
|
|
|
22
22
|
tabIndex={0}
|
|
23
23
|
>
|
|
24
24
|
<FocusOn returnFocus={true} onEscapeKey={() => onDismiss()}>
|
|
25
|
-
<
|
|
25
|
+
<motion.div
|
|
26
26
|
key="overlay"
|
|
27
|
-
|
|
27
|
+
className={styles.DrawerOverlay}
|
|
28
28
|
initial={{opacity: 0}}
|
|
29
29
|
animate={{opacity: 1}}
|
|
30
30
|
exit={{opacity: 0}}
|
|
31
31
|
transition={{type: 'tween'}}
|
|
32
32
|
onClick={() => onDismiss()}
|
|
33
|
-
sx={{top: 0, right: 0, bottom: 0, left: 0, bg: 'rgba(0, 0, 0, 0.5)', position: 'fixed', zIndex: 1}}
|
|
34
33
|
/>
|
|
35
34
|
|
|
36
|
-
<
|
|
35
|
+
<motion.div
|
|
37
36
|
key="drawer"
|
|
38
|
-
|
|
37
|
+
className={styles.DrawerPanel}
|
|
39
38
|
initial={{x: '100%'}}
|
|
40
39
|
animate={{x: 0}}
|
|
41
40
|
exit={{x: '100%'}}
|
|
42
41
|
transition={{type: 'tween', duration: 0.2}}
|
|
43
|
-
style={{zIndex: 1}}
|
|
44
|
-
sx={{width: 300, top: 0, right: 0, bottom: 0, bg: 'gray.0', position: 'fixed'}}
|
|
45
42
|
>
|
|
46
43
|
{children}
|
|
47
|
-
</
|
|
44
|
+
</motion.div>
|
|
48
45
|
</FocusOn>
|
|
49
46
|
</div>
|
|
50
47
|
) : null}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.StickyHeader {
|
|
2
|
+
position: sticky;
|
|
3
|
+
top: 0;
|
|
4
|
+
z-index: 99;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.ContentContainer {
|
|
8
|
+
max-width: 1200px;
|
|
9
|
+
width: 100%;
|
|
10
|
+
margin: 0 auto;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.BreadcrumbRoot,
|
|
14
|
+
.BreadcrumbItem {
|
|
15
|
+
color: var(--brand-InlineLink-color-rest);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.BreadcrumbItem {
|
|
19
|
+
text-transform: capitalize;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.HeroImageWrapper {
|
|
23
|
+
padding-block-start: var(--base-size-16);
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
.ActionsWrapper {
|
|
29
|
+
padding-block-start: var(--base-size-16);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
.RelatedLinks {
|
|
34
|
+
padding-top: var(--base-size-20);
|
|
35
|
+
}
|
|
@@ -4,13 +4,12 @@ import NextLink from 'next/link'
|
|
|
4
4
|
import Head from 'next/head'
|
|
5
5
|
import type {Folder, MdxFile, PageMapItem} from 'nextra'
|
|
6
6
|
import {useFSRoute} from 'nextra/hooks'
|
|
7
|
-
import {BaseStyles,
|
|
7
|
+
import {BaseStyles, Breadcrumbs, PageLayout, ThemeProvider} from '@primer/react'
|
|
8
8
|
import '@primer/primitives/dist/css/functional/themes/light.css'
|
|
9
9
|
import '@primer/primitives/dist/css/functional/themes/dark.css'
|
|
10
10
|
import {
|
|
11
11
|
Animate,
|
|
12
12
|
AnimationProvider,
|
|
13
|
-
Box,
|
|
14
13
|
ButtonGroup,
|
|
15
14
|
ThemeProvider as BrandThemeProvider,
|
|
16
15
|
Button,
|
|
@@ -38,6 +37,7 @@ import {RelatedContentLinks} from '../related-content-links/RelatedContentLinks'
|
|
|
38
37
|
import {getRelatedPages} from '../related-content-links/getRelatedPages'
|
|
39
38
|
import {hasChildren} from '../../../helpers/hasChildren'
|
|
40
39
|
import {Footer} from '../footer/Footer'
|
|
40
|
+
import styles from './Theme.module.css'
|
|
41
41
|
|
|
42
42
|
const repoSrcPath = process.env.NEXT_PUBLIC_REPO_SRC_PATH || ''
|
|
43
43
|
const repoURL = process.env.NEXT_PUBLIC_REPO || ''
|
|
@@ -119,16 +119,10 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
119
119
|
</Head>
|
|
120
120
|
|
|
121
121
|
<ContentWrapper disableAnimations={disablePageAnimation}>
|
|
122
|
-
<
|
|
123
|
-
sx={{
|
|
124
|
-
position: 'sticky',
|
|
125
|
-
top: 0,
|
|
126
|
-
zIndex: 99,
|
|
127
|
-
}}
|
|
128
|
-
>
|
|
122
|
+
<div className={styles.StickyHeader}>
|
|
129
123
|
<SkipToMainContent href="#main">Skip to main content</SkipToMainContent>
|
|
130
124
|
<Header flatDocsDirectories={flatDocsDirectories} siteTitle={siteTitle} pageMap={pageMap} />
|
|
131
|
-
</
|
|
125
|
+
</div>
|
|
132
126
|
<PageLayout rowGap="none" columnGap="none" padding="none" containerWidth="full">
|
|
133
127
|
<PageLayout.Pane
|
|
134
128
|
width="small"
|
|
@@ -145,20 +139,14 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
145
139
|
</PageLayout.Pane>
|
|
146
140
|
<PageLayout.Content padding="normal">
|
|
147
141
|
<div id="main">
|
|
148
|
-
<
|
|
142
|
+
<div style={!isHomePage ? {maxWidth: 1200, width: '100%', margin: '0 auto'} : undefined}>
|
|
149
143
|
<Stack direction="vertical" padding="none" gap="spacious">
|
|
150
144
|
{!isHomePage && (
|
|
151
145
|
<>
|
|
152
146
|
{activePath.length > 0 && (
|
|
153
|
-
<Breadcrumbs>
|
|
147
|
+
<Breadcrumbs className={styles.BreadcrumbRoot}>
|
|
154
148
|
{(activeHeaderLink || siteTitle) && (
|
|
155
|
-
<Breadcrumbs.Item
|
|
156
|
-
as={NextLink}
|
|
157
|
-
href="/"
|
|
158
|
-
sx={{
|
|
159
|
-
color: 'var(--brand-InlineLink-color-rest)',
|
|
160
|
-
}}
|
|
161
|
-
>
|
|
149
|
+
<Breadcrumbs.Item as={NextLink} href="/">
|
|
162
150
|
{activeHeaderLink ? activeHeaderLink.title : siteTitle}
|
|
163
151
|
</Breadcrumbs.Item>
|
|
164
152
|
)}
|
|
@@ -192,10 +180,7 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
192
180
|
key={item.name}
|
|
193
181
|
href={item.route}
|
|
194
182
|
selected={isLastItem}
|
|
195
|
-
|
|
196
|
-
textTransform: 'capitalize',
|
|
197
|
-
color: 'var(--brand-InlineLink-color-rest)',
|
|
198
|
-
}}
|
|
183
|
+
className={styles.BreadcrumbItem}
|
|
199
184
|
>
|
|
200
185
|
{itemTitle.replace(/-/g, ' ')}
|
|
201
186
|
</Breadcrumbs.Item>
|
|
@@ -204,7 +189,7 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
204
189
|
</Breadcrumbs>
|
|
205
190
|
)}
|
|
206
191
|
|
|
207
|
-
<
|
|
192
|
+
<div>
|
|
208
193
|
<Stack direction="vertical" padding="none" gap={12} alignItems="flex-start">
|
|
209
194
|
{activeMetadata.title && (
|
|
210
195
|
<Heading as="h1" size="3">
|
|
@@ -217,12 +202,12 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
217
202
|
</Text>
|
|
218
203
|
)}
|
|
219
204
|
{activeMetadata.image && (
|
|
220
|
-
<
|
|
205
|
+
<div className={styles.HeroImageWrapper}>
|
|
221
206
|
<Hero.Image src={activeMetadata.image} alt={activeMetadata['image-alt']} />
|
|
222
|
-
</
|
|
207
|
+
</div>
|
|
223
208
|
)}
|
|
224
209
|
{activeMetadata['action-1-text'] && (
|
|
225
|
-
<
|
|
210
|
+
<div className={styles.ActionsWrapper}>
|
|
226
211
|
<ButtonGroup>
|
|
227
212
|
<Button as="a" href={activeMetadata['action-1-link']}>
|
|
228
213
|
{activeMetadata['action-1-text']}
|
|
@@ -233,10 +218,10 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
233
218
|
</Button>
|
|
234
219
|
)}
|
|
235
220
|
</ButtonGroup>
|
|
236
|
-
</
|
|
221
|
+
</div>
|
|
237
222
|
)}
|
|
238
223
|
</Stack>
|
|
239
|
-
</
|
|
224
|
+
</div>
|
|
240
225
|
{activeMetadata['show-tabs'] && <UnderlineNav tabData={filteredTabData} />}
|
|
241
226
|
</>
|
|
242
227
|
)}
|
|
@@ -248,16 +233,16 @@ export function Theme({pageMap, children}: ThemeProps) {
|
|
|
248
233
|
<>{children}</>
|
|
249
234
|
|
|
250
235
|
{relatedLinks.length > 0 && (
|
|
251
|
-
<
|
|
236
|
+
<div className={styles.RelatedLinks}>
|
|
252
237
|
<RelatedContentLinks links={relatedLinks} />
|
|
253
|
-
</
|
|
238
|
+
</div>
|
|
254
239
|
)}
|
|
255
240
|
</>
|
|
256
241
|
)}
|
|
257
242
|
</article>
|
|
258
243
|
<Footer filePath={filePath} repoURL={repoURL} repoSrcPath={repoSrcPath} />
|
|
259
244
|
</Stack>
|
|
260
|
-
</
|
|
245
|
+
</div>
|
|
261
246
|
</div>
|
|
262
247
|
</PageLayout.Content>
|
|
263
248
|
</PageLayout>
|
|
@@ -19,6 +19,14 @@
|
|
|
19
19
|
font-size: var(--brand-text-size-100);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.NavListGroup {
|
|
23
|
+
margin-bottom: var(--base-size-24);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.NavListItemCapitalize {
|
|
27
|
+
text-transform: capitalize;
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
.NavList__Container li a,
|
|
23
31
|
.NavList__Container li button {
|
|
24
32
|
font-size: var(--brand-text-size-200);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, {useMemo} from 'react'
|
|
2
2
|
import NextLink from 'next/link'
|
|
3
3
|
import {NavList} from '@primer/react'
|
|
4
|
-
import {
|
|
4
|
+
import {Heading} from '@primer/react-brand'
|
|
5
5
|
import type {Folder, MdxFile, PageMapItem} from 'nextra'
|
|
6
6
|
|
|
7
7
|
import styles from './Sidebar.module.css'
|
|
@@ -49,12 +49,12 @@ export function Sidebar({pageMap}: SidebarProps) {
|
|
|
49
49
|
return (
|
|
50
50
|
<div className={styles.Sidebar}>
|
|
51
51
|
{activeHeaderLink && (
|
|
52
|
-
<
|
|
52
|
+
<Heading as="h2" size="6" className={styles.Sidebar__title} id="nav-list-heading">
|
|
53
53
|
{activeHeaderLink.title}
|
|
54
|
-
|
|
54
|
+
<span className="visually-hidden"> navigation</span>
|
|
55
|
+
</Heading>
|
|
55
56
|
)}
|
|
56
|
-
|
|
57
|
-
<NavList className={styles.NavList} aria-label="Menu links">
|
|
57
|
+
<NavList className={styles.NavList} aria-labelledby="nav-list-heading">
|
|
58
58
|
{reorderedPageMap.map(item => {
|
|
59
59
|
if (item.hasOwnProperty('data')) return null
|
|
60
60
|
|
|
@@ -77,7 +77,7 @@ export function Sidebar({pageMap}: SidebarProps) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
return (
|
|
80
|
-
<NavList.Group title={subNavName} key={item.name}
|
|
80
|
+
<NavList.Group title={subNavName} key={item.name} className={styles.NavListGroup}>
|
|
81
81
|
<NavList.GroupHeading as="h3">
|
|
82
82
|
<NextLink href={item.route}>{subNavName}</NextLink>
|
|
83
83
|
</NavList.GroupHeading>
|
|
@@ -142,9 +142,8 @@ export function Sidebar({pageMap}: SidebarProps) {
|
|
|
142
142
|
as={NextLink}
|
|
143
143
|
key={landingPageItem.route}
|
|
144
144
|
href={landingPageItem.route}
|
|
145
|
-
sx={{textTransform: 'capitalize'}}
|
|
146
145
|
aria-current={isCurrentOrChild ? 'page' : undefined}
|
|
147
|
-
className={styles.NavListItem}
|
|
146
|
+
className={`${styles.NavListItem} ${styles.NavListItemCapitalize}`}
|
|
148
147
|
>
|
|
149
148
|
{landingPageItem.frontMatter?.title || item.name}
|
|
150
149
|
</NavList.Item>
|
|
@@ -155,7 +154,7 @@ export function Sidebar({pageMap}: SidebarProps) {
|
|
|
155
154
|
)
|
|
156
155
|
})}
|
|
157
156
|
{sidebarLinks.length > 0 && (
|
|
158
|
-
<NavList.Group title=""
|
|
157
|
+
<NavList.Group title="" className={styles.NavListGroup}>
|
|
159
158
|
{sidebarLinks.map(link => {
|
|
160
159
|
return (
|
|
161
160
|
<NavList.Item
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/doctocat-nextjs",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1-rc.bf9f37a",
|
|
4
4
|
"description": "A Next.js theme for building Primer documentation sites",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/primer/doctocat-nextjs.git"
|
|
10
|
+
},
|
|
7
11
|
"scripts": {
|
|
8
12
|
"check": "tsc --noEmit",
|
|
9
13
|
"lint": "eslint '**/*.{js,ts,tsx,md,mdx}' --max-warnings=0 --config ./.eslintrc.cjs",
|
|
@@ -23,7 +27,7 @@
|
|
|
23
27
|
"dependencies": {
|
|
24
28
|
"@next/mdx": "15.5.2",
|
|
25
29
|
"@primer/octicons-react": "19.15.1",
|
|
26
|
-
"@primer/react": "^
|
|
30
|
+
"@primer/react": "^38.0.0",
|
|
27
31
|
"@types/lodash.debounce": "^4.0.9",
|
|
28
32
|
"framer-motion": "12.4.0",
|
|
29
33
|
"lodash.debounce": "^4.0.8",
|