Table of Contents
A customizable table of contents component for your documentation.
Installation
npm install @udecode/plate-heading
Usage
// ...
import { TocPlugin } from '@udecode/plate-heading/react';
const editor = usePlateEditor({
id: 'toc-demo',
override: {
components: {
...otherPlateComponents,
[TocPlugin.key]: TocElement,
},
},
plugins: [
...otherPlatePlugins,
TocPlugin.configure({
options: {
scrollContainerSelector: `#your-scroll-container-id`,
topOffset: 80,
},
}),
],
value: tocValue,
});
Set scroll container
In this plugin, you need to provide a selector to options.scrollContainerSelector to specify the scrollable container. This selector is used with Document.querySelector
to locate the container element.
You can use various selector formats, such as:
- An ID:
#scrollable-container
- A class:
.content-wrapper
- A more specific selector:
body #main-content
You can set this id to <Editor />
component or a div that wraps the <Editor />
. It specifically depends on your use case.
We recommend using the same id for both TocPlugin and BlockSelectionPlugin.
Configure options
type TocOptions = {
isScroll: boolean;
topOffset: number;
queryHeading?: (editor: SlateEditor) => Heading[];
scrollContainerSelector?: string;
};
isScroll
: Set this tofalse
if your editor doesn't have a fixed height.topOffset
: After scrolling to the specified element, scroll an additional distance.scrollContainerSelector
: explained above
queryHeading: if you want to customize the heading selection logic, you can provide a function to query the headings. for example, you just want to use heading level 1 and 2, you can use this. by default, it will use all heading levels.
Toc Sidebar (Plus)
Toc Sidebar has the following props you can configure it to match your needs:
type TocSidebarProps = {
rootMargin?: string;
topOffset?: number;
maxShowCount?: number;
};
rootMargin
: The margin around the viewport that should be considered when calculating the visibility of the target element.which is used in IntersectionObserver.topOffset
: After scrolling to the specified element, scroll an additional distance.maxShowCount
: The maximum number of items to show in the sidebar default is 20.
here is an example of how to use the TocSidebar component:
<Plate>
<Editor />
<TocSideBar
className="fixed right-8 top-24 ml-4 h-fit"
rootMargin="0px 0px 0px 0px"
topOffset={30}
maxShowCount={20}
/>
</Plate>
If you find TocSideBar is not highlight the correct heading, please make sure you have added the element.id
to the heading-element
.
For example:
export const HeadingElement = withRef<typeof HeadingElementVariants>(
({ children, isFirstBlock, variant = 'h1', ...props }, ref) => {
const { editor, element } = props;
return (
<HeadingElementVariants
// Add id to the heading element
id={element.id as string}
ref={ref}
as={variant!}
variant={variant}
isFirstBlock={element === editor.children[0]}
{...props}
>
{children}
</HeadingElementVariants>
);
}
);
Plate Plus
The TocSideBar component in Plate Plus offers the following features:
- Responsive design that adapts to different screen sizes
- Dynamic highlighting of the corresponding thumbnail on the right side based on the current section
- Hover thumbnail to see the preview of the section with smooth animation
- Elegant transition effects when navigating between sections
- Animated highlighting of the current section in the sidebar
Here's an example of how to use the enhanced TocSideBar component in Plate Plus: