Inline TOC
A collapsible table of contents component for displaying page headings inline with your content.
Usage
Basic Inline TOC
The InlineTOC component displays a collapsible table of contents within your content. It automatically tracks the active section as users scroll.
import { InlineTOC } from "@prisma-docs/eclipse";
export default function Page({ toc }) {
return (
<article>
<InlineTOC items={toc}>
Table of Contents
</InlineTOC>
{/* Your page content */}
</article>
);
}Live Example:
Default Open
You can set the TOC to be open by default:
import { InlineTOC } from "@prisma-docs/eclipse";
export default function Page({ toc }) {
return (
<InlineTOC items={toc} defaultOpen>
Table of Contents
</InlineTOC>
);
}Live Example:
With Nested Items
The component supports nested headings for sub-sections:
import { InlineTOC } from "@prisma-docs/eclipse";
const tocItems = [
{
title: "Getting Started",
url: "#getting-started",
depth: 2,
items: [
{ title: "Installation", url: "#installation", depth: 3 },
{ title: "Configuration", url: "#configuration", depth: 3 },
],
},
{
title: "API Reference",
url: "#api-reference",
depth: 2,
items: [
{ title: "Components", url: "#components", depth: 3 },
{ title: "Hooks", url: "#hooks", depth: 3 },
],
},
];
export default function Page() {
return (
<InlineTOC items={tocItems}>
On this page
</InlineTOC>
);
}Live Example:
Controlled State
You can control the open/closed state programmatically:
import { InlineTOC } from "@prisma-docs/eclipse";
import { useState } from "react";
export default function Page({ toc }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(!isOpen)}>
Toggle TOC
</button>
<InlineTOC
items={toc}
open={isOpen}
onOpenChange={setIsOpen}
>
Table of Contents
</InlineTOC>
</>
);
}In MDX Content
You can use InlineTOC directly in your MDX files:
---
title: My Document
---
import { InlineTOC } from "@prisma-docs/eclipse";
<InlineTOC items={toc}>
Table of Contents
</InlineTOC>
## Section 1
Content here...
## Section 2
More content...Adding to All Pages
You can add InlineTOC to every documentation page automatically:
// page.tsx
import { DocsPage } from "fumadocs-ui/layouts/docs/page";
import { InlineTOC } from "@prisma-docs/eclipse";
export default function Page({ params }) {
const page = getPage(params.slug);
return (
<DocsPage toc={page.data.toc}>
<InlineTOC items={page.data.toc}>
On this page
</InlineTOC>
<page.data.body />
</DocsPage>
);
}InlineTOC Props
items- Array of table of contents items (TOCItem[], required)defaultOpen- Whether the TOC is open by default (boolean, default: false)open- Controlled open state (boolean, optional)disabled- Whether the TOC is disabled (boolean, default: false)onOpenChange- Callback when open state changes ((open: boolean) => void, optional)asChild- Whether to use the child element as the trigger (boolean, default: false)children- The trigger content, usually "Table of Contents" or similar (ReactNode, optional)className- Additional CSS classes (optional)
TOC Item Type
Each item in the items array should have:
title- The title of the heading (string, required)url- The URL/hash to link to (string, required)depth- The depth/level of the heading (number, required)items- Nested items for sub-headings (TOCItem[], optional)
Features
- ✅ Collapsible interface to save space
- ✅ Automatic active section tracking on scroll
- ✅ Support for nested headings
- ✅ Smooth scrolling to sections
- ✅ Controlled and uncontrolled modes
- ✅ Eclipse design system styling
- ✅ Built on Fumadocs InlineTOC
Best Practices
- Place the InlineTOC near the top of long documents
- Use "On this page" or "Table of Contents" as the trigger text
- Set
defaultOpento true for shorter pages where the TOC is always relevant - Keep heading depth to 2-3 levels for better readability
- Ensure all TOC items have corresponding heading anchors on the page
- Use consistent heading levels throughout your content
Integration with Fumadocs
The InlineTOC component works seamlessly with Fumadocs' automatic TOC generation:
import { getPage } from "@/lib/source";
import { InlineTOC } from "@prisma-docs/eclipse";
export default function Page({ params }) {
const page = getPage(params.slug);
// page.data.toc is automatically generated by Fumadocs
return (
<>
<InlineTOC items={page.data.toc}>
On this page
</InlineTOC>
<page.data.body />
</>
);
}