-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23334 from storybookjs/revert-23333-revert-23142-…
…shilman/toc-proof-of-concept Revert "Revert "Addon-docs: Add opt-in table of contents""
- Loading branch information
Showing
11 changed files
with
278 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { global as globalThis } from '@storybook/global'; | ||
|
||
export default { | ||
component: globalThis.Components.Button, | ||
tags: ['autodocs'], | ||
parameters: { | ||
chromatic: { disable: true }, | ||
docs: { toc: {} }, | ||
}, | ||
}; | ||
|
||
export const One = { | ||
args: { label: 'One' }, | ||
}; | ||
|
||
export const Two = { | ||
args: { label: 'Two' }, | ||
}; | ||
|
||
export const Three = { | ||
args: { label: 'Two' }, | ||
}; |
14 changes: 14 additions & 0 deletions
14
code/addons/docs/template/stories/toc/custom-selector.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { global as globalThis } from '@storybook/global'; | ||
import { One, Two, Three } from './basic.stories'; | ||
|
||
export default { | ||
component: globalThis.Components.Button, | ||
tags: ['autodocs'], | ||
parameters: { | ||
chromatic: { disable: true }, | ||
// Select all the headings in the document | ||
docs: { toc: { headingSelector: 'h1, h2, h3' } }, | ||
}, | ||
}; | ||
|
||
export { One, Two, Three }; |
14 changes: 14 additions & 0 deletions
14
code/addons/docs/template/stories/toc/custom-title.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { global as globalThis } from '@storybook/global'; | ||
import { One, Two, Three } from './basic.stories'; | ||
|
||
export default { | ||
component: globalThis.Components.Button, | ||
tags: ['autodocs'], | ||
parameters: { | ||
chromatic: { disable: true }, | ||
// Custom title label | ||
docs: { toc: { title: 'Contents' } }, | ||
}, | ||
}; | ||
|
||
export { One, Two, Three }; |
14 changes: 14 additions & 0 deletions
14
code/addons/docs/template/stories/toc/ignore-selector.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { global as globalThis } from '@storybook/global'; | ||
import { One, Two, Three } from './basic.stories'; | ||
|
||
export default { | ||
component: globalThis.Components.Button, | ||
tags: ['autodocs'], | ||
parameters: { | ||
chromatic: { disable: true }, | ||
// Skip the first story in the TOC | ||
docs: { toc: { ignoreSelector: '#one' } }, | ||
}, | ||
}; | ||
|
||
export { One, Two, Three }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
import React, { useEffect } from 'react'; | ||
import type { FC, ReactElement } from 'react'; | ||
import { styled } from '@storybook/theming'; | ||
import tocbot from 'tocbot'; | ||
|
||
export interface TocParameters { | ||
/** CSS selector for the container to search for headings. */ | ||
contentsSelector?: string; | ||
|
||
/** | ||
* When true, hide the TOC. We still show the empty container | ||
* (as opposed to showing nothing at all) because it affects the | ||
* page layout and we want to preserve the layout across pages. | ||
*/ | ||
disable?: boolean; | ||
|
||
/** CSS selector to match headings to list in the TOC. */ | ||
headingSelector?: string; | ||
|
||
/** Headings that match the ignoreSelector will be skipped. */ | ||
ignoreSelector?: string; | ||
|
||
/** Custom title ReactElement or string to display above the TOC. */ | ||
title?: ReactElement | string | null; | ||
|
||
/** | ||
* TocBot options, not guaranteed to be available in future versions. | ||
* @see tocbot docs {@link https://tscanlin.github.io/tocbot/#usage} | ||
*/ | ||
unsafeTocbotOptions?: tocbot.IStaticOptions; | ||
} | ||
|
||
const Wrapper = styled.div(({ theme }) => ({ | ||
width: '10rem', | ||
|
||
'@media (max-width: 768px)': { | ||
display: 'none', | ||
}, | ||
})); | ||
|
||
const Content = styled.div(({ theme }) => ({ | ||
position: 'fixed', | ||
top: 0, | ||
width: '10rem', | ||
paddingTop: '4rem', | ||
|
||
fontFamily: theme.typography.fonts.base, | ||
fontSize: theme.typography.size.s2, | ||
|
||
WebkitFontSmoothing: 'antialiased', | ||
MozOsxFontSmoothing: 'grayscale', | ||
WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', | ||
WebkitOverflowScrolling: 'touch', | ||
|
||
'& *': { | ||
boxSizing: 'border-box', | ||
}, | ||
|
||
'& > .toc-wrapper > .toc-list': { | ||
paddingLeft: 0, | ||
borderLeft: `solid 2px ${theme.color.mediumlight}`, | ||
|
||
'.toc-list': { | ||
paddingLeft: 0, | ||
borderLeft: `solid 2px ${theme.color.mediumlight}`, | ||
|
||
'.toc-list': { | ||
paddingLeft: 0, | ||
borderLeft: `solid 2px ${theme.color.mediumlight}`, | ||
}, | ||
}, | ||
}, | ||
'& .toc-list-item': { | ||
position: 'relative', | ||
listStyleType: 'none', | ||
marginLeft: 20, | ||
paddingTop: 3, | ||
paddingBottom: 3, | ||
}, | ||
'& .toc-list-item::before': { | ||
content: '""', | ||
position: 'absolute', | ||
height: '100%', | ||
top: 0, | ||
left: 0, | ||
transform: `translateX(calc(-2px - 20px))`, | ||
borderLeft: `solid 2px ${theme.color.mediumdark}`, | ||
opacity: 0, | ||
transition: 'opacity 0.2s', | ||
}, | ||
'& .toc-list-item.is-active-li::before': { | ||
opacity: 1, | ||
}, | ||
'& .toc-list-item > a': { | ||
color: theme.color.defaultText, | ||
textDecoration: 'none', | ||
}, | ||
'& .toc-list-item.is-active-li > a': { | ||
fontWeight: 600, | ||
color: theme.color.secondary, | ||
textDecoration: 'none', | ||
}, | ||
})); | ||
|
||
const Heading = styled.p(({ theme }) => ({ | ||
fontWeight: 600, | ||
fontSize: '0.875em', | ||
color: theme.textColor, | ||
textTransform: 'uppercase', | ||
marginBottom: 10, | ||
})); | ||
|
||
type TableOfContentsProps = React.PropsWithChildren< | ||
TocParameters & { | ||
className?: string; | ||
} | ||
>; | ||
|
||
const OptionalTitle: FC<{ title: TableOfContentsProps['title'] }> = ({ title }) => { | ||
if (title === null) { | ||
return null; | ||
} | ||
if (typeof title === 'string') { | ||
return <Heading>{title}</Heading>; | ||
} | ||
return title; | ||
}; | ||
|
||
export const TableOfContents = ({ | ||
title, | ||
disable, | ||
headingSelector, | ||
contentsSelector, | ||
ignoreSelector, | ||
unsafeTocbotOptions, | ||
}: TableOfContentsProps) => { | ||
useEffect(() => { | ||
const configuration = { | ||
tocSelector: '.toc-wrapper', | ||
contentSelector: contentsSelector ?? '.sbdocs-content', | ||
headingSelector: headingSelector ?? 'h3', | ||
ignoreSelector: ignoreSelector ?? '.skip-toc', | ||
headingsOffset: 40, | ||
scrollSmoothOffset: -40, | ||
/** | ||
* Ignore headings that did not | ||
* come from the main markdown code. | ||
*/ | ||
// ignoreSelector: ':not(.sbdocs), .hide-from-toc', | ||
orderedList: false, | ||
/** | ||
* Prevent default linking behavior, | ||
* leaving only the smooth scrolling. | ||
*/ | ||
onClick: () => false, | ||
...unsafeTocbotOptions, | ||
}; | ||
|
||
/** | ||
* Wait for the DOM to be ready. | ||
*/ | ||
const timeout = setTimeout(() => tocbot.init(configuration), 100); | ||
return () => { | ||
clearTimeout(timeout); | ||
tocbot.destroy(); | ||
}; | ||
}, [disable]); | ||
|
||
return ( | ||
<> | ||
<Wrapper> | ||
{!disable ? ( | ||
<Content> | ||
<OptionalTitle title={title || null} /> | ||
<div className="toc-wrapper" /> | ||
</Content> | ||
) : null} | ||
</Wrapper> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters