@adres/mgda-ui 0.0.0-stage → 0.0.1
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.
- package/brand-knowledge.json +451 -0
- package/knowledge/accordion.md +135 -0
- package/knowledge/activity-rings.md +123 -0
- package/knowledge/alert.md +184 -0
- package/knowledge/answer-actions.md +217 -0
- package/knowledge/aspect-ratio.md +82 -0
- package/knowledge/avatar.md +158 -0
- package/knowledge/badge.md +172 -0
- package/knowledge/bar-graph.md +167 -0
- package/knowledge/bento-grid.md +115 -0
- package/knowledge/blockquote.md +153 -0
- package/knowledge/box-list.md +177 -0
- package/knowledge/bullet-list.md +128 -0
- package/knowledge/button-group.md +179 -0
- package/knowledge/button.md +231 -0
- package/knowledge/calendar.md +168 -0
- package/knowledge/card.md +321 -0
- package/knowledge/cards-nav.md +170 -0
- package/knowledge/chain-of-thought.md +164 -0
- package/knowledge/chat-container.md +135 -0
- package/knowledge/chat-message.md +224 -0
- package/knowledge/checkbox-card.md +172 -0
- package/knowledge/checkbox.md +111 -0
- package/knowledge/citations.md +241 -0
- package/knowledge/combobox.md +265 -0
- package/knowledge/countdown-pill.md +153 -0
- package/knowledge/cta.md +118 -0
- package/knowledge/data-list.md +173 -0
- package/knowledge/data-table.md +220 -0
- package/knowledge/dialog.md +249 -0
- package/knowledge/drawer.md +236 -0
- package/knowledge/dropdown-menu.md +238 -0
- package/knowledge/dropzone.md +153 -0
- package/knowledge/email-chips-input.md +161 -0
- package/knowledge/empty-state.md +106 -0
- package/knowledge/entity-header.md +166 -0
- package/knowledge/feature-grid.md +120 -0
- package/knowledge/feedback-bar.md +127 -0
- package/knowledge/footer.md +116 -0
- package/knowledge/heading.md +189 -0
- package/knowledge/hero.md +361 -0
- package/knowledge/input-button.md +187 -0
- package/knowledge/input-group.md +185 -0
- package/knowledge/input.md +256 -0
- package/knowledge/inset.md +177 -0
- package/knowledge/kpi-card.md +206 -0
- package/knowledge/list-nav.md +181 -0
- package/knowledge/logo-cloud.md +102 -0
- package/knowledge/media-gallery.md +158 -0
- package/knowledge/message-actions.md +175 -0
- package/knowledge/nav-sidebar.md +225 -0
- package/knowledge/number-stepper.md +159 -0
- package/knowledge/page-header.md +109 -0
- package/knowledge/pagination.md +225 -0
- package/knowledge/popover.md +159 -0
- package/knowledge/pricing.md +132 -0
- package/knowledge/progress.md +156 -0
- package/knowledge/prompt-input.md +337 -0
- package/knowledge/prompt-suggestions.md +168 -0
- package/knowledge/quota-bar.md +160 -0
- package/knowledge/quote.md +116 -0
- package/knowledge/radio-card.md +172 -0
- package/knowledge/radio-group.md +135 -0
- package/knowledge/reasoning.md +142 -0
- package/knowledge/search.md +131 -0
- package/knowledge/section-nav.md +162 -0
- package/knowledge/segmented-control.md +181 -0
- package/knowledge/select-button.md +205 -0
- package/knowledge/select.md +210 -0
- package/knowledge/separator.md +75 -0
- package/knowledge/shimmer-text.md +140 -0
- package/knowledge/sidebar.md +227 -0
- package/knowledge/skeleton.md +142 -0
- package/knowledge/slider.md +133 -0
- package/knowledge/slideshow.md +159 -0
- package/knowledge/source.md +156 -0
- package/knowledge/spinner.md +120 -0
- package/knowledge/stat-strip.md +128 -0
- package/knowledge/stats.md +117 -0
- package/knowledge/step-indicator.md +157 -0
- package/knowledge/switch.md +88 -0
- package/knowledge/table.md +190 -0
- package/knowledge/tabs.md +169 -0
- package/knowledge/testimonials.md +115 -0
- package/knowledge/text-link.md +192 -0
- package/knowledge/text.md +194 -0
- package/knowledge/thinking-bar.md +115 -0
- package/knowledge/thinking-steps.md +140 -0
- package/knowledge/toaster.md +127 -0
- package/knowledge/toggle.md +113 -0
- package/knowledge/tool-call-card.md +241 -0
- package/knowledge/tooltip.md +120 -0
- package/knowledge/top-nav.md +138 -0
- package/knowledge.json +19854 -0
- package/package.json +94 -4
- package/src/components/accordion.stories.tsx +46 -0
- package/src/components/accordion.tsx +74 -0
- package/src/components/activity-rings.stories.tsx +73 -0
- package/src/components/activity-rings.tsx +121 -0
- package/src/components/alert.stories.tsx +43 -0
- package/src/components/alert.tsx +132 -0
- package/src/components/answer-actions.stories.tsx +54 -0
- package/src/components/answer-actions.test.tsx +37 -0
- package/src/components/answer-actions.tsx +313 -0
- package/src/components/aspect-ratio.stories.tsx +32 -0
- package/src/components/aspect-ratio.tsx +5 -0
- package/src/components/avatar.stories.tsx +40 -0
- package/src/components/avatar.tsx +154 -0
- package/src/components/badge.stories.tsx +27 -0
- package/src/components/badge.tsx +63 -0
- package/src/components/bar-graph.stories.tsx +28 -0
- package/src/components/bar-graph.tsx +204 -0
- package/src/components/bento-grid.stories.tsx +23 -0
- package/src/components/bento-grid.tsx +67 -0
- package/src/components/blockquote.stories.tsx +28 -0
- package/src/components/blockquote.tsx +88 -0
- package/src/components/box-list.stories.tsx +25 -0
- package/src/components/box-list.tsx +108 -0
- package/src/components/bullet-list.stories.tsx +22 -0
- package/src/components/bullet-list.tsx +101 -0
- package/src/components/button-group.stories.tsx +31 -0
- package/src/components/button-group.tsx +156 -0
- package/src/components/button.stories.tsx +66 -0
- package/src/components/button.test.ts +17 -0
- package/src/components/button.tsx +139 -0
- package/src/components/calendar.stories.tsx +25 -0
- package/src/components/calendar.tsx +367 -0
- package/src/components/card.stories.tsx +44 -0
- package/src/components/card.tsx +392 -0
- package/src/components/cards-nav.stories.tsx +35 -0
- package/src/components/cards-nav.tsx +115 -0
- package/src/components/chain-of-thought.stories.tsx +67 -0
- package/src/components/chain-of-thought.test.tsx +50 -0
- package/src/components/chain-of-thought.tsx +170 -0
- package/src/components/chat-container.stories.tsx +47 -0
- package/src/components/chat-container.test.tsx +49 -0
- package/src/components/chat-container.tsx +222 -0
- package/src/components/chat-message.stories.tsx +52 -0
- package/src/components/chat-message.test.tsx +36 -0
- package/src/components/chat-message.tsx +163 -0
- package/src/components/checkbox-card.stories.tsx +27 -0
- package/src/components/checkbox-card.tsx +200 -0
- package/src/components/checkbox.stories.tsx +26 -0
- package/src/components/checkbox.tsx +61 -0
- package/src/components/citations.stories.tsx +64 -0
- package/src/components/citations.test.tsx +61 -0
- package/src/components/citations.tsx +220 -0
- package/src/components/combobox.stories.tsx +184 -0
- package/src/components/combobox.test.tsx +82 -0
- package/src/components/combobox.tsx +407 -0
- package/src/components/countdown-pill.stories.tsx +24 -0
- package/src/components/countdown-pill.tsx +129 -0
- package/src/components/cta.stories.tsx +29 -0
- package/src/components/cta.tsx +52 -0
- package/src/components/data-list.stories.tsx +50 -0
- package/src/components/data-list.test.tsx +35 -0
- package/src/components/data-list.tsx +181 -0
- package/src/components/data-table.stories.tsx +29 -0
- package/src/components/data-table.tsx +200 -0
- package/src/components/dialog.stories.tsx +42 -0
- package/src/components/dialog.tsx +200 -0
- package/src/components/drawer.stories.tsx +48 -0
- package/src/components/drawer.tsx +385 -0
- package/src/components/dropdown-menu.stories.tsx +41 -0
- package/src/components/dropdown-menu.tsx +252 -0
- package/src/components/dropzone.stories.tsx +19 -0
- package/src/components/dropzone.tsx +250 -0
- package/src/components/email-chips-input.stories.tsx +135 -0
- package/src/components/email-chips-input.tsx +210 -0
- package/src/components/empty-state.stories.tsx +22 -0
- package/src/components/empty-state.tsx +35 -0
- package/src/components/entity-header.stories.tsx +43 -0
- package/src/components/entity-header.test.tsx +35 -0
- package/src/components/entity-header.tsx +92 -0
- package/src/components/feature-grid.stories.tsx +25 -0
- package/src/components/feature-grid.tsx +87 -0
- package/src/components/feedback-bar.stories.tsx +25 -0
- package/src/components/feedback-bar.test.tsx +24 -0
- package/src/components/feedback-bar.tsx +62 -0
- package/src/components/footer.stories.tsx +23 -0
- package/src/components/footer.tsx +78 -0
- package/src/components/heading.stories.tsx +45 -0
- package/src/components/heading.test.tsx +22 -0
- package/src/components/heading.tsx +77 -0
- package/src/components/hero.stories.tsx +38 -0
- package/src/components/hero.tsx +498 -0
- package/src/components/input-button.stories.tsx +19 -0
- package/src/components/input-button.tsx +112 -0
- package/src/components/input-group.stories.tsx +38 -0
- package/src/components/input-group.tsx +157 -0
- package/src/components/input.stories.tsx +31 -0
- package/src/components/input.tsx +284 -0
- package/src/components/inset.stories.tsx +29 -0
- package/src/components/inset.tsx +70 -0
- package/src/components/kpi-card.stories.tsx +29 -0
- package/src/components/kpi-card.tsx +284 -0
- package/src/components/list-nav.stories.tsx +22 -0
- package/src/components/list-nav.tsx +145 -0
- package/src/components/logo-cloud.stories.tsx +23 -0
- package/src/components/logo-cloud.tsx +42 -0
- package/src/components/media-gallery.stories.tsx +25 -0
- package/src/components/media-gallery.tsx +347 -0
- package/src/components/message-actions.stories.tsx +45 -0
- package/src/components/message-actions.test.tsx +32 -0
- package/src/components/message-actions.tsx +119 -0
- package/src/components/nav-sidebar.stories.tsx +58 -0
- package/src/components/nav-sidebar.test.tsx +54 -0
- package/src/components/nav-sidebar.tsx +462 -0
- package/src/components/number-stepper.stories.tsx +19 -0
- package/src/components/number-stepper.tsx +158 -0
- package/src/components/page-header.stories.tsx +25 -0
- package/src/components/page-header.tsx +64 -0
- package/src/components/pagination.stories.tsx +110 -0
- package/src/components/pagination.test.tsx +46 -0
- package/src/components/pagination.tsx +144 -0
- package/src/components/popover.stories.tsx +26 -0
- package/src/components/popover.tsx +62 -0
- package/src/components/pricing.stories.tsx +42 -0
- package/src/components/pricing.tsx +130 -0
- package/src/components/progress.stories.tsx +22 -0
- package/src/components/progress.tsx +189 -0
- package/src/components/prompt-input.stories.tsx +62 -0
- package/src/components/prompt-input.test.tsx +106 -0
- package/src/components/prompt-input.tsx +343 -0
- package/src/components/prompt-suggestions.stories.tsx +53 -0
- package/src/components/prompt-suggestions.test.tsx +37 -0
- package/src/components/prompt-suggestions.tsx +122 -0
- package/src/components/quota-bar.stories.tsx +19 -0
- package/src/components/quota-bar.tsx +191 -0
- package/src/components/quote.stories.tsx +18 -0
- package/src/components/quote.tsx +43 -0
- package/src/components/radio-card.stories.tsx +27 -0
- package/src/components/radio-card.tsx +225 -0
- package/src/components/radio-group.stories.tsx +32 -0
- package/src/components/radio-group.tsx +68 -0
- package/src/components/reasoning.stories.tsx +50 -0
- package/src/components/reasoning.test.tsx +48 -0
- package/src/components/reasoning.tsx +143 -0
- package/src/components/search.stories.tsx +18 -0
- package/src/components/search.tsx +133 -0
- package/src/components/section-nav.stories.tsx +59 -0
- package/src/components/section-nav.test.tsx +36 -0
- package/src/components/section-nav.tsx +146 -0
- package/src/components/segmented-control.stories.tsx +22 -0
- package/src/components/segmented-control.tsx +301 -0
- package/src/components/select-button.stories.tsx +27 -0
- package/src/components/select-button.tsx +174 -0
- package/src/components/select.stories.tsx +27 -0
- package/src/components/select.tsx +198 -0
- package/src/components/separator.stories.tsx +22 -0
- package/src/components/separator.tsx +23 -0
- package/src/components/shimmer-text.stories.tsx +23 -0
- package/src/components/shimmer-text.test.tsx +35 -0
- package/src/components/shimmer-text.tsx +43 -0
- package/src/components/sidebar.stories.tsx +25 -0
- package/src/components/sidebar.tsx +234 -0
- package/src/components/skeleton.stories.tsx +22 -0
- package/src/components/skeleton.tsx +96 -0
- package/src/components/slider.stories.tsx +20 -0
- package/src/components/slider.tsx +176 -0
- package/src/components/slideshow.stories.tsx +30 -0
- package/src/components/slideshow.tsx +291 -0
- package/src/components/source.stories.tsx +32 -0
- package/src/components/source.test.tsx +40 -0
- package/src/components/source.tsx +161 -0
- package/src/components/spinner.stories.tsx +19 -0
- package/src/components/spinner.tsx +76 -0
- package/src/components/stat-strip.stories.tsx +36 -0
- package/src/components/stat-strip.test.tsx +25 -0
- package/src/components/stat-strip.tsx +85 -0
- package/src/components/stats.stories.tsx +24 -0
- package/src/components/stats.tsx +83 -0
- package/src/components/step-indicator.stories.tsx +18 -0
- package/src/components/step-indicator.test.tsx +18 -0
- package/src/components/step-indicator.tsx +286 -0
- package/src/components/switch.stories.tsx +26 -0
- package/src/components/switch.tsx +32 -0
- package/src/components/table.stories.tsx +38 -0
- package/src/components/table.tsx +220 -0
- package/src/components/tabs.stories.tsx +25 -0
- package/src/components/tabs.tsx +276 -0
- package/src/components/testimonials.stories.tsx +22 -0
- package/src/components/testimonials.tsx +109 -0
- package/src/components/text-link.stories.tsx +47 -0
- package/src/components/text-link.test.tsx +18 -0
- package/src/components/text-link.tsx +88 -0
- package/src/components/text.stories.tsx +49 -0
- package/src/components/text.tsx +105 -0
- package/src/components/thinking-bar.stories.tsx +19 -0
- package/src/components/thinking-bar.test.tsx +27 -0
- package/src/components/thinking-bar.tsx +64 -0
- package/src/components/thinking-steps.stories.tsx +44 -0
- package/src/components/thinking-steps.test.tsx +42 -0
- package/src/components/thinking-steps.tsx +92 -0
- package/src/components/toaster.stories.tsx +80 -0
- package/src/components/toaster.tsx +36 -0
- package/src/components/toggle.stories.tsx +21 -0
- package/src/components/toggle.tsx +103 -0
- package/src/components/tool-call-card.stories.tsx +97 -0
- package/src/components/tool-call-card.test.tsx +88 -0
- package/src/components/tool-call-card.tsx +231 -0
- package/src/components/tooltip.stories.tsx +25 -0
- package/src/components/tooltip.tsx +43 -0
- package/src/components/top-nav.stories.tsx +20 -0
- package/src/components/top-nav.tsx +76 -0
- package/src/docs/Colors.stories.tsx +192 -0
- package/src/docs/GettingStarted.mdx +72 -0
- package/src/docs/Mcp.mdx +52 -0
- package/src/docs/Typography.stories.tsx +114 -0
- package/src/hooks/use-in-view.ts +32 -0
- package/src/hooks/use-reduced-motion.ts +26 -0
- package/src/index.ts +343 -0
- package/src/lib/cn.test.ts +67 -0
- package/src/lib/cn.ts +81 -0
- package/src/lib/motion.ts +109 -0
- package/src/lib/prefix-utilities.test.ts +56 -0
- package/src/lib/prefix-utilities.ts +50 -0
- package/src/styles/base.css +489 -0
- package/src/styles/motion.css +69 -0
- package/src/styles/overrides.css +44 -0
- package/src/styles/typography.css +173 -0
- package/src/theme/theme.css +391 -0
- package/src/theme/tokens.ts +29 -0
- package/src/theme/types.ts +26 -0
- package/README.md +0 -3
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: radio-group
|
|
6
|
+
sourceFile: packages/design-system/src/components/radio-group.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-form-controls
|
|
9
|
+
categoryFromBarrel: web-app-form-controls
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: RadioGroup
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<Omit<RadioGroupProps & RefAttributes<HTMLDivElement>, \"ref\"> & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: RadioGroupItem
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<RadioGroupItemProps & RefAttributes<HTMLButtonElement>>"
|
|
19
|
+
- name: RadioGroupItemProps
|
|
20
|
+
kind: type
|
|
21
|
+
primaryExport: RadioGroup
|
|
22
|
+
subcomponents:
|
|
23
|
+
- RadioGroupItem
|
|
24
|
+
props:
|
|
25
|
+
RadioGroupItem:
|
|
26
|
+
- name: size
|
|
27
|
+
type: "\"base\" | \"lg\" | \"sm\""
|
|
28
|
+
required: false
|
|
29
|
+
declaredIn: self
|
|
30
|
+
variantKey: true
|
|
31
|
+
extendsProps: []
|
|
32
|
+
variants:
|
|
33
|
+
size:
|
|
34
|
+
kind: enum
|
|
35
|
+
options:
|
|
36
|
+
- sm
|
|
37
|
+
- base
|
|
38
|
+
- lg
|
|
39
|
+
default: base
|
|
40
|
+
on: RadioGroup
|
|
41
|
+
variantSource: cva
|
|
42
|
+
compoundVariants: []
|
|
43
|
+
sizeMaps:
|
|
44
|
+
- INDICATOR_SIZE
|
|
45
|
+
dataSlots: []
|
|
46
|
+
dependsOn:
|
|
47
|
+
internal: []
|
|
48
|
+
lib:
|
|
49
|
+
- cn
|
|
50
|
+
hooks: []
|
|
51
|
+
external:
|
|
52
|
+
- "@radix-ui/react-radio-group"
|
|
53
|
+
- class-variance-authority
|
|
54
|
+
- lucide-react
|
|
55
|
+
- react
|
|
56
|
+
contexts: []
|
|
57
|
+
stories:
|
|
58
|
+
- exportName: Default
|
|
59
|
+
id: components-radiogroup--default
|
|
60
|
+
storybookTitle: Components/RadioGroup
|
|
61
|
+
docsId: components-radiogroup--documentation
|
|
62
|
+
argTypeOptions: {}
|
|
63
|
+
resolvedCleanly: true
|
|
64
|
+
contractHash: fba286141750
|
|
65
|
+
factsHash: f99370fdd642
|
|
66
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
67
|
+
status: stable
|
|
68
|
+
summary: "A set of mutually-exclusive radio buttons, built on Radix RadioGroup."
|
|
69
|
+
useWhen:
|
|
70
|
+
- "a compact list of mutually-exclusive options, each paired with its own visible label"
|
|
71
|
+
useInstead:
|
|
72
|
+
- id: radio-card
|
|
73
|
+
when: "the options deserve more visual weight than a plain dot and label row"
|
|
74
|
+
- id: segmented-control
|
|
75
|
+
when: "the options read better as a single connected control with a sliding indicator, not a stacked list"
|
|
76
|
+
related:
|
|
77
|
+
- radio-card
|
|
78
|
+
- segmented-control
|
|
79
|
+
a11y:
|
|
80
|
+
notes:
|
|
81
|
+
- "RadioGroupItem has no built-in label - pair each one with a real Label pointing at a matching id, the same pattern Checkbox uses."
|
|
82
|
+
keyboard:
|
|
83
|
+
- "Native Radix radio-group keyboard behavior: arrow keys move selection between items in the group, Tab enters or exits the group once."
|
|
84
|
+
radixHandles: true
|
|
85
|
+
pitfalls:
|
|
86
|
+
- "RadioGroup renders no visible layout beyond a vertical grid gap - laying out each RadioGroupItem next to its Label (each in its own row) is left entirely to the consumer, unlike RadioCard, which bundles the label into the card."
|
|
87
|
+
- "size lives on RadioGroupItem, not RadioGroup - setting it once on the group has no effect; each item needs its own size prop for a consistent look."
|
|
88
|
+
- "value/defaultValue/onValueChange on RadioGroup, and value/id on RadioGroupItem, are all real Radix props, but the extractor did not resolve them into derived.props/extendsProps for this file (a bare pass-through Root plus inline generics) - the machine-checked canonicalSnippet below is intentionally minimal because of this; see the fuller example in ## Usage."
|
|
89
|
+
canonicalSnippet: |
|
|
90
|
+
import { RadioGroup, RadioGroupItem } from "@adres/mgda-ui"
|
|
91
|
+
|
|
92
|
+
<RadioGroup>
|
|
93
|
+
<RadioGroupItem size="base" />
|
|
94
|
+
</RadioGroup>
|
|
95
|
+
reviewedAt: 2026-08-31
|
|
96
|
+
reviewedAgainstContractHash: fba286141750
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Usage
|
|
100
|
+
|
|
101
|
+
`RadioGroup` is a set of mutually-exclusive options, each item paired with
|
|
102
|
+
its own visible label - reach for `RadioCard` instead when the options
|
|
103
|
+
deserve more visual weight, or `SegmentedControl` when they read better as
|
|
104
|
+
one connected control with a sliding indicator rather than a stacked list.
|
|
105
|
+
|
|
106
|
+
`value`/`defaultValue`/`onValueChange` on `RadioGroup`, and `value`/`id` on
|
|
107
|
+
each `RadioGroupItem`, are all real Radix props - they just cannot appear in
|
|
108
|
+
this file's machine-checked `canonicalSnippet` above (see the pitfall on
|
|
109
|
+
why). The real, recommended usage pairs each item with a `Label`:
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { Label, RadioGroup, RadioGroupItem } from "@adres/mgda-ui"
|
|
113
|
+
|
|
114
|
+
<RadioGroup defaultValue="comfortable">
|
|
115
|
+
<div className="ax:flex ax:items-center ax:gap-sm">
|
|
116
|
+
<RadioGroupItem value="default" id="r1" />
|
|
117
|
+
<Label htmlFor="r1">Default</Label>
|
|
118
|
+
</div>
|
|
119
|
+
<div className="ax:flex ax:items-center ax:gap-sm">
|
|
120
|
+
<RadioGroupItem value="comfortable" id="r2" />
|
|
121
|
+
<Label htmlFor="r2">Comfortable</Label>
|
|
122
|
+
</div>
|
|
123
|
+
</RadioGroup>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`RadioGroup` itself only renders a vertical gap - laying out each item next
|
|
127
|
+
to its label, as above, is left to the consumer, unlike `RadioCard`, which
|
|
128
|
+
bundles the label into the card itself.
|
|
129
|
+
|
|
130
|
+
## Anatomy
|
|
131
|
+
|
|
132
|
+
| Part | Role |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| `RadioGroup` | Root. Holds the selected value. A thin wrapper around Radix `Root` that adds only a vertical grid gap. |
|
|
135
|
+
| `RadioGroupItem` | One selectable dot. `size` scales it; has no label of its own. |
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: reasoning
|
|
6
|
+
sourceFile: packages/design-system/src/components/reasoning.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-ai
|
|
9
|
+
categoryFromBarrel: web-app-ai
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: Reasoning
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<ReasoningProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: ReasoningContent
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<ReasoningContentProps & RefAttributes<HTMLDivElement>>"
|
|
19
|
+
- name: ReasoningContentProps
|
|
20
|
+
kind: type
|
|
21
|
+
- name: ReasoningProps
|
|
22
|
+
kind: type
|
|
23
|
+
- name: ReasoningTrigger
|
|
24
|
+
kind: component
|
|
25
|
+
typeText: "ForwardRefExoticComponent<ReasoningTriggerProps & RefAttributes<HTMLButtonElement>>"
|
|
26
|
+
- name: ReasoningTriggerProps
|
|
27
|
+
kind: type
|
|
28
|
+
primaryExport: Reasoning
|
|
29
|
+
subcomponents:
|
|
30
|
+
- ReasoningContent
|
|
31
|
+
- ReasoningTrigger
|
|
32
|
+
props:
|
|
33
|
+
Reasoning:
|
|
34
|
+
- name: defaultOpen
|
|
35
|
+
type: boolean
|
|
36
|
+
required: false
|
|
37
|
+
declaredIn: self
|
|
38
|
+
- name: onOpenChange
|
|
39
|
+
type: "((open: boolean) => void)"
|
|
40
|
+
required: false
|
|
41
|
+
declaredIn: self
|
|
42
|
+
- name: open
|
|
43
|
+
type: boolean
|
|
44
|
+
required: false
|
|
45
|
+
declaredIn: self
|
|
46
|
+
- name: streaming
|
|
47
|
+
type: boolean
|
|
48
|
+
required: false
|
|
49
|
+
declaredIn: self
|
|
50
|
+
doc: "True while the model is still reasoning: the panel opens, then closes when it turns false."
|
|
51
|
+
ReasoningContent:
|
|
52
|
+
- name: contentClassName
|
|
53
|
+
type: string
|
|
54
|
+
required: false
|
|
55
|
+
declaredIn: self
|
|
56
|
+
doc: "Extra classes for the inner text block, inside the animated wrapper."
|
|
57
|
+
extendsProps:
|
|
58
|
+
- "React.HTMLAttributes<HTMLDivElement>"
|
|
59
|
+
variants: {}
|
|
60
|
+
variantSource: none
|
|
61
|
+
compoundVariants: []
|
|
62
|
+
sizeMaps: []
|
|
63
|
+
dataSlots:
|
|
64
|
+
- reasoning
|
|
65
|
+
- reasoning-content
|
|
66
|
+
dependsOn:
|
|
67
|
+
internal:
|
|
68
|
+
- shimmer-text
|
|
69
|
+
lib:
|
|
70
|
+
- cn
|
|
71
|
+
hooks: []
|
|
72
|
+
external:
|
|
73
|
+
- lucide-react
|
|
74
|
+
- react
|
|
75
|
+
contexts:
|
|
76
|
+
- name: ReasoningContext
|
|
77
|
+
type: ReasoningContextValue
|
|
78
|
+
default: null
|
|
79
|
+
stories:
|
|
80
|
+
- exportName: Default
|
|
81
|
+
id: components-reasoning--default
|
|
82
|
+
- exportName: Streaming
|
|
83
|
+
id: components-reasoning--streaming
|
|
84
|
+
storybookTitle: Components/Reasoning
|
|
85
|
+
docsId: components-reasoning--documentation
|
|
86
|
+
argTypeOptions: {}
|
|
87
|
+
resolvedCleanly: true
|
|
88
|
+
contractHash: aa42ec0be8b4
|
|
89
|
+
factsHash: "0d9818571780"
|
|
90
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
91
|
+
status: beta
|
|
92
|
+
summary: "The model's thinking behind an answer in a collapsible panel that opens while it streams and folds away once the answer is ready."
|
|
93
|
+
useWhen:
|
|
94
|
+
- "a reasoning model streams its thinking before the answer and people may want to read it"
|
|
95
|
+
- "a finished answer should keep its reasoning available but out of the way"
|
|
96
|
+
useInstead:
|
|
97
|
+
- id: chain-of-thought
|
|
98
|
+
when: "the reasoning is a set of discrete steps, each with its own detail"
|
|
99
|
+
- id: thinking-steps
|
|
100
|
+
when: "only progress matters: a running summary over named steps"
|
|
101
|
+
related:
|
|
102
|
+
- chat-message
|
|
103
|
+
- chain-of-thought
|
|
104
|
+
- thinking-steps
|
|
105
|
+
a11y:
|
|
106
|
+
notes:
|
|
107
|
+
- "The trigger is a button with aria-expanded and aria-controls, so the panel toggles with Enter or Space."
|
|
108
|
+
- "Closed content stays in the DOM for the height animation but is inert and aria-hidden, so it cannot be focused or read."
|
|
109
|
+
- "The shimmer while streaming is decorative and stops under reduced motion; the label text says what is happening."
|
|
110
|
+
radixHandles: false
|
|
111
|
+
pitfalls:
|
|
112
|
+
- "The panel follows streaming edges: it opens when streaming turns true and closes when it turns false. A manual toggle mid-stream holds until the next edge."
|
|
113
|
+
- "A controlled open always wins; handle streaming yourself when you pass open."
|
|
114
|
+
- "There is no built-in markdown; render rich reasoning yourself and pass it as children."
|
|
115
|
+
- "Change the trigger label with the state, such as \"Thinking\" while streaming and \"Thought for 4 seconds\" after."
|
|
116
|
+
canonicalSnippet: |
|
|
117
|
+
import { Reasoning, ReasoningTrigger, ReasoningContent } from "@adres/mgda-ui"
|
|
118
|
+
|
|
119
|
+
<Reasoning streaming={thinking}>
|
|
120
|
+
<ReasoningTrigger>{thinking ? "Thinking" : "Show reasoning"}</ReasoningTrigger>
|
|
121
|
+
<ReasoningContent>{reasoningText}</ReasoningContent>
|
|
122
|
+
</Reasoning>
|
|
123
|
+
reviewedAt: 2026-10-06
|
|
124
|
+
reviewedAgainstContractHash: aa42ec0be8b4
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Usage
|
|
128
|
+
|
|
129
|
+
`Reasoning` holds the open state. `ReasoningTrigger` is the muted label with
|
|
130
|
+
a chevron that toggles it, and `ReasoningContent` is the reasoning text beside
|
|
131
|
+
a thin rule, growing and shrinking with a short height animation.
|
|
132
|
+
|
|
133
|
+
Pass `streaming` while the model is reasoning: the panel opens and the label
|
|
134
|
+
shimmers, then the panel folds away when `streaming` turns false. Use
|
|
135
|
+
`defaultOpen` to start open without streaming, or control it with `open` and
|
|
136
|
+
`onOpenChange`. `contentClassName` styles the inner text block.
|
|
137
|
+
|
|
138
|
+
## Anatomy
|
|
139
|
+
|
|
140
|
+
- `Reasoning` - holds the open and streaming state.
|
|
141
|
+
- `ReasoningTrigger` - muted label and chevron; shimmers while streaming.
|
|
142
|
+
- `ReasoningContent` - the reasoning text beside a rule; inert while closed.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: search
|
|
6
|
+
sourceFile: packages/design-system/src/components/search.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-core-primitives
|
|
9
|
+
categoryFromBarrel: web-app-core-primitives
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: Search
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<SearchProps & RefAttributes<HTMLInputElement>>"
|
|
16
|
+
- name: SearchProps
|
|
17
|
+
kind: type
|
|
18
|
+
primaryExport: Search
|
|
19
|
+
subcomponents: []
|
|
20
|
+
props:
|
|
21
|
+
Search:
|
|
22
|
+
- name: className
|
|
23
|
+
type: string
|
|
24
|
+
required: false
|
|
25
|
+
declaredIn: self
|
|
26
|
+
doc: "Optional className applied to the outer `TextFieldRoot`. Useful for setting width (e.g. `\"ax:w-65\"`) or alignment helpers (`\"ax:ms-auto\"`)."
|
|
27
|
+
- name: clearable
|
|
28
|
+
type: boolean
|
|
29
|
+
required: false
|
|
30
|
+
declaredIn: self
|
|
31
|
+
doc: "Show a trailing clear button when the input has a value. Defaults to `true` for controlled inputs (when `value` is set). Pass `false` to suppress entirely. When clicked, the input is cleared by calling either: • `onClear` (if provided), or • `onChange` with a synthetic event whose `target.value` is `\"\"`. The latter keeps controlled callers working without an extra prop."
|
|
32
|
+
- name: invalid
|
|
33
|
+
type: boolean
|
|
34
|
+
required: false
|
|
35
|
+
declaredIn: self
|
|
36
|
+
doc: "Marks the input as invalid (red border + ring)."
|
|
37
|
+
- name: onClear
|
|
38
|
+
type: "(() => void)"
|
|
39
|
+
required: false
|
|
40
|
+
declaredIn: self
|
|
41
|
+
doc: "Called when the user clicks the clear button. Takes precedence over the default behaviour of dispatching an empty-string change event."
|
|
42
|
+
- name: size
|
|
43
|
+
type: InputSize
|
|
44
|
+
required: false
|
|
45
|
+
declaredIn: self
|
|
46
|
+
doc: "Visual density - passes through to the underlying `TextFieldRoot` / `Input`. Defaults to `md`."
|
|
47
|
+
extendsProps:
|
|
48
|
+
- "Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\">"
|
|
49
|
+
variants:
|
|
50
|
+
size:
|
|
51
|
+
kind: enum
|
|
52
|
+
options:
|
|
53
|
+
- sm
|
|
54
|
+
- md
|
|
55
|
+
- lg
|
|
56
|
+
default: md
|
|
57
|
+
on: Search
|
|
58
|
+
variantSource: prop-union
|
|
59
|
+
compoundVariants: []
|
|
60
|
+
sizeMaps: []
|
|
61
|
+
dataSlots: []
|
|
62
|
+
dependsOn:
|
|
63
|
+
internal:
|
|
64
|
+
- input
|
|
65
|
+
lib:
|
|
66
|
+
- cn
|
|
67
|
+
hooks: []
|
|
68
|
+
external:
|
|
69
|
+
- lucide-react
|
|
70
|
+
- react
|
|
71
|
+
contexts: []
|
|
72
|
+
stories:
|
|
73
|
+
- exportName: Default
|
|
74
|
+
id: components-search--default
|
|
75
|
+
storybookTitle: Components/Search
|
|
76
|
+
docsId: components-search--documentation
|
|
77
|
+
argTypeOptions: {}
|
|
78
|
+
resolvedCleanly: true
|
|
79
|
+
contractHash: "340492e4cb3b"
|
|
80
|
+
factsHash: "061ec021a274"
|
|
81
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
82
|
+
status: stable
|
|
83
|
+
summary: "A styled search input: leading magnifying-glass icon and an optional trailing clear button, built on TextFieldRoot and Input."
|
|
84
|
+
useWhen:
|
|
85
|
+
- "the field is a search or filter box, not a general text field"
|
|
86
|
+
useInstead:
|
|
87
|
+
- id: input
|
|
88
|
+
when: "the field is a plain text field with no search icon or clear affordance"
|
|
89
|
+
- id: combobox
|
|
90
|
+
when: "typing should show a list of suggestions to pick from"
|
|
91
|
+
related:
|
|
92
|
+
- input
|
|
93
|
+
- combobox
|
|
94
|
+
a11y:
|
|
95
|
+
notes:
|
|
96
|
+
- "aria-label defaults to \"Search\" since the field usually has no visible Label - override it when the search scopes a specific list, e.g. \"Search students\"."
|
|
97
|
+
- "The clear button always carries its own aria-label (\"Clear search\") so it reads correctly even though it has no visible text."
|
|
98
|
+
keyboard:
|
|
99
|
+
- "Native input semantics; the clear button is a real button, so it is reachable and activates with Enter/Space."
|
|
100
|
+
radixHandles: false
|
|
101
|
+
pitfalls:
|
|
102
|
+
- "clearable defaults to showing the button only in controlled mode (a value prop is set) - an uncontrolled Search using only defaultValue never shows the clear button unless clearable is passed explicitly."
|
|
103
|
+
- "The clear button's fallback behavior mutates the native input value and dispatches a synthetic input event to keep a controlled onChange in sync - if neither onClear nor onChange is provided, clicking clear does nothing but refocus the field."
|
|
104
|
+
canonicalSnippet: |
|
|
105
|
+
import { Search } from "@adres/mgda-ui"
|
|
106
|
+
|
|
107
|
+
const searchLabel = "Search residents"
|
|
108
|
+
|
|
109
|
+
<Search
|
|
110
|
+
value={query}
|
|
111
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
112
|
+
onClear={() => setQuery("")}
|
|
113
|
+
placeholder={searchLabel}
|
|
114
|
+
aria-label={searchLabel}
|
|
115
|
+
/>
|
|
116
|
+
reviewedAt: 2026-09-30
|
|
117
|
+
reviewedAgainstContractHash: "340492e4cb3b"
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Usage
|
|
121
|
+
|
|
122
|
+
`Search` is the shipped, correct way to build a search field - reach for it
|
|
123
|
+
instead of assembling `TextFieldRoot` + `TextFieldSlot` + `Input` by hand any
|
|
124
|
+
time the field is a search box. It always renders the leading magnifying-glass
|
|
125
|
+
icon and `type="search"`.
|
|
126
|
+
|
|
127
|
+
Pass `value` + `onChange` for a controlled search box, the common case - the
|
|
128
|
+
clear button appears automatically once there is a value. Pass `onClear` when
|
|
129
|
+
clearing needs to do more than reset the input (resetting a debounced query or
|
|
130
|
+
a page number too); otherwise the built-in fallback dispatches a synthetic
|
|
131
|
+
change event that keeps a controlled caller's state in sync without it.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: section-nav
|
|
6
|
+
sourceFile: packages/design-system/src/components/section-nav.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-layout-navigation
|
|
9
|
+
categoryFromBarrel: web-app-layout-navigation
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: SectionNav
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<SectionNavProps & RefAttributes<HTMLElement>>"
|
|
16
|
+
- name: SectionNavItem
|
|
17
|
+
kind: type
|
|
18
|
+
- name: SectionNavProps
|
|
19
|
+
kind: type
|
|
20
|
+
primaryExport: SectionNav
|
|
21
|
+
subcomponents: []
|
|
22
|
+
props:
|
|
23
|
+
SectionNav:
|
|
24
|
+
- name: activationRatio
|
|
25
|
+
type: number
|
|
26
|
+
required: false
|
|
27
|
+
declaredIn: self
|
|
28
|
+
doc: "How far down the scroll root (0-1) a section's top must pass to count as the current one. Default `0.24`."
|
|
29
|
+
- name: items
|
|
30
|
+
type: "SectionNavItem[]"
|
|
31
|
+
required: true
|
|
32
|
+
declaredIn: self
|
|
33
|
+
doc: "Sections to list, in page order. Each `id` must match an element on the page."
|
|
34
|
+
- name: layout
|
|
35
|
+
type: "\"responsive\" | \"vertical\""
|
|
36
|
+
required: false
|
|
37
|
+
declaredIn: self
|
|
38
|
+
doc: "`vertical` (default) is a stacked list at every width. `responsive` runs as a horizontally scrolling row below `xl` and a stacked list from `xl` up, hiding the title in the row."
|
|
39
|
+
- name: onActiveChange
|
|
40
|
+
type: "((id: string) => void)"
|
|
41
|
+
required: false
|
|
42
|
+
declaredIn: self
|
|
43
|
+
doc: "Fires when the current section changes, from scrolling or from a click."
|
|
44
|
+
- name: scrollRoot
|
|
45
|
+
type: "HTMLElement | string"
|
|
46
|
+
required: false
|
|
47
|
+
declaredIn: self
|
|
48
|
+
doc: "The scrolling container the sections live in: a CSS selector, an element, or `null` (default) for the window."
|
|
49
|
+
- name: title
|
|
50
|
+
type: ReactNode
|
|
51
|
+
required: false
|
|
52
|
+
declaredIn: self
|
|
53
|
+
doc: "Eyebrow title above the list. Pass `null` to hide it."
|
|
54
|
+
extendsProps:
|
|
55
|
+
- "Omit<React.HTMLAttributes<HTMLElement>, \"title\" | \"onSelect\">"
|
|
56
|
+
variants:
|
|
57
|
+
layout:
|
|
58
|
+
kind: enum
|
|
59
|
+
options:
|
|
60
|
+
- vertical
|
|
61
|
+
- responsive
|
|
62
|
+
default: vertical
|
|
63
|
+
on: SectionNav
|
|
64
|
+
variantSource: prop-union
|
|
65
|
+
compoundVariants: []
|
|
66
|
+
sizeMaps: []
|
|
67
|
+
dataSlots: []
|
|
68
|
+
dependsOn:
|
|
69
|
+
internal:
|
|
70
|
+
- list-nav
|
|
71
|
+
lib:
|
|
72
|
+
- cn
|
|
73
|
+
hooks: []
|
|
74
|
+
external:
|
|
75
|
+
- react
|
|
76
|
+
contexts: []
|
|
77
|
+
stories:
|
|
78
|
+
- exportName: Default
|
|
79
|
+
id: components-sectionnav--default
|
|
80
|
+
- exportName: InScrollContainer
|
|
81
|
+
id: components-sectionnav--in-scroll-container
|
|
82
|
+
- exportName: Responsive
|
|
83
|
+
id: components-sectionnav--responsive
|
|
84
|
+
storybookTitle: Components/SectionNav
|
|
85
|
+
docsId: components-sectionnav--documentation
|
|
86
|
+
argTypeOptions: {}
|
|
87
|
+
resolvedCleanly: true
|
|
88
|
+
contractHash: "9a3f2097e4ee"
|
|
89
|
+
factsHash: ead2951fb1f5
|
|
90
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
91
|
+
status: beta
|
|
92
|
+
summary: "An in-page \"Jump to\" menu that lists a page's sections as anchor links and highlights the one currently in view."
|
|
93
|
+
useWhen:
|
|
94
|
+
- "a long single page (docs, a policy, a listing detail) has named sections the reader wants to jump between"
|
|
95
|
+
- "the side or top nav should follow the reader's position as they scroll"
|
|
96
|
+
useInstead:
|
|
97
|
+
- id: list-nav
|
|
98
|
+
when: "the items go to other pages or trigger actions rather than sections of the current page"
|
|
99
|
+
- id: tabs
|
|
100
|
+
when: "only one section should be visible at a time instead of one long scrolling page"
|
|
101
|
+
- id: sidebar
|
|
102
|
+
when: "it is the app's main cross-page navigation"
|
|
103
|
+
related:
|
|
104
|
+
- list-nav
|
|
105
|
+
- tabs
|
|
106
|
+
composesWith:
|
|
107
|
+
- list-nav
|
|
108
|
+
tokens:
|
|
109
|
+
- "--primary-foreground"
|
|
110
|
+
- "--border"
|
|
111
|
+
a11y:
|
|
112
|
+
notes:
|
|
113
|
+
- "Renders a nav landmark labelled \"Page sections\" by default - pass aria-label when a page has more than one SectionNav or another nav with the same name."
|
|
114
|
+
- "The current section is exposed through ListNavItem's active state (aria-current=\"page\"), updated on scroll and on click."
|
|
115
|
+
- "Every item is a real <a href=\"#id\">, so links work and are announced as links without JavaScript."
|
|
116
|
+
keyboard:
|
|
117
|
+
- "Native anchor semantics - Tab moves between items, Enter jumps to the section."
|
|
118
|
+
radixHandles: false
|
|
119
|
+
pitfalls:
|
|
120
|
+
- "Each item id must match an element id on the page - a missing id is skipped silently and that item can never become active."
|
|
121
|
+
- "When the content scrolls inside a container rather than the window, pass scrollRoot (a selector or element); otherwise scroll-spy listens to the window and never updates."
|
|
122
|
+
- "A string scrollRoot is resolved once in an effect - if the container mounts later than SectionNav, scroll-spy does not attach. Pass the element itself in that case."
|
|
123
|
+
- "Define items outside render or memoize them - a new array every render re-attaches the scroll listener each time."
|
|
124
|
+
canonicalSnippet: |
|
|
125
|
+
import { SectionNav } from "@adres/mgda-ui"
|
|
126
|
+
|
|
127
|
+
const items = [
|
|
128
|
+
{ id: "overview", label: "Overview" },
|
|
129
|
+
{ id: "eligibility", label: "Eligibility" },
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
<div className="ax:flex ax:gap-xl">
|
|
133
|
+
<div className="ax:w-56 ax:shrink-0">
|
|
134
|
+
<div className="ax:sticky ax:top-md">
|
|
135
|
+
<SectionNav items={items} />
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
<div className="ax:flex-1">
|
|
139
|
+
<section id="overview">Overview</section>
|
|
140
|
+
<section id="eligibility">Eligibility</section>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
reviewedAt: 2026-10-26
|
|
144
|
+
reviewedAgainstContractHash: "9a3f2097e4ee"
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Usage
|
|
148
|
+
|
|
149
|
+
`SectionNav` is a table of contents for the current page. Give it the page's
|
|
150
|
+
sections in order, each with the `id` of its element, and it renders a `ListNav`
|
|
151
|
+
of anchor links. As the reader scrolls, the section whose top has passed
|
|
152
|
+
`activationRatio` of the way down the viewport (or `scrollRoot`) is marked
|
|
153
|
+
active with a primary start border and text.
|
|
154
|
+
|
|
155
|
+
Place it in a sticky column beside the content for desktop reading. Use
|
|
156
|
+
`layout="responsive"` when the same nav must also work on narrow screens: below
|
|
157
|
+
`xl` it becomes a horizontally scrolling row with the title hidden, and from
|
|
158
|
+
`xl` up it stacks as a list.
|
|
159
|
+
|
|
160
|
+
`onActiveChange` reports the current section, for syncing other UI such as a
|
|
161
|
+
progress indicator. The active state itself is managed internally and cannot be
|
|
162
|
+
controlled from outside.
|