Page outline and catalogue index composed with List Item. Use toc for on-page headings with optional nest line and scroll spy. Use index for sectioned side navigation.
Also known as: toc, table of contents, on this page, catalogue index, side nav, outline, contents
Install with the CLI, or copy the component source into your project.
Add contents-nav (npm)
1npx --yes -p @default-file/ui df-ui add contents-nav
On-page outline with nested muted rows and a nest guide line. scrollSpy is off in the demo so the selected row stays stable.
Same toc tree with nestLine false so nested rows indent without a guide line.
Catalogue-style index with section labels and top dividers between groups.
Flat index list without section labels.
Build the toc from parts. ListItemNest controls the nest guide line per group.
Index built from sections, items, and a separator for flat groupings.
Page outline and catalogue index composed with List Item. Use variant toc for on-page headings with nested rows, optional nest guide line, and scroll spy. Use variant index for sectioned side navigation. Pass scrollRoot for the host scrollport. Compose with ContentsNavHeading, ContentsNavSection, ContentsNavItem, and ListItemNest, or pass items and sections.
Root nav. toc defaults nestLine and scrollSpy on. index defaults them off and uses section labels.
| Prop | Type | Default | Notes |
|---|---|---|---|
| variant | "toc" | "index" | "toc" | toc is the on-page outline. index is the catalogue or side index. |
| title | ReactNode | - | Optional heading above the list. Typical for toc (for example On this page). |
| items | ContentsNavItemData[] | - | Tree or flat rows. Each item needs id and title. Optional href, children, disabled, and readOnly. toc defaults href to #id when omitted. Pass href null for a non-link row. readOnly keeps size and selected chrome without hover or activation. |
| sections | ContentsNavSectionData[] | - | Grouped index sections with label, optional divided, and items. Used when variant is index and layout is grouped. |
| layout | "grouped" | "flat" | "grouped" | Index list shape. grouped renders sections. flat renders items only. |
| nestLine | boolean | - | Default guide line for nested groups. Defaults true for toc and false for index. Override per group with ListItemNest line. |
| scrollSpy | boolean | - | Update activeId from scroll position. Defaults true for toc and false for index. |
| scrollRoot | Element | RefObject<Element | null> | (() => Element | null) | - | Scrollport used by scroll spy. Defaults to document.scrollingElement. Pass your app scroller when the page does not scroll on the document. |
| spyRatio | number | 0.25 | Fraction of the scrollport height used as the primary spy marker. |
| activeId | string | - | Controlled active item id. |
| defaultActiveId | string | - | Uncontrolled initial active id. |
| onActiveIdChange | (id: string) => void | - | Called when the active id changes from spy or selection. |
| itemVariant | "accent" | "muted" | "muted" | Default List Item variant for rows. |
| itemSize | "xs" | "sm" | "md" | "lg" | - | Default List Item size for top-level rows. Defaults to "sm" for toc and "md" for index. |
| nestItemSize | "xs" | "sm" | "md" | "lg" | "xs" | Default List Item size for nested rows. |
| itemChrome | ListItemChromeProps | - | Default List Item chrome for every row (padding, gap, type size/family/weight/color, radius, fills, and stroke). Applies to composed ContentsNavItem rows and data-driven branches. Per-item chrome props on ContentsNavItem win. See List Item for the full chrome contract. |
| nestChrome | ListItemNestChromeProps | - | Default ListItemNest chrome for data-driven child groups (indent, pad, gap, lineWidth, lineColor). nestLine still controls whether the guide line paints. Composed ListItemNest instances set their own props. |
| renderItem | (item, ctx) => ReactElement | - | Render a custom host for each data item (for example a router Link). The host is painted with List Item via asChild. |
| children | ReactNode | - | Composition mode. Use ContentsNavHeading, ContentsNavSection, ContentsNavItem, and ListItemNest instead of items or sections. |
| className | string | - | Additional styles on the nav host. |
Title row above the list (data-df contents-nav-heading).
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Heading text. |
| className | string | - | Additional styles. |
Index section with ListItemLabel nav and optional top divider.
| Prop | Type | Default | Notes |
|---|---|---|---|
| label | ReactNode | - | Section title rendered with ListItemLabel variant nav. |
| divided | boolean | false | When true, adds a top hairline and spacing above the section. |
| children | ReactNode | - | Section rows. |
List Item row for a nav entry. Also accepts List Item chrome props such as padding, gap, fontSize, fills, stroke, and radius. Per-item chrome wins over ContentsNav itemChrome. See List Item.
| Prop | Type | Default | Notes |
|---|---|---|---|
| active | boolean | - | Selected appearance. When omitted and itemId is set, matches activeId from context. |
| itemId | string | - | Id used for selection and scroll spy matching. |
| href | string | - | Renders an anchor row when asChild is false. |
| asChild | boolean | false | Paint List Item onto a single child element such as a link. |
| disabled | boolean | false | Non-interactive row. Forwarded to List Item. Dims the row and blocks activation. |
| readOnly | boolean | false | Presentational row. Forwarded to List Item. Keeps size, variant, and selected appearance with no hover, press, or activation. |
| size | "xs" | "sm" | "md" | "lg" | - | Overrides the size default. Outside ListItemNest, defaults to itemSize. Inside ListItemNest, defaults to nestItemSize. |
| variant | "accent" | "muted" | - | Overrides the ContentsNav itemVariant default. |
Horizontal hairline between flat index groups.
| Prop | Type | Default | Notes |
|---|---|---|---|
| className | string | - | Additional styles. |
Theme defaults live on :root. Override these globally or on a local host.
| Token | Type | Default | Notes |
|---|---|---|---|
| --df-contents-nav-gap | CSS length | - | Gap between top-level children. Index defaults to 0 so sections own rhythm. |
| --df-contents-nav-branch-gap | CSS length | - | Gap between a row and its nested group. |
| --df-contents-nav-heading-margin-bottom | CSS length | - | Space under ContentsNavHeading. |
| --df-list-item-nest-indent | CSS length | - | Outer inset on ListItemNest. Set by the indent prop. |
| --df-list-item-nest-pad | CSS length | - | Inner pad after the nest guide line. Set by the pad prop. |
| --df-list-item-nest-gap | CSS length | - | Gap between nested rows. Set by the gap prop on ListItemNest. |
| --df-list-item-nest-line-width | CSS length | - | Nest guide line thickness. Set by lineWidth. |
| --df-list-item-nest-line-color | CSS color | - | Nest guide line color. Set by lineColor. |