@rinzai/zen 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +16 -1
  3. package/dist/animated-number/index.js +14 -14
  4. package/dist/breadcrumbs/index.js +14 -14
  5. package/dist/calendar/index.js +29 -29
  6. package/dist/calendar-heatmap/index.js +12 -12
  7. package/dist/canvas/index.js +19 -19
  8. package/dist/carousel/index.d.ts.map +1 -1
  9. package/dist/carousel/index.js +29 -29
  10. package/dist/chart/index.js +7 -7
  11. package/dist/code-block/index.js +5 -5
  12. package/dist/collapse/index.js +6 -6
  13. package/dist/color-picker/index.js +10 -10
  14. package/dist/combobox/index.js +61 -61
  15. package/dist/command-palette/index.js +5 -5
  16. package/dist/confirm-dialog/index.js +4 -4
  17. package/dist/date-picker/index.js +15 -15
  18. package/dist/dialog/index.d.ts.map +1 -1
  19. package/dist/dialog/index.js +45 -65
  20. package/dist/docs/README.md +205 -0
  21. package/dist/docs/accordion.md +122 -0
  22. package/dist/docs/alert.md +69 -0
  23. package/dist/docs/animated-number.md +105 -0
  24. package/dist/docs/avatar.md +91 -0
  25. package/dist/docs/backdrop.md +94 -0
  26. package/dist/docs/badge.md +37 -0
  27. package/dist/docs/breadcrumbs.md +44 -0
  28. package/dist/docs/button-group.md +76 -0
  29. package/dist/docs/button.md +131 -0
  30. package/dist/docs/calendar-heatmap.md +73 -0
  31. package/dist/docs/calendar.md +101 -0
  32. package/dist/docs/canvas.md +584 -0
  33. package/dist/docs/card.md +180 -0
  34. package/dist/docs/carousel.md +162 -0
  35. package/dist/docs/chart.md +325 -0
  36. package/dist/docs/checkbox.md +88 -0
  37. package/dist/docs/chip.md +52 -0
  38. package/dist/docs/code-block.md +116 -0
  39. package/dist/docs/code-input.md +52 -0
  40. package/dist/docs/collapse.md +46 -0
  41. package/dist/docs/color-picker.md +145 -0
  42. package/dist/docs/combobox.md +208 -0
  43. package/dist/docs/command-palette.md +65 -0
  44. package/dist/docs/date-picker.md +167 -0
  45. package/dist/docs/dialog.md +271 -0
  46. package/dist/docs/disclosure.md +88 -0
  47. package/dist/docs/editable-cell.md +90 -0
  48. package/dist/docs/empty-state.md +46 -0
  49. package/dist/docs/field.md +82 -0
  50. package/dist/docs/file-drop.md +44 -0
  51. package/dist/docs/filter-bar.md +66 -0
  52. package/dist/docs/header.md +51 -0
  53. package/dist/docs/hover-card.md +110 -0
  54. package/dist/docs/icon-picker.md +65 -0
  55. package/dist/docs/input-group.md +89 -0
  56. package/dist/docs/input.md +33 -0
  57. package/dist/docs/inset.md +57 -0
  58. package/dist/docs/kbd.md +34 -0
  59. package/dist/docs/keypad.md +51 -0
  60. package/dist/docs/load-more.md +66 -0
  61. package/dist/docs/locale-provider.md +99 -0
  62. package/dist/docs/marquee.md +86 -0
  63. package/dist/docs/menu.md +456 -0
  64. package/dist/docs/meter.md +102 -0
  65. package/dist/docs/money-input.md +169 -0
  66. package/dist/docs/month-picker.md +80 -0
  67. package/dist/docs/navigation-menu.md +157 -0
  68. package/dist/docs/number-field.md +129 -0
  69. package/dist/docs/page-header.md +44 -0
  70. package/dist/docs/page-transition.md +93 -0
  71. package/dist/docs/pagination.md +42 -0
  72. package/dist/docs/pills.md +85 -0
  73. package/dist/docs/player-bar.md +158 -0
  74. package/dist/docs/popover.md +200 -0
  75. package/dist/docs/progress-ring.md +70 -0
  76. package/dist/docs/radio-cards.md +82 -0
  77. package/dist/docs/radio-group.md +86 -0
  78. package/dist/docs/range-slider.md +64 -0
  79. package/dist/docs/repeat-picker.md +44 -0
  80. package/dist/docs/resizable.md +107 -0
  81. package/dist/docs/seek-bar.md +97 -0
  82. package/dist/docs/segmented.md +89 -0
  83. package/dist/docs/select.md +148 -0
  84. package/dist/docs/separator.md +76 -0
  85. package/dist/docs/side-nav.md +75 -0
  86. package/dist/docs/skeleton.md +89 -0
  87. package/dist/docs/slider.md +87 -0
  88. package/dist/docs/sortable.md +244 -0
  89. package/dist/docs/sparkline.md +56 -0
  90. package/dist/docs/spinner.md +69 -0
  91. package/dist/docs/status-pill.md +81 -0
  92. package/dist/docs/stepper.md +59 -0
  93. package/dist/docs/tab-bar.md +78 -0
  94. package/dist/docs/table-of-contents.md +43 -0
  95. package/dist/docs/table.md +714 -0
  96. package/dist/docs/tabs.md +140 -0
  97. package/dist/docs/tag-input.md +45 -0
  98. package/dist/docs/textarea.md +25 -0
  99. package/dist/docs/theme-toggle.md +85 -0
  100. package/dist/docs/theming.md +193 -0
  101. package/dist/docs/time-field.md +71 -0
  102. package/dist/docs/timeline.md +50 -0
  103. package/dist/docs/toast.md +53 -0
  104. package/dist/docs/toggle-group.md +83 -0
  105. package/dist/docs/toggle.md +38 -0
  106. package/dist/docs/toolbar.md +97 -0
  107. package/dist/docs/tooltip.md +102 -0
  108. package/dist/docs/tree.md +295 -0
  109. package/dist/docs/trend.md +50 -0
  110. package/dist/filter-bar/index.js +6 -6
  111. package/dist/header/index.js +6 -6
  112. package/dist/icon-picker/index.js +5 -5
  113. package/dist/icons/arrow-path.d.ts +3 -0
  114. package/dist/icons/arrow-path.d.ts.map +1 -0
  115. package/dist/icons/arrows-right-left.d.ts +3 -0
  116. package/dist/icons/arrows-right-left.d.ts.map +1 -0
  117. package/dist/icons/backward.d.ts +3 -0
  118. package/dist/icons/backward.d.ts.map +1 -0
  119. package/dist/icons/forward.d.ts +3 -0
  120. package/dist/icons/forward.d.ts.map +1 -0
  121. package/dist/icons/heart-solid.d.ts +3 -0
  122. package/dist/icons/heart-solid.d.ts.map +1 -0
  123. package/dist/icons/heart.d.ts +3 -0
  124. package/dist/icons/heart.d.ts.map +1 -0
  125. package/dist/icons/musical-note.d.ts +3 -0
  126. package/dist/icons/musical-note.d.ts.map +1 -0
  127. package/dist/icons/pause.d.ts +3 -0
  128. package/dist/icons/pause.d.ts.map +1 -0
  129. package/dist/icons/play.d.ts +3 -0
  130. package/dist/icons/play.d.ts.map +1 -0
  131. package/dist/icons/queue-list.d.ts +3 -0
  132. package/dist/icons/queue-list.d.ts.map +1 -0
  133. package/dist/icons/speaker-wave.d.ts +3 -0
  134. package/dist/icons/speaker-wave.d.ts.map +1 -0
  135. package/dist/icons/speaker-x-mark.d.ts +3 -0
  136. package/dist/icons/speaker-x-mark.d.ts.map +1 -0
  137. package/dist/index.d.ts +7 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/keypad/index.js +5 -5
  140. package/dist/lib.js +86 -80
  141. package/dist/load-more/index.js +5 -5
  142. package/dist/marquee/index.d.ts +15 -0
  143. package/dist/marquee/index.d.ts.map +1 -0
  144. package/dist/marquee/index.js +90 -0
  145. package/dist/menu/index.d.ts +7 -1
  146. package/dist/menu/index.d.ts.map +1 -1
  147. package/dist/menu/index.js +222 -178
  148. package/dist/money-input/index.js +54 -54
  149. package/dist/month-picker/index.js +11 -11
  150. package/dist/number-field/index.js +5 -5
  151. package/dist/pagination/index.js +12 -12
  152. package/dist/player-bar/index.d.ts +11 -0
  153. package/dist/player-bar/index.d.ts.map +1 -0
  154. package/dist/player-bar/index.js +17 -0
  155. package/dist/radio-cards/index.d.ts +2 -1
  156. package/dist/radio-cards/index.d.ts.map +1 -1
  157. package/dist/radio-cards/index.js +3 -3
  158. package/dist/range-slider/index.js +11 -11
  159. package/dist/repeat-picker/index.js +5 -5
  160. package/dist/resizable/index.js +22 -22
  161. package/dist/seek-bar/index.d.ts +26 -0
  162. package/dist/seek-bar/index.d.ts.map +1 -0
  163. package/dist/seek-bar/index.js +121 -0
  164. package/dist/segmented/index.d.ts +3 -2
  165. package/dist/segmented/index.d.ts.map +1 -1
  166. package/dist/segmented/index.js +19 -18
  167. package/dist/select/index.js +21 -21
  168. package/dist/slider/index.d.ts +2 -1
  169. package/dist/slider/index.d.ts.map +1 -1
  170. package/dist/sortable/index.d.ts +13 -1
  171. package/dist/sortable/index.d.ts.map +1 -1
  172. package/dist/sortable/index.js +74 -55
  173. package/dist/sortable/shared.js +14 -14
  174. package/dist/sortable/tree.js +17 -17
  175. package/dist/sparkline/index.js +4 -4
  176. package/dist/stepper/index.js +13 -13
  177. package/dist/tab-bar/index.d.ts +4 -2
  178. package/dist/tab-bar/index.d.ts.map +1 -1
  179. package/dist/tab-bar/index.js +24 -19
  180. package/dist/table/index.js +26 -26
  181. package/dist/table/selection.js +9 -9
  182. package/dist/table-of-contents/index.js +11 -11
  183. package/dist/tag-input/index.js +5 -5
  184. package/dist/textarea/index.d.ts +6 -2
  185. package/dist/textarea/index.d.ts.map +1 -1
  186. package/dist/textarea/index.js +2 -1
  187. package/dist/theme-toggle/index.js +4 -4
  188. package/dist/theme.css +143 -0
  189. package/dist/time-field/index.js +21 -21
  190. package/dist/toast/index.d.ts.map +1 -1
  191. package/dist/toast/index.js +41 -41
  192. package/dist/tooltip/index.d.ts +9 -3
  193. package/dist/tooltip/index.d.ts.map +1 -1
  194. package/dist/tooltip/index.js +19 -16
  195. package/dist/tree/index.js +34 -34
  196. package/dist/trend/index.js +5 -5
  197. package/dist/utils/duration.d.ts +3 -0
  198. package/dist/utils/duration.d.ts.map +1 -0
  199. package/dist/utils/duration.js +7 -0
  200. package/dist/utils/messages.d.ts +3 -0
  201. package/dist/utils/messages.d.ts.map +1 -1
  202. package/dist/utils/messages.js +4 -1
  203. package/dist/utils/slot.d.ts +5 -2
  204. package/dist/utils/slot.d.ts.map +1 -1
  205. package/dist/utils/slot.js +16 -11
  206. package/dist/utils/swipe.d.ts +7 -0
  207. package/dist/utils/swipe.d.ts.map +1 -1
  208. package/dist/utils/swipe.js +45 -25
  209. package/dist/utils/useAnchoredPopup.d.ts +2 -1
  210. package/dist/utils/useAnchoredPopup.d.ts.map +1 -1
  211. package/dist/utils/useAnchoredPopup.js +10 -5
  212. package/dist/utils/useHeightVar.d.ts +7 -0
  213. package/dist/utils/useHeightVar.d.ts.map +1 -0
  214. package/dist/utils/useHeightVar.js +17 -0
  215. package/dist/utils/useMediaPlayer.d.ts +38 -0
  216. package/dist/utils/useMediaPlayer.d.ts.map +1 -0
  217. package/dist/utils/useMediaPlayer.js +91 -0
  218. package/dist/utils/useMediaSession.d.ts +24 -0
  219. package/dist/utils/useMediaSession.d.ts.map +1 -0
  220. package/dist/utils/useMediaSession.js +76 -0
  221. package/dist/utils/useVirtualList.d.ts +6 -1
  222. package/dist/utils/useVirtualList.d.ts.map +1 -1
  223. package/dist/utils/useVirtualList.js +12 -12
  224. package/dist/zen.css +1 -1
  225. package/package.json +4 -2
