@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,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: step-indicator
|
|
6
|
+
sourceFile: packages/design-system/src/components/step-indicator.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-patterns
|
|
9
|
+
categoryFromBarrel: web-app-patterns
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: StepIndicator
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<StepIndicatorProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: StepIndicatorOrientation
|
|
17
|
+
kind: type
|
|
18
|
+
- name: StepIndicatorProps
|
|
19
|
+
kind: type
|
|
20
|
+
- name: StepIndicatorSize
|
|
21
|
+
kind: type
|
|
22
|
+
- name: StepIndicatorStep
|
|
23
|
+
kind: type
|
|
24
|
+
primaryExport: StepIndicator
|
|
25
|
+
subcomponents: []
|
|
26
|
+
props:
|
|
27
|
+
StepIndicator:
|
|
28
|
+
- name: currentStep
|
|
29
|
+
type: number
|
|
30
|
+
required: true
|
|
31
|
+
declaredIn: self
|
|
32
|
+
doc: "Zero-based index of the active step. Steps before it render as done; the step at this index renders as active; later steps stay muted."
|
|
33
|
+
- name: onStepClick
|
|
34
|
+
type: "((index: number) => void)"
|
|
35
|
+
required: false
|
|
36
|
+
declaredIn: self
|
|
37
|
+
doc: "When provided, the indicator becomes interactive: done and active steps render as buttons that call back with the step index. Upcoming steps remain inert (users can't jump ahead)."
|
|
38
|
+
- name: orientation
|
|
39
|
+
type: StepIndicatorOrientation
|
|
40
|
+
required: false
|
|
41
|
+
declaredIn: self
|
|
42
|
+
doc: "Layout direction. `horizontal` (default) is best for desktop wizards; `vertical` is better on mobile or in side panels."
|
|
43
|
+
- name: size
|
|
44
|
+
type: StepIndicatorSize
|
|
45
|
+
required: false
|
|
46
|
+
declaredIn: self
|
|
47
|
+
doc: "Visual density."
|
|
48
|
+
- name: steps
|
|
49
|
+
type: "StepIndicatorStep[]"
|
|
50
|
+
required: true
|
|
51
|
+
declaredIn: self
|
|
52
|
+
extendsProps:
|
|
53
|
+
- "React.HTMLAttributes<HTMLDivElement>"
|
|
54
|
+
variants:
|
|
55
|
+
size:
|
|
56
|
+
kind: enum
|
|
57
|
+
options:
|
|
58
|
+
- sm
|
|
59
|
+
- md
|
|
60
|
+
- lg
|
|
61
|
+
default: md
|
|
62
|
+
on: StepIndicator
|
|
63
|
+
orientation:
|
|
64
|
+
kind: enum
|
|
65
|
+
options:
|
|
66
|
+
- horizontal
|
|
67
|
+
- vertical
|
|
68
|
+
default: horizontal
|
|
69
|
+
on: StepIndicator
|
|
70
|
+
variantSource: prop-union
|
|
71
|
+
compoundVariants: []
|
|
72
|
+
sizeMaps:
|
|
73
|
+
- CIRCLE_H
|
|
74
|
+
- CIRCLE_SIZE
|
|
75
|
+
- ICON_CLASS
|
|
76
|
+
- LABEL_CLASS
|
|
77
|
+
- NUMBER_CLASS
|
|
78
|
+
dataSlots: []
|
|
79
|
+
dependsOn:
|
|
80
|
+
internal: []
|
|
81
|
+
lib:
|
|
82
|
+
- cn
|
|
83
|
+
hooks: []
|
|
84
|
+
external:
|
|
85
|
+
- lucide-react
|
|
86
|
+
- react
|
|
87
|
+
contexts: []
|
|
88
|
+
stories:
|
|
89
|
+
- exportName: Default
|
|
90
|
+
id: components-stepindicator--default
|
|
91
|
+
storybookTitle: Components/StepIndicator
|
|
92
|
+
docsId: components-stepindicator--documentation
|
|
93
|
+
argTypeOptions: {}
|
|
94
|
+
resolvedCleanly: true
|
|
95
|
+
contractHash: a0e45cc52f9d
|
|
96
|
+
factsHash: "72b15c96378f"
|
|
97
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
98
|
+
status: stable
|
|
99
|
+
summary: "A multi-step progress indicator (horizontal wizard or vertical timeline) with done/active/upcoming/error states, optionally clickable to navigate backward."
|
|
100
|
+
useWhen:
|
|
101
|
+
- "showing progress through a fixed sequence of discrete steps - a multi-page form, an onboarding wizard, an order-status timeline"
|
|
102
|
+
useInstead:
|
|
103
|
+
- id: progress
|
|
104
|
+
when: "progress is a continuous percentage or value, not a fixed sequence of named steps"
|
|
105
|
+
- id: countdown-pill
|
|
106
|
+
when: "showing time remaining until one event, not discrete steps in a process"
|
|
107
|
+
related:
|
|
108
|
+
- progress
|
|
109
|
+
- countdown-pill
|
|
110
|
+
a11y:
|
|
111
|
+
notes:
|
|
112
|
+
- "aria-current=\"step\" marks the active step on both interactive and static renders - assistive tech can identify the current position regardless of onStepClick."
|
|
113
|
+
- "onStepClick makes done and active steps real button elements automatically; upcoming steps stay non-interactive divs even when onStepClick is provided - users cannot jump ahead, matching the visual cue that upcoming steps are muted."
|
|
114
|
+
keyboard:
|
|
115
|
+
- "When interactive, clickable steps are native buttons, so Tab/Enter/Space work without extra wiring - no custom keyboard handling is needed."
|
|
116
|
+
radixHandles: false
|
|
117
|
+
pitfalls:
|
|
118
|
+
- "currentStep is the only source of done/active/upcoming state - steps do not track their own completion; passing an out-of-range currentStep (negative, or >= steps.length) does not throw, it just renders every step as either done or upcoming with no active step highlighted."
|
|
119
|
+
- "status: \"error\" on a step overrides its computed done/active/upcoming state entirely, and takes over the connector color on both sides of that step - marking a past step as error still shows it distinct from a normal done step, not just tinted."
|
|
120
|
+
- "onStepClick only ever fires for steps at or before currentStep - passing it does not let users skip ahead to upcoming steps, by design; there is no prop to relax that restriction."
|
|
121
|
+
- "orientation=\"vertical\" allows step.label to be a full ReactNode (e.g. a details block), but orientation=\"horizontal\" visually assumes a short, non-wrapping label - a long or rich label in horizontal mode overflows rather than wraps."
|
|
122
|
+
canonicalSnippet: |
|
|
123
|
+
import { StepIndicator } from "@adres/mgda-ui"
|
|
124
|
+
|
|
125
|
+
<StepIndicator
|
|
126
|
+
currentStep={1}
|
|
127
|
+
steps={[
|
|
128
|
+
{ label: "Account" },
|
|
129
|
+
{ label: "Profile" },
|
|
130
|
+
{ label: "Confirm" },
|
|
131
|
+
]}
|
|
132
|
+
/>
|
|
133
|
+
reviewedAt: 2026-09-01
|
|
134
|
+
reviewedAgainstContractHash: a0e45cc52f9d
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Usage
|
|
138
|
+
|
|
139
|
+
`StepIndicator` shows progress through a fixed sequence of discrete, named
|
|
140
|
+
steps - a multi-page form, an onboarding wizard, an order-status timeline.
|
|
141
|
+
Reach for `Progress` instead when progress is a continuous percentage, not a
|
|
142
|
+
set of named steps, and `CountdownPill` when showing time remaining until
|
|
143
|
+
one event rather than discrete steps in a process.
|
|
144
|
+
|
|
145
|
+
`currentStep` (zero-based) is the only source of truth for step state -
|
|
146
|
+
steps before it render `done`, the step at that index renders `active`,
|
|
147
|
+
later steps stay `upcoming`. A per-step `status: "error"` overrides that
|
|
148
|
+
computed state regardless of position.
|
|
149
|
+
|
|
150
|
+
Pass `onStepClick` to make the indicator navigable: only `done` and `active`
|
|
151
|
+
steps become clickable, matching the natural rule that users can revisit a
|
|
152
|
+
completed step or the current one, but cannot skip ahead to an `upcoming`
|
|
153
|
+
step.
|
|
154
|
+
|
|
155
|
+
`orientation="horizontal"` (default) suits desktop wizards with short
|
|
156
|
+
labels; `orientation="vertical"` suits mobile or side panels and allows a
|
|
157
|
+
richer `ReactNode` label per step, such as a details block.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: switch
|
|
6
|
+
sourceFile: packages/design-system/src/components/switch.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: uncategorized
|
|
9
|
+
categoryFromBarrel: null
|
|
10
|
+
barrelExported: false
|
|
11
|
+
importPath: "@adres/mgda-ui/components/switch"
|
|
12
|
+
exports:
|
|
13
|
+
- name: Switch
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<Omit<SwitchProps & RefAttributes<HTMLButtonElement>, \"ref\"> & RefAttributes<HTMLButtonElement>>"
|
|
16
|
+
primaryExport: Switch
|
|
17
|
+
subcomponents: []
|
|
18
|
+
props: {}
|
|
19
|
+
extendsProps: []
|
|
20
|
+
variants: {}
|
|
21
|
+
variantSource: none
|
|
22
|
+
compoundVariants: []
|
|
23
|
+
sizeMaps: []
|
|
24
|
+
dataSlots: []
|
|
25
|
+
dependsOn:
|
|
26
|
+
internal: []
|
|
27
|
+
lib:
|
|
28
|
+
- cn
|
|
29
|
+
hooks: []
|
|
30
|
+
external:
|
|
31
|
+
- "@radix-ui/react-switch"
|
|
32
|
+
- react
|
|
33
|
+
contexts: []
|
|
34
|
+
stories:
|
|
35
|
+
- exportName: Default
|
|
36
|
+
id: components-switch--default
|
|
37
|
+
- exportName: Checked
|
|
38
|
+
id: components-switch--checked
|
|
39
|
+
storybookTitle: Components/Switch
|
|
40
|
+
docsId: components-switch--documentation
|
|
41
|
+
argTypeOptions: {}
|
|
42
|
+
resolvedCleanly: true
|
|
43
|
+
contractHash: c5e06226b968
|
|
44
|
+
factsHash: "5a117fe889c2"
|
|
45
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
46
|
+
status: stable
|
|
47
|
+
summary: "An on/off toggle switch, built on Radix Switch, for a setting that takes effect immediately."
|
|
48
|
+
useWhen:
|
|
49
|
+
- "an immediate on/off setting - e.g. airplane mode, notifications enabled - that applies right away, not a form-bound selection to submit"
|
|
50
|
+
useInstead:
|
|
51
|
+
- id: checkbox
|
|
52
|
+
when: "the control is a form-bound boolean or tri-state selection, especially in a list, form, or table row"
|
|
53
|
+
- id: toggle
|
|
54
|
+
when: "the control needs to look like a pressable button rather than a physical switch"
|
|
55
|
+
related:
|
|
56
|
+
- checkbox
|
|
57
|
+
- toggle
|
|
58
|
+
a11y:
|
|
59
|
+
notes:
|
|
60
|
+
- "Switch has no built-in label - pair it with a Label (via htmlFor/id, as in the story) so the control has an accessible name."
|
|
61
|
+
keyboard:
|
|
62
|
+
- "Native Radix switch role - Space toggles it, and it takes part in tab order automatically."
|
|
63
|
+
radixHandles: true
|
|
64
|
+
pitfalls:
|
|
65
|
+
- "Switch is not exported from the package barrel (@adres/mgda-ui) - import it from the deep path @adres/mgda-ui/components/switch."
|
|
66
|
+
canonicalSnippet: |
|
|
67
|
+
import { Switch } from "@adres/mgda-ui/components/switch"
|
|
68
|
+
|
|
69
|
+
<Switch aria-label="Airplane mode" onCheckedChange={setEnabled} />
|
|
70
|
+
reviewedAt: 2026-09-01
|
|
71
|
+
reviewedAgainstContractHash: c5e06226b968
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
`Switch` is for an immediate on/off setting that takes effect right away -
|
|
77
|
+
airplane mode, a notifications toggle - as opposed to a value that gets
|
|
78
|
+
submitted with a form. Reach for `Checkbox` instead when the control is a
|
|
79
|
+
form-bound boolean or tri-state selection, especially in a list, form, or
|
|
80
|
+
table row.
|
|
81
|
+
|
|
82
|
+
`Switch` renders no label of its own - always give it an accessible name,
|
|
83
|
+
either via `aria-label` (as above) or by pairing it with a `Label` pointing at
|
|
84
|
+
the switch's `id` with `htmlFor`.
|
|
85
|
+
|
|
86
|
+
Unlike most components in this package, `Switch` is not re-exported from the
|
|
87
|
+
package barrel; import it from its deep path,
|
|
88
|
+
`@adres/mgda-ui/components/switch`.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: table
|
|
6
|
+
sourceFile: packages/design-system/src/components/table.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-data
|
|
9
|
+
categoryFromBarrel: web-app-data
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: Table
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<TableProps & RefAttributes<HTMLTableElement>>"
|
|
16
|
+
- name: TableBody
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & RefAttributes<HTMLTableSectionElement>>"
|
|
19
|
+
- name: TableCaption
|
|
20
|
+
kind: component
|
|
21
|
+
typeText: "ForwardRefExoticComponent<HTMLAttributes<HTMLTableCaptionElement> & RefAttributes<HTMLTableCaptionElement>>"
|
|
22
|
+
- name: TableCell
|
|
23
|
+
kind: component
|
|
24
|
+
typeText: "ForwardRefExoticComponent<TdHTMLAttributes<HTMLTableCellElement> & RefAttributes<HTMLTableCellElement>>"
|
|
25
|
+
- name: TableFooter
|
|
26
|
+
kind: component
|
|
27
|
+
typeText: "ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & RefAttributes<HTMLTableSectionElement>>"
|
|
28
|
+
- name: TableHead
|
|
29
|
+
kind: component
|
|
30
|
+
typeText: "ForwardRefExoticComponent<ThHTMLAttributes<HTMLTableCellElement> & RefAttributes<HTMLTableCellElement>>"
|
|
31
|
+
- name: TableHeader
|
|
32
|
+
kind: component
|
|
33
|
+
typeText: "ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & RefAttributes<HTMLTableSectionElement>>"
|
|
34
|
+
- name: TableProps
|
|
35
|
+
kind: type
|
|
36
|
+
- name: TableRow
|
|
37
|
+
kind: component
|
|
38
|
+
typeText: "ForwardRefExoticComponent<HTMLAttributes<HTMLTableRowElement> & RefAttributes<HTMLTableRowElement>>"
|
|
39
|
+
- name: TableSize
|
|
40
|
+
kind: type
|
|
41
|
+
- name: TableVariant
|
|
42
|
+
kind: type
|
|
43
|
+
primaryExport: Table
|
|
44
|
+
subcomponents:
|
|
45
|
+
- TableBody
|
|
46
|
+
- TableCaption
|
|
47
|
+
- TableCell
|
|
48
|
+
- TableFooter
|
|
49
|
+
- TableHead
|
|
50
|
+
- TableHeader
|
|
51
|
+
- TableRow
|
|
52
|
+
props:
|
|
53
|
+
Table:
|
|
54
|
+
- name: size
|
|
55
|
+
type: TableSize
|
|
56
|
+
required: false
|
|
57
|
+
declaredIn: self
|
|
58
|
+
- name: variant
|
|
59
|
+
type: TableVariant
|
|
60
|
+
required: false
|
|
61
|
+
declaredIn: self
|
|
62
|
+
extendsProps:
|
|
63
|
+
- "React.HTMLAttributes<HTMLTableElement>"
|
|
64
|
+
variants:
|
|
65
|
+
size:
|
|
66
|
+
kind: enum
|
|
67
|
+
options:
|
|
68
|
+
- sm
|
|
69
|
+
- md
|
|
70
|
+
- lg
|
|
71
|
+
default: md
|
|
72
|
+
on: Table
|
|
73
|
+
variant:
|
|
74
|
+
kind: enum
|
|
75
|
+
options:
|
|
76
|
+
- ghost
|
|
77
|
+
- surface
|
|
78
|
+
default: surface
|
|
79
|
+
on: Table
|
|
80
|
+
variantSource: prop-union
|
|
81
|
+
compoundVariants: []
|
|
82
|
+
sizeMaps:
|
|
83
|
+
- CELL_PADDING
|
|
84
|
+
- TEXT_SIZE
|
|
85
|
+
dataSlots: []
|
|
86
|
+
dependsOn:
|
|
87
|
+
internal: []
|
|
88
|
+
lib:
|
|
89
|
+
- cn
|
|
90
|
+
hooks: []
|
|
91
|
+
external:
|
|
92
|
+
- react
|
|
93
|
+
contexts:
|
|
94
|
+
- name: TableContext
|
|
95
|
+
type: TableContextValue
|
|
96
|
+
default: null
|
|
97
|
+
stories:
|
|
98
|
+
- exportName: Default
|
|
99
|
+
id: components-table--default
|
|
100
|
+
storybookTitle: Components/Table
|
|
101
|
+
docsId: components-table--documentation
|
|
102
|
+
argTypeOptions: {}
|
|
103
|
+
resolvedCleanly: true
|
|
104
|
+
contractHash: "954f019b29cd"
|
|
105
|
+
factsHash: d411faad10ae
|
|
106
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
107
|
+
status: stable
|
|
108
|
+
summary: "A hand-markup HTML table (thead/tbody/tfoot/tr/th/td) with density sizes and a bordered or ghost surface, for full control over table structure."
|
|
109
|
+
useWhen:
|
|
110
|
+
- "the table needs custom structure raw markup gives you - row spans, grouped headers, a footer row, or hand-placed cells - beyond a plain column-driven grid"
|
|
111
|
+
useInstead:
|
|
112
|
+
- id: data-table
|
|
113
|
+
when: "columns are defined in data and you want built-in client-side sorting without wiring the markup by hand"
|
|
114
|
+
- id: data-list
|
|
115
|
+
when: "showing label/value pairs for a single record, not multiple rows sharing the same columns"
|
|
116
|
+
- id: accordion
|
|
117
|
+
when: "the content is a list of expandable sections, not tabular rows and columns"
|
|
118
|
+
related:
|
|
119
|
+
- data-table
|
|
120
|
+
- data-list
|
|
121
|
+
- accordion
|
|
122
|
+
tokens:
|
|
123
|
+
- "--border"
|
|
124
|
+
- "--muted"
|
|
125
|
+
- "--card"
|
|
126
|
+
- "--background"
|
|
127
|
+
- "--primary-muted"
|
|
128
|
+
- "--foreground"
|
|
129
|
+
- "--muted-foreground"
|
|
130
|
+
a11y:
|
|
131
|
+
notes:
|
|
132
|
+
- "Renders real table/thead/tbody/tfoot/tr/th/td elements, so screen readers get native table navigation and header/cell association for free - no extra ARIA is needed for a straightforward table."
|
|
133
|
+
- "TableCaption renders a real caption element, the correct way to give a table an accessible name or description - prefer it over a heading placed above the table."
|
|
134
|
+
radixHandles: false
|
|
135
|
+
pitfalls:
|
|
136
|
+
- "TableBody, not TableRow, owns the row background, hover, and selected-state styling (data-state=\"selected\") - putting those classes on TableRow directly would also paint header rows, since TableHeader and TableRow share the same underlying element."
|
|
137
|
+
- "variant=\"surface\" (default) wraps the table in a bordered, rounded, scrollable container; variant=\"ghost\" drops that chrome entirely for a table meant to sit flush inside another surface, such as one already inside a Card."
|
|
138
|
+
- "size drives two separate maps (cell padding, text size) with intentional half-step padding values that fall between the spacing token scale - do not round these to the nearest token when customizing, they are tuned to the row's font size."
|
|
139
|
+
- "This is markup written by hand, row by row - for data driven by an array of records with built-in sorting, DataTable is very likely the better fit; reach for Table only when structure is needed that DataTable does not support (row spans, grouped headers, a footer)."
|
|
140
|
+
canonicalSnippet: |
|
|
141
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@adres/mgda-ui"
|
|
142
|
+
|
|
143
|
+
<Table>
|
|
144
|
+
<TableHeader>
|
|
145
|
+
<TableRow>
|
|
146
|
+
<TableHead>Name</TableHead>
|
|
147
|
+
<TableHead>Status</TableHead>
|
|
148
|
+
</TableRow>
|
|
149
|
+
</TableHeader>
|
|
150
|
+
<TableBody>
|
|
151
|
+
<TableRow>
|
|
152
|
+
<TableCell>Acme Corp</TableCell>
|
|
153
|
+
<TableCell>Active</TableCell>
|
|
154
|
+
</TableRow>
|
|
155
|
+
</TableBody>
|
|
156
|
+
</Table>
|
|
157
|
+
reviewedAt: 2026-09-01
|
|
158
|
+
reviewedAgainstContractHash: "954f019b29cd"
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Usage
|
|
162
|
+
|
|
163
|
+
`Table` is the hand-markup table primitive - reach for it when structure is
|
|
164
|
+
needed that a column-driven grid cannot express: row spans, grouped headers,
|
|
165
|
+
a footer row, or manually placed cells. For the common case of rendering rows
|
|
166
|
+
from an array of records with built-in sorting, `DataTable` is very likely
|
|
167
|
+
the better fit and needs far less markup. Reach for `DataList` instead for a
|
|
168
|
+
single record's label/value pairs, and `Accordion` for expandable sections
|
|
169
|
+
rather than tabular rows and columns.
|
|
170
|
+
|
|
171
|
+
`variant="surface"` (default) wraps the table in a bordered, rounded,
|
|
172
|
+
scrollable container; `variant="ghost"` drops that chrome for a table meant
|
|
173
|
+
to sit flush inside another surface, such as one already inside a `Card`.
|
|
174
|
+
`size` scales cell padding and text together across the whole table - set it
|
|
175
|
+
once on `Table`, not per cell.
|
|
176
|
+
|
|
177
|
+
## Anatomy
|
|
178
|
+
|
|
179
|
+
`Table` renders real, semantic HTML table elements throughout.
|
|
180
|
+
|
|
181
|
+
| Part | Role |
|
|
182
|
+
| --- | --- |
|
|
183
|
+
| `Table` | The `<table>` root, wrapped in a scroll container. Owns `size` and `variant`, shared via context. |
|
|
184
|
+
| `TableHeader` | The `<thead>`. Tinted when `variant="surface"`. |
|
|
185
|
+
| `TableBody` | The `<tbody>`. Owns row background, hover, and selected-state styling - deliberately not on `TableRow`, so header rows are unaffected. |
|
|
186
|
+
| `TableFooter` | The `<tfoot>`. |
|
|
187
|
+
| `TableRow` | A `<tr>`. Intentionally unstyled beyond structure - see `TableBody`. |
|
|
188
|
+
| `TableHead` | A `<th>`. |
|
|
189
|
+
| `TableCell` | A `<td>`. |
|
|
190
|
+
| `TableCaption` | A real `<caption>` - the correct way to give the table an accessible name or description. |
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: tabs
|
|
6
|
+
sourceFile: packages/design-system/src/components/tabs.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: Tabs
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<TabsProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: TabsContent
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<Omit<TabsContentProps & RefAttributes<HTMLDivElement>, \"ref\"> & RefAttributes<HTMLDivElement>>"
|
|
19
|
+
- name: TabsList
|
|
20
|
+
kind: component
|
|
21
|
+
typeText: "ForwardRefExoticComponent<Omit<TabsListProps & RefAttributes<HTMLDivElement>, \"ref\"> & RefAttributes<HTMLDivElement>>"
|
|
22
|
+
- name: TabsOrientation
|
|
23
|
+
kind: type
|
|
24
|
+
- name: TabsProps
|
|
25
|
+
kind: type
|
|
26
|
+
- name: TabsSize
|
|
27
|
+
kind: type
|
|
28
|
+
- name: TabsTrigger
|
|
29
|
+
kind: component
|
|
30
|
+
typeText: "ForwardRefExoticComponent<Omit<TabsTriggerProps & RefAttributes<HTMLButtonElement>, \"ref\"> & RefAttributes<HTMLButtonElement>>"
|
|
31
|
+
primaryExport: Tabs
|
|
32
|
+
subcomponents:
|
|
33
|
+
- TabsContent
|
|
34
|
+
- TabsList
|
|
35
|
+
- TabsTrigger
|
|
36
|
+
props:
|
|
37
|
+
Tabs:
|
|
38
|
+
- name: orientation
|
|
39
|
+
type: TabsOrientation
|
|
40
|
+
required: false
|
|
41
|
+
declaredIn: self
|
|
42
|
+
doc: "`horizontal` (default) is a segmented row; `vertical` stacks the triggers in a left-aligned column (labels may wrap)."
|
|
43
|
+
- name: size
|
|
44
|
+
type: TabsSize
|
|
45
|
+
required: false
|
|
46
|
+
declaredIn: self
|
|
47
|
+
extendsProps:
|
|
48
|
+
- "React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>"
|
|
49
|
+
variants:
|
|
50
|
+
size:
|
|
51
|
+
kind: enum
|
|
52
|
+
options:
|
|
53
|
+
- sm
|
|
54
|
+
- md
|
|
55
|
+
- lg
|
|
56
|
+
default: md
|
|
57
|
+
on: Tabs
|
|
58
|
+
orientation:
|
|
59
|
+
kind: enum
|
|
60
|
+
options:
|
|
61
|
+
- horizontal
|
|
62
|
+
- vertical
|
|
63
|
+
default: horizontal
|
|
64
|
+
on: Tabs
|
|
65
|
+
variantSource: prop-union
|
|
66
|
+
compoundVariants: []
|
|
67
|
+
sizeMaps:
|
|
68
|
+
- LIST_HEIGHT
|
|
69
|
+
- TRIGGER_PADDING
|
|
70
|
+
- TRIGGER_PADDING_Y
|
|
71
|
+
- TRIGGER_TEXT
|
|
72
|
+
dataSlots: []
|
|
73
|
+
dependsOn:
|
|
74
|
+
internal: []
|
|
75
|
+
lib:
|
|
76
|
+
- cn
|
|
77
|
+
hooks: []
|
|
78
|
+
external:
|
|
79
|
+
- "@radix-ui/react-tabs"
|
|
80
|
+
- react
|
|
81
|
+
contexts:
|
|
82
|
+
- name: TabsContext
|
|
83
|
+
type: TabsContextValue
|
|
84
|
+
default: null
|
|
85
|
+
stories:
|
|
86
|
+
- exportName: Default
|
|
87
|
+
id: components-tabs--default
|
|
88
|
+
storybookTitle: Components/Tabs
|
|
89
|
+
docsId: components-tabs--documentation
|
|
90
|
+
argTypeOptions: {}
|
|
91
|
+
resolvedCleanly: true
|
|
92
|
+
contractHash: "3be5f90e7de1"
|
|
93
|
+
factsHash: "4a3f7798cec2"
|
|
94
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
95
|
+
status: stable
|
|
96
|
+
summary: "A segmented (or vertically stacked) tab switcher with a floating, animated active indicator, on top of Radix Tabs."
|
|
97
|
+
useWhen:
|
|
98
|
+
- "switching between a small, fixed set of views that share the same context (a settings page's sections, a record's detail panels)"
|
|
99
|
+
- "the tab set is known ahead of time and short enough to show all at once - not for a long or dynamic list of destinations"
|
|
100
|
+
useInstead:
|
|
101
|
+
- id: segmented-control
|
|
102
|
+
when: "you're picking one value from a small set, not switching between panels of content - SegmentedControl carries the same visual language without the panel/content wiring"
|
|
103
|
+
- id: list-nav
|
|
104
|
+
when: "the set of destinations is longer than fits comfortably as tabs, or each one should be a real navigable URL"
|
|
105
|
+
related:
|
|
106
|
+
- segmented-control
|
|
107
|
+
composesWith: []
|
|
108
|
+
tokens:
|
|
109
|
+
- "--muted"
|
|
110
|
+
- "--card"
|
|
111
|
+
- "--primary-foreground"
|
|
112
|
+
- "--muted-foreground"
|
|
113
|
+
- "--foreground"
|
|
114
|
+
- "--ring"
|
|
115
|
+
a11y:
|
|
116
|
+
notes:
|
|
117
|
+
- "Radix Tabs supplies the full tab-panel contract: role=\"tablist\"/\"tab\"/\"tabpanel\", aria-selected, and roving tabindex so only the active trigger is in the tab order."
|
|
118
|
+
- "The floating indicator div is aria-hidden and purely visual - it plays no role in the accessible tab/panel relationship, which Radix handles independently."
|
|
119
|
+
- "size and orientation are read from context by TabsList/TabsTrigger/TabsContent - they must be set on the ancestor Tabs, not on the individual parts."
|
|
120
|
+
requiredProps:
|
|
121
|
+
- "every TabsTrigger and its paired TabsContent must share the same value string"
|
|
122
|
+
keyboard:
|
|
123
|
+
- "Radix default: Arrow keys move focus between triggers (horizontal uses Left/Right, vertical uses Up/Down per orientation), and Home/End jump to the first/last trigger."
|
|
124
|
+
- "By default Radix activates a tab as soon as it receives focus (automatic activation) - set activationMode=\"manual\" on Tabs (passed through props) if pressing Enter/Space should be required to switch."
|
|
125
|
+
radixHandles: true
|
|
126
|
+
pitfalls:
|
|
127
|
+
- "TabsList measures the active trigger's DOM rect to position the floating indicator - rendering TabsTrigger conditionally (mounting/unmounting rather than just disabling) can leave the indicator momentarily unpositioned until the next value change."
|
|
128
|
+
- "orientation must be set on Tabs, not on TabsList directly - it also changes Radix's own keyboard arrow-key axis, so setting it only visually (e.g. via className) leaves keyboard nav on the wrong axis."
|
|
129
|
+
- "TabsContent's default top margin (mt-4) only applies for horizontal orientation - vertical layouts are expected to place TabsList and TabsContent side by side in the consumer's own row layout, with no automatic gap between them."
|
|
130
|
+
subcomponentNotes:
|
|
131
|
+
TabsList: "Hosts the floating active-tab indicator, measured via getBoundingClientRect and re-measured via ResizeObserver on layout changes."
|
|
132
|
+
TabsTrigger: "Requires value, matched against Tabs' own value/defaultValue/onValueChange. Registers itself with TabsList so the indicator can find its position."
|
|
133
|
+
TabsContent: "Requires the same value as its paired TabsTrigger. Radix keeps only the active panel mounted by default."
|
|
134
|
+
rtl: "Layout uses flex, gap, and logical text-start/justify-start only - both orientations mirror correctly under RTL with no extra work. The floating indicator's position is computed from measured pixel rects, so it follows the mirrored layout automatically."
|
|
135
|
+
canonicalSnippet: |
|
|
136
|
+
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@adres/mgda-ui"
|
|
137
|
+
|
|
138
|
+
<Tabs defaultValue="profile" size="md">
|
|
139
|
+
<TabsList>
|
|
140
|
+
<TabsTrigger value="profile">Profile</TabsTrigger>
|
|
141
|
+
<TabsTrigger value="billing">Billing</TabsTrigger>
|
|
142
|
+
</TabsList>
|
|
143
|
+
<TabsContent value="profile">Profile settings go here.</TabsContent>
|
|
144
|
+
<TabsContent value="billing">Billing settings go here.</TabsContent>
|
|
145
|
+
</Tabs>
|
|
146
|
+
reviewedAt: 2026-08-31
|
|
147
|
+
reviewedAgainstContractHash: "3be5f90e7de1"
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Usage
|
|
151
|
+
|
|
152
|
+
Tabs wraps Radix's Tabs primitive with a shared visual language (matching
|
|
153
|
+
`SegmentedControl`/`Button` heights at every size) and a floating indicator
|
|
154
|
+
that slides behind the active trigger instead of each trigger drawing its own
|
|
155
|
+
active background. `size` and `orientation` are set once on the root `Tabs`
|
|
156
|
+
and read by every part through context - they cannot be set per-part.
|
|
157
|
+
|
|
158
|
+
Prefer uncontrolled usage (`defaultValue`) unless something outside the
|
|
159
|
+
component needs to read or drive the active tab; pass `value` +
|
|
160
|
+
`onValueChange` only in that case.
|
|
161
|
+
|
|
162
|
+
## Anatomy
|
|
163
|
+
|
|
164
|
+
- **Tabs** - the root: owns `size`, `orientation`, and the active value
|
|
165
|
+
(controlled or uncontrolled), and provides context to every other part.
|
|
166
|
+
- **TabsList** - the row (or column, in vertical orientation) of triggers,
|
|
167
|
+
plus the floating active-tab indicator.
|
|
168
|
+
- **TabsTrigger** - one tab button; `value` pairs it to its `TabsContent`.
|
|
169
|
+
- **TabsContent** - the panel shown when its `value` matches the active tab.
|