{"name":"toc","title":"Table of Contents","description":"Tracks headings in a scroll container, highlights the active section while scrolling, and smooth-scrolls to a heading on click.","installCommand":"bunx marko-ui add toc -y","usageTags":"<Toc>","importSnippet":"import Toc from \"@/components/ui/toc/toc.marko\";","usageSnippet":"static const items = [\n  { value: \"introduction\", depth: 2, label: \"Introduction\" },\n  { value: \"usage\", depth: 2, label: \"Usage\" },\n];\n\n<div/scrollContainer class=\"h-72 overflow-y-auto\">\n  <h2 id=\"introduction\">Introduction</h2>\n  <h2 id=\"usage\">Usage</h2>\n</div>\n<Toc items=items scrollEl=() => scrollContainer()/>","tags":["Toc"],"parts":[],"props":[{"name":"items","type":"TocItem[]","required":true,"description":"The TOC items with `value` (slug/id) and `depth` (heading level)."},{"name":"activeIds","type":"string[] | undefined","required":false,"description":"The controlled active heading ids."},{"name":"autoScroll","type":"boolean | undefined","required":false,"default":"true","description":"Whether to auto-scroll the TOC container so the first active item\nis visible when active headings change."},{"name":"defaultActiveIds","type":"string[] | undefined","required":false,"description":"The default active heading ids when rendered.\nUse when you don't need to control the active headings."},{"name":"dir","type":"'ltr' | 'rtl' | undefined","required":false,"default":"ltr","description":"The document's text/writing direction."},{"name":"getRootNode","type":"(() => ShadowRoot | Document | Node) | undefined","required":false,"description":"A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron."},{"name":"ids","type":"ElementIds | undefined","required":false,"description":"The ids of the elements in the TOC. Useful for composition."},{"name":"rootMargin","type":"string | undefined","required":false,"description":"The root margin for the IntersectionObserver.\nControls the effective viewport area for determining active headings."},{"name":"scrollBehavior","type":"ScrollBehavior | undefined","required":false,"default":"smooth","description":"The default scroll behavior used when auto-scrolling the TOC container\nand when scrolling to a heading (via link click or `api.scrollTo`).\nCan be overridden per-call by passing `behavior` to `api.scrollTo`."},{"name":"scrollEl","type":"(() => HTMLElement | null) | undefined","required":false,"description":"Function that returns the scroll container element to observe within.\nDefaults to the document/viewport."},{"name":"threshold","type":"number | number[] | undefined","required":false,"default":"0","description":"The IntersectionObserver threshold. A value of `0` means the heading is\nactive as soon as even one pixel is visible within the root margin area."},{"name":"title","type":"string","required":false}],"events":[{"name":"activeIdsChange","arg":"string[]"},{"name":"activeItemsChange","arg":"TocItem[]"},{"name":"onActiveChange","arg":"ActiveChangeDetails","description":"Callback when the active (visible) headings change."}],"keyboard":[],"accessibilityNotes":[],"examples":[{"id":"toc-demo","title":"Basic","source":"import Toc from \"@marko-ui/shadcn/ui/toc/toc.marko\";\n\nstatic const items = [\n  { value: \"demo-introduction\", depth: 2, label: \"Introduction\" },\n  { value: \"demo-installation\", depth: 2, label: \"Installation\" },\n  { value: \"demo-usage\", depth: 2, label: \"Usage\" },\n  { value: \"demo-api-reference\", depth: 2, label: \"API reference\" },\n  { value: \"demo-faq\", depth: 2, label: \"FAQ\" },\n];\n\n<div class=\"grid w-full grid-cols-[1fr_200px] gap-8\">\n  <div/scrollContainer tabindex=\"0\" class=\"h-72 overflow-y-auto rounded-lg border border-border p-6\">\n    <div class=\"space-y-6\">\n      <h2 id=\"demo-introduction\" class=\"text-lg font-semibold\">Introduction</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Scroll this panel and watch the table of contents on the right track which section is\n        currently in view.\n      </p>\n\n      <h2 id=\"demo-installation\" class=\"text-lg font-semibold\">Installation</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Components are added to your project with the CLI, which copies the source files directly\n        into your own registry directory so you can edit them freely.\n      </p>\n\n      <h2 id=\"demo-usage\" class=\"text-lg font-semibold\">Usage</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Import the component, pass it your heading list and the scroll container to observe, and\n        it takes care of the rest.\n      </p>\n\n      <h2 id=\"demo-api-reference\" class=\"text-lg font-semibold\">API reference</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Every prop mirrors the underlying Zag machine, plus a small set of additive sugar props.\n      </p>\n\n      <h2 id=\"demo-faq\" class=\"text-lg font-semibold\">FAQ</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Common questions about theming and accessibility are answered on the main site.\n      </p>\n    </div>\n  </div>\n  <Toc\n    items=items\n    scrollEl=() => scrollContainer()\n    class=\"sticky top-6 self-start\"\n  />\n</div>","description":"A table of contents tracking headings inside a scrollable panel."},{"id":"toc-with-title","title":"With title","source":"import Toc from \"@marko-ui/shadcn/ui/toc/toc.marko\";\n\nstatic const items = [\n  { value: \"overview\", depth: 2, label: \"Overview\" },\n  { value: \"getting-started\", depth: 2, label: \"Getting started\" },\n  { value: \"examples\", depth: 2, label: \"Examples\" },\n];\n\n<div class=\"grid w-full grid-cols-[1fr_200px] gap-8\">\n  <div/scrollContainer tabindex=\"0\" class=\"h-64 overflow-y-auto rounded-lg border border-border p-6\">\n    <div class=\"space-y-6\">\n      <h2 id=\"overview\" class=\"text-lg font-semibold\">Overview</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Pass a <code class=\"rounded bg-muted px-1 py-0.5 text-xs\">title</code> to render a heading\n        above the list of links.\n      </p>\n\n      <h2 id=\"getting-started\" class=\"text-lg font-semibold\">Getting started</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        The title is rendered from the machine's own title part, so it participates in the same\n        accessibility wiring as the rest of the nav.\n      </p>\n\n      <h2 id=\"demo-examples\" class=\"text-lg font-semibold\">Examples</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Scroll to see the active link update as each heading enters view.\n      </p>\n    </div>\n  </div>\n  <Toc\n    items=items\n    scrollEl=() => scrollContainer()\n    title=\"On this page\"\n    class=\"sticky top-6 self-start\"\n  />\n</div>","description":"Pass `title` to render a heading above the list of links."},{"id":"toc-nested","title":"Nested headings","source":"import Toc from \"@marko-ui/shadcn/ui/toc/toc.marko\";\n\nstatic const items = [\n  { value: \"installation\", depth: 2, label: \"Installation\" },\n  { value: \"prerequisites\", depth: 3, label: \"Prerequisites\" },\n  { value: \"quick-start\", depth: 3, label: \"Quick start\" },\n  { value: \"usage\", depth: 2, label: \"Usage\" },\n  { value: \"basic-example\", depth: 3, label: \"Basic example\" },\n  { value: \"advanced-example\", depth: 3, label: \"Advanced example\" },\n];\n\n<div class=\"grid w-full grid-cols-[1fr_200px] gap-8\">\n  <div/scrollContainer tabindex=\"0\" class=\"h-72 overflow-y-auto rounded-lg border border-border p-6\">\n    <div class=\"space-y-6\">\n      <h2 id=\"demo-nested-installation\" class=\"text-lg font-semibold\">Installation</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Deeper headings indent further in the list, driven entirely by each item's\n        <code class=\"rounded bg-muted px-1 py-0.5 text-xs\">depth</code>.\n      </p>\n\n      <h3 id=\"prerequisites\" class=\"text-base font-semibold\">Prerequisites</h3>\n      <p class=\"text-sm text-muted-foreground\">\n        You will need a Marko 6 project with Tailwind CSS and the\n        <code class=\"rounded bg-muted px-1 py-0.5 text-xs\">marko-ui</code> adapter installed.\n      </p>\n\n      <h3 id=\"quick-start\" class=\"text-base font-semibold\">Quick start</h3>\n      <p class=\"text-sm text-muted-foreground\">\n        Run the CLI command for the component you want and import it into your route.\n      </p>\n\n      <h2 id=\"demo-nested-usage\" class=\"text-lg font-semibold\">Usage</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Every interactive component follows the same one-tag wiring pattern: <code>&lt;zag&gt;</code>\n        picks the machine's props, creates and connects the service, and returns the api getter.\n      </p>\n\n      <h3 id=\"basic-example\" class=\"text-base font-semibold\">Basic example</h3>\n      <p class=\"text-sm text-muted-foreground\">\n        Import the component, pass the required props, and render it like any other tag.\n      </p>\n\n      <h3 id=\"advanced-example\" class=\"text-base font-semibold\">Advanced example</h3>\n      <p class=\"text-sm text-muted-foreground\">\n        Controlled usage is supported throughout the registry.\n      </p>\n    </div>\n  </div>\n  <Toc\n    items=items\n    scrollEl=() => scrollContainer()\n    class=\"sticky top-6 self-start\"\n  />\n</div>","description":"Each item's `depth` controls its indentation, so `h2`/`h3` outlines nest naturally.","essential":true},{"id":"toc-controlled","title":"Controlled","source":"import Toc from \"@marko-ui/shadcn/ui/toc/toc.marko\";\n\nstatic const items = [\n  { value: \"one\", depth: 2, label: \"Section one\" },\n  { value: \"two\", depth: 2, label: \"Section two\" },\n  { value: \"three\", depth: 2, label: \"Section three\" },\n];\n\n<let/activeIds=([] as string[])/>\n\n<div class=\"grid w-full grid-cols-[1fr_200px] gap-8\">\n  <div/scrollContainer tabindex=\"0\" class=\"h-64 overflow-y-auto rounded-lg border border-border p-6\">\n    <div class=\"space-y-6\">\n      <h2 id=\"one\" class=\"text-lg font-semibold\">Section one</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Listen for <code class=\"rounded bg-muted px-1 py-0.5 text-xs\">activeIdsChange</code> to\n        read which headings are currently active, without taking over control of the list.\n      </p>\n\n      <h2 id=\"two\" class=\"text-lg font-semibold\">Section two</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        The active heading below reflects the same value the indicator bar is tracking.\n      </p>\n\n      <h2 id=\"three\" class=\"text-lg font-semibold\">Section three</h2>\n      <p class=\"text-sm text-muted-foreground\">\n        Scroll to the bottom to see the active id list update.\n      </p>\n    </div>\n  </div>\n  <div class=\"sticky top-6 flex flex-col gap-3 self-start\">\n    <Toc\n      items=items\n      scrollEl=() => scrollContainer()\n      activeIdsChange=(next) => { activeIds = next; }\n    />\n    <span class=\"text-xs text-muted-foreground\">active: ${activeIds.join(\", \") || \"none\"}</span>\n  </div>\n</div>","description":"Listen for `activeIdsChange` (or `onActiveChange` for the full details) to read the active headings without taking over control of the list."}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","nativeAttributes":"nav","itemTypes":[{"prop":"items","typeName":"TocItem","fields":[{"name":"label","type":"string","required":false}]}]}