@@ -0,0 +1,69 @@
1
+ # Spinner
2
+
3
+ A small loading spinner in the current text colour, announced to screen readers when labelled.
4
+
5
+ ```tsx
6
+ import { Spinner } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ ```tsx
14
+ import { Spinner } from '@rinzai/zen';
15
+
16
+ /** Sized and coloured with className; it follows the text colour. */
17
+ export default function Default() {
18
+ return (
19
+ <div className="flex items-center gap-6">
20
+ <Spinner />
21
+ <Spinner className="size-6" />
22
+ <Spinner className="text-primary size-8 border-[3px]" />
23
+ <Spinner className="text-muted-foreground size-5" />
24
+ </div>
25
+ );
26
+ }
27
+ ```
28
+
29
+ ### Loading
30
+
31
+ ```tsx
32
+ import { Button, Card, CardHeader, CardTitle, Spinner } from '@rinzai/zen';
33
+ import { useState } from 'react';
34
+
35
+ /** Standing on its own, a spinner needs a label so screen readers announce what is loading. */
36
+ export default function Loading() {
37
+ const [loading, setLoading] = useState(true);
38
+ return (
39
+ <Card className="w-80">
40
+ <CardHeader>
41
+ <CardTitle>Entries</CardTitle>
42
+ </CardHeader>
43
+ {loading ? (
44
+ <div className="text-muted-foreground flex items-center gap-3 py-6 text-sm">
45
+ <Spinner label="Loading entries" />
46
+ Loading entries…
47
+ </div>
48
+ ) : (
49
+ <p className="py-6 text-sm">12 entries this month.</p>
50
+ )}
51
+ <Button variant="outline" size="sm" onClick={() => setLoading((l) => !l)}>
52
+ {loading ? 'Finish loading' : 'Load again'}
53
+ </Button>
54
+ </Card>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ## API reference
60
+
61
+ ### Spinner
62
+
63
+ Small circular spinner in the current text colour; size it with className
64
+ (default size-4). Decorative by default (e.g. inside a loading Button). Give
65
+ it a `label` when it stands on its own, and screen readers announce it.
66
+
67
+ | Prop | Type | Default | Description |
68
+ | --- | --- | --- | --- |
69
+ | `label` | `string` | | What is loading, e.g. "Loading entries". Makes the spinner announce itself. |
@@ -0,0 +1,81 @@
1
+ # Status Pill
2
+
3
+ A small status that changes in place, such as Saving…, Saved or Not saved with a Retry, and fades back once the news is old.
4
+
5
+ ```tsx
6
+ import { StatusPill, StatusPillAction } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Save
12
+
13
+ ```tsx
14
+ import { Button, Spinner, StatusPill, StatusPillAction } from '@rinzai/zen';
15
+ import { useEffect, useState } from 'react';
16
+ // Icons from Heroicons (https://heroicons.com): AlertTriangle (exclamation-triangle), Check (check).
17
+
18
+ type Save = 'saving' | 'saved' | 'error';
19
+
20
+ /** A save indicator: saving spins, saved checks and then quietens, a failure is red and offers a retry. */
21
+ export default function Save() {
22
+ const [state, setState] = useState<Save>('saved');
23
+ const [quiet, setQuiet] = useState(false);
24
+ useEffect(() => {
25
+ setQuiet(false);
26
+ if (state !== 'saved') return;
27
+ const t = window.setTimeout(() => setQuiet(true), 2500);
28
+ return () => window.clearTimeout(t);
29
+ }, [state]);
30
+ const save = (ok: boolean) => {
31
+ setState('saving');
32
+ window.setTimeout(() => setState(ok ? 'saved' : 'error'), 1200);
33
+ };
34
+
35
+ return (
36
+ <div className="flex flex-col items-center gap-4">
37
+ {state === 'error' ? (
38
+ <StatusPill tone="negative">
39
+ <AlertTriangle />
40
+ Not saved
41
+ <StatusPillAction onClick={() => save(true)}>Retry</StatusPillAction>
42
+ </StatusPill>
43
+ ) : (
44
+ <StatusPill tone={state === 'saved' ? 'positive' : 'default'} quiet={state === 'saved' && quiet}>
45
+ {state === 'saving' ? <Spinner /> : <Check />}
46
+ {state === 'saving' ? 'Saving…' : 'Saved'}
47
+ </StatusPill>
48
+ )}
49
+ <div className="flex gap-2">
50
+ <Button variant="outline" size="sm" onClick={() => save(true)}>
51
+ Save
52
+ </Button>
53
+ <Button variant="outline" size="sm" onClick={() => save(false)}>
54
+ Save and fail
55
+ </Button>
56
+ </div>
57
+ </div>
58
+ );
59
+ }
60
+ ```
61
+
62
+ ## API reference
63
+
64
+ ### StatusPill
65
+
66
+ A small rounded status that changes in place, e.g. an app's "Saving…",
67
+ "Saved", "Not saved · Retry": an icon (a Spinner, a Check) and a few words.
68
+ `quiet` fades it back once the news is old (a save a few seconds ago).
69
+ Changes are read out politely (role="status"). For an action inside it,
70
+ such as Retry, use StatusPillAction. For a fixed label or count, use Badge.
71
+
72
+ | Prop | Type | Default | Description |
73
+ | --- | --- | --- | --- |
74
+ | `quiet` | `boolean` | `false` | Faded back into the page: the news is old. |
75
+ | `tone` | `"default" \| "negative" \| "positive"` | `default` | `positive` in the accent colour (done), `negative` in red (failed); `default` is muted (in progress). |
76
+
77
+ ### StatusPillAction
78
+
79
+ A text button inside a StatusPill, e.g. Retry, in the pill's colour.
80
+
81
+ No props of its own; it accepts the props of the element it renders.
@@ -0,0 +1,59 @@
1
+ # Stepper
2
+
3
+ The steps of a flow and where you are in it; the line between them fills in as you go.
4
+
5
+ ```tsx
6
+ import { Stepper, Step } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ ```tsx
14
+ import { Button, Step, Stepper } from '@rinzai/zen';
15
+ import { useState } from 'react';
16
+
17
+ /** Importing a statement in three steps. */
18
+ export default function Default() {
19
+ const [step, setStep] = useState(1);
20
+ return (
21
+ <div className="flex w-full max-w-lg flex-col items-center gap-8">
22
+ <Stepper value={step}>
23
+ <Step description="CSV or Excel">Upload</Step>
24
+ <Step description="Match the columns">Map</Step>
25
+ <Step description="Check and import">Review</Step>
26
+ </Stepper>
27
+ <div className="flex gap-2">
28
+ <Button variant="outline" disabled={step === 0} onClick={() => setStep(step - 1)}>
29
+ Back
30
+ </Button>
31
+ <Button disabled={step === 3} onClick={() => setStep(step + 1)}>
32
+ {step >= 2 ? 'Import' : 'Next'}
33
+ </Button>
34
+ </div>
35
+ </div>
36
+ );
37
+ }
38
+ ```
39
+
40
+ ## API reference
41
+
42
+ ### Stepper
43
+
44
+ The steps of a flow (sign-up, checkout, import), with where you are: steps
45
+ before `value` (from 0) are done, the one at it is current. The line between
46
+ them fills in as you go.
47
+
48
+ | Prop | Type | Default | Description |
49
+ | --- | --- | --- | --- |
50
+ | `value` (required) | `number` | | The current step, from 0. Steps before it are done; past the last, all are. |
51
+
52
+ ### Step
53
+
54
+ One step's label, and optionally a line under it (`description`).
55
+
56
+ | Prop | Type | Default | Description |
57
+ | --- | --- | --- | --- |
58
+ | `className` | `string` | | |
59
+ | `description` | `ReactNode` | | |
@@ -0,0 +1,78 @@
1
+ # Tab Bar
2
+
3
+ Phone navigation fixed to the bottom of the screen. Works with any router.
4
+
5
+ ```tsx
6
+ import { TabBar, TabBarItem } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ ```tsx
14
+ import { TabBar, TabBarItem } from '@rinzai/zen';
15
+ import { useState } from 'react';
16
+ // Icons from Heroicons (https://heroicons.com): CalendarIcon (calendar), Flag (flag), Settings (cog-6-tooth), TableIcon (table-cells).
17
+
18
+ const TABS = [
19
+ { label: 'Month', icon: <CalendarIcon /> },
20
+ { label: 'Planner', icon: <TableIcon /> },
21
+ { label: 'Goals', icon: <Flag /> },
22
+ { label: 'Settings', icon: <Settings /> },
23
+ ];
24
+
25
+ /** Phone navigation. Fixed to the bottom of the screen; here it sits in a phone-sized frame. */
26
+ export default function Default() {
27
+ const [current, setCurrent] = useState('Month');
28
+ return (
29
+ <div className="border-tint/10 relative h-72 w-80 [transform:translateZ(0)] overflow-hidden rounded-2xl border">
30
+ <p className="text-muted-foreground p-4 text-sm">{current}</p>
31
+ <TabBar aria-label="Main" hideFrom={false} className="absolute! rounded-b-[15px]">
32
+ {TABS.map((t) => (
33
+ <TabBarItem
34
+ key={t.label}
35
+ href={`#${t.label.toLowerCase()}`}
36
+ icon={t.icon}
37
+ active={t.label === current}
38
+ onClick={(e) => {
39
+ e.preventDefault();
40
+ setCurrent(t.label);
41
+ }}
42
+ >
43
+ {t.label}
44
+ </TabBarItem>
45
+ ))}
46
+ </TabBar>
47
+ </div>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## API reference
53
+
54
+ ### TabBar
55
+
56
+ Phone navigation: a glass bar fixed to the bottom, clear of the home
57
+ indicator, hidden from `hideFrom` up (default md). Fill it with TabBarItems.
58
+ Its height is kept in `--zen-tab-bar-height` on its parent (0px while
59
+ hidden): a PlayerBar beside it sits on it, and the page can pad its end by it.
60
+ Inside a rounded frame, round the bar to match (className, e.g.
61
+ rounded-b-[15px]): with GPU compositing, Chrome doesn't clip a blurred
62
+ backdrop to an ancestor's rounded corners, only to the element's own.
63
+
64
+ | Prop | Type | Default | Description |
65
+ | --- | --- | --- | --- |
66
+ | `hideFrom` | `"lg" \| "md" \| "sm" \| false` | `md` | Hide the bar from this breakpoint up (false: always show). |
67
+
68
+ ### TabBarItem
69
+
70
+ One destination: an icon over a label. `active` marks the current page; with
71
+ `asChild`, the styles go onto your own link (e.g. a router's NavLink, which
72
+ sets aria-current itself).
73
+
74
+ | Prop | Type | Default | Description |
75
+ | --- | --- | --- | --- |
76
+ | `active` | `boolean` | | |
77
+ | `asChild` | `boolean` | | Style the single child element (a router link holding the label) instead of rendering an <a>; `icon` goes inside it. |
78
+ | `icon` | `ReactNode` | | |
@@ -0,0 +1,43 @@
1
+ # Table of Contents
2
+
3
+ An "On this page" list that highlights the section being read.
4
+
5
+ ```tsx
6
+ import { TableOfContents } from '@rinzai/zen';
7
+ ```
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ ```tsx
14
+ import { TableOfContents } from '@rinzai/zen';
15
+
16
+ /** Point items at heading ids; the link for the section being read lights up as you scroll. */
17
+ export default function Default() {
18
+ return (
19
+ <TableOfContents
20
+ className="w-48"
21
+ items={[
22
+ { id: 'installation', label: 'Installation' },
23
+ { id: 'usage', label: 'Usage' },
24
+ { id: 'theming', label: 'Theming' },
25
+ { id: 'tokens', label: 'Tokens', depth: 2 },
26
+ ]}
27
+ />
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## API reference
33
+
34
+ ### TableOfContents
35
+
36
+ "On this page": links to the page's headings, highlighting the section being
37
+ read. Items point at element ids; nested items (depth 2) are indented.
38
+
39
+ | Prop | Type | Default | Description |
40
+ | --- | --- | --- | --- |
41
+ | `items` (required) | `TableOfContentsItem[]` | | |
42
+ | `className` | `string` | | |
43
+ | `title` | `string` | | Shown above the list, and names it. Empty: no heading shown (e.g. under a trigger that says it). |