-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(nx-dev): add TOC markdoc component for blog posts
- Loading branch information
Showing
3 changed files
with
85 additions
and
0 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
70 changes: 70 additions & 0 deletions
70
nx-dev/ui-markdoc/src/lib/tags/table-of-contents.component.tsx
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,70 @@ | ||
'use client'; | ||
|
||
import { useEffect, useState } from 'react'; | ||
|
||
interface TocItem { | ||
id: string; | ||
text: string; | ||
level: number; | ||
} | ||
|
||
interface TableOfContentsProps { | ||
maxDepth?: number; | ||
} | ||
|
||
export function TableOfContents({ | ||
maxDepth = 3, | ||
}: TableOfContentsProps): JSX.Element { | ||
const [headings, setHeadings] = useState<TocItem[]>([]); | ||
|
||
useEffect(() => { | ||
// Find the main content wrapper where markdown content is rendered | ||
const content = document.querySelector('[data-document="main"]'); | ||
if (!content) return; | ||
|
||
// Get all headings h1-h6 within the content | ||
const headingElements = content.querySelectorAll('h1, h2, h3, h4, h5, h6'); | ||
|
||
const items: TocItem[] = Array.from(headingElements) | ||
.map((heading) => { | ||
const level = parseInt(heading.tagName[1]); | ||
if (level > maxDepth) return null; | ||
|
||
return { | ||
id: heading.id, | ||
text: heading.textContent || '', | ||
level, | ||
}; | ||
}) | ||
.filter((item): item is TocItem => item !== null); | ||
|
||
setHeadings(items); | ||
}, [maxDepth]); | ||
|
||
if (headings.length === 0) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<nav className="toc not-prose mb-8 rounded-lg border border-slate-200 bg-slate-50 p-4 dark:border-slate-800 dark:bg-slate-900/50"> | ||
<p className="mb-3 text-sm font-semibold text-slate-900 dark:text-slate-100"> | ||
Table of Contents | ||
</p> | ||
<ul className="space-y-2 text-sm"> | ||
{headings.map((heading) => ( | ||
<li | ||
key={heading.id} | ||
style={{ paddingLeft: `${(heading.level - 1) * 1}rem` }} | ||
> | ||
<a | ||
href={`#${heading.id}`} | ||
className="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200" | ||
> | ||
{heading.text} | ||
</a> | ||
</li> | ||
))} | ||
</ul> | ||
</nav> | ||
); | ||
} |
11 changes: 11 additions & 0 deletions
11
nx-dev/ui-markdoc/src/lib/tags/table-of-contents.schema.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,11 @@ | ||
import { Schema } from '@markdoc/markdoc'; | ||
|
||
export const tableOfContents: Schema = { | ||
render: 'TableOfContents', | ||
attributes: { | ||
maxDepth: { | ||
type: 'Number', | ||
default: 3, | ||
}, | ||
}, | ||
}; |