sv-toc
Installation
You can install sv-toc through your preferred package manager:
npm install sv-toc
yarn add sv-toc
pnpm add sv-toc
bun add sv-toc
Usage
<script lang="ts">
import { class TocToc } from "sv-toc";
const const toc: Toctoc = new new Toc(config?: TocConfig): TocToc({
updateHeadings?: boolean | undefinedWhether the Toc instance should observe DOM changes within the configured root and update the TOC when headings or their contents change.updateHeadings: true,
headingSelector?: string | undefinedCSS selector used to identify heading elements within the document.
A common use case may be to only observe headings starting at a specific level, such as "h2, h3, h4".headingSelector: "h1, h2, h3, h4, h5, h6",
rootSelector?: string | undefinedCSS selector used to identify the root element within which the Toc instance should observe headings.rootSelector: "body",
observeScroll?: string | boolean | undefinedWhether to look for scroll events to determine the active heading.
- `true`: Observe scroll events on the window.
- `false`: Do not observe scroll events.
- `string`: Observe scroll events on the element matching the provided CSS selector.observeScroll: true,
scrollTopOffset?: number | undefinedNumber of pixels to offset from the top of the viewport when determining the active heading.scrollTopOffset: 0,
scrollBottomOffset?: number | undefinedNumber of pixels to offset from the bottom of the viewport when determining the active heading.scrollBottomOffset: 0,
activeStrategy?: "first" | "last" | "all" | undefinedStrategy used to determine which headings are considered active.
- `"first"`: Only the topmost visible heading is considered active.
- `"last"`: Only the bottommost visible heading is considered active.
- `"all"`: All visible headings are considered active.activeStrategy: "all",
addIds?: boolean | "force" | undefinedWhether to automatically add an ID to each heading element.
- `true`: Automatically add an ID to each heading element if it doesn't already have one.
- `"force"`: Always add an ID to each heading element, even if it already has one.
- `false`: Do not automatically add an ID to heading elements.addIds: false,
});
</script>
<!-- Now do whatever you want with toc.current -->
{#each const toc: Toctoc.Toc.current: TocHeading[]The current table of contentcurrent as let heading: TocHeadingheading, let index: numberindex (let index: numberindex)}
...
{/each}
Configuration
You can optionally pass a configuration object of the type TocConfig to the Toc constructor to change its behavior. All options are optional and will fall back to their default values if not provided.
updateHeadings
updateHeadings?: boolean
Whether the Toc instance should observe DOM changes within the configured root and update the TOC when headings or their contents change.
Default: true
Note: Headings will still update if scroll events are observed, even if updateHeadings is set to false.
headingSelector
headingSelector?: string
CSS selector used to identify heading elements within the document.
A common use case may be to only observe headings starting at a specific level, such as "h2, h3, h4".
Default: "h1, h2, h3, h4, h5, h6"
rootSelector
rootSelector?: string
CSS selector used to identify the root element within which the Toc instance should observe headings.
Default: "body"
observeScroll
observeScroll?: boolean | string
Whether to look for scroll events to determine the active heading.
true: Observe scroll events on the window.false: Do not observe scroll events.string: Observe scroll events on the element matching the provided CSS selector.
Default: true
Note: This will also watch the window for resize events.
scrollTopOffset
scrollTopOffset?: number
Number of pixels to offset from the top of the viewport when determining the active heading.
Default: 0
scrollBottomOffset
scrollBottomOffset?: number
Number of pixels to offset from the bottom of the viewport when determining the active heading.
Default: 0
activeStrategy
activeStrategy?: "first" | "last" | "all"
Strategy used to determine which headings are considered active.
"first": Only the topmost visible heading is considered active."last": Only the bottommost visible heading is considered active."all": All visible headings are considered active.
Default: "all"
Note: This value does nothing if observeScroll is set to false.
addIds
addIds?: boolean | "force"
Whether to automatically add an ID to each heading element.
true: Automatically add an ID to each heading element if it doesn't already have one."force": Always add an ID to each heading element, even if it already has one.false: Do not automatically add an ID to heading elements.
Headings are generated by slugifying the heading's text content.
<h2>Hello, World!</h2>
becomes:
<h2 id="hello-world">Hello, World!</h2>
Duplicate IDs are automatically sufixed:
<h2 id="hello-world">Hello, World!</h2>
<h2 id="hello-world-1">Hello, World!</h2>
<h2 id="hello-world-2">Hello, World!</h2>
Default: false
Result
You can access the list of headings by accessing current on your Toc instance. This value is reactive and will update as the active heading changes. current returns a TocHeading[] array containing all the headings in the document with a schema as follows:
headingLevel
headingLevel?: number
The level of the element (e.g., 1 for <h1>, 2 for <h2>, etc.).
If the element is not a HTML heading element (due to overriding headingSelector in the configuration), this value will be undefined.
tagName
tagName: string
The tag name of the element (e.g., "h1", "h2", etc.).
id
id?: string
The ID of the heading element, if it has one.
textContent
textContent?: string
The text content of the heading element, trimmed of leading and trailing whitespace.
active
active?: boolean
Whether the heading element is currently considered active based on the Toc instance's active strategy.
Environment
Toc is intended for browser environments. During SSR, DOM-related operations safely return no headings until browser APIs are available.