@omni-design/components 0.7.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.
- package/.claude/commands/ScanComponents.md +26 -0
- package/.claude/commands/ShareComponent.md +128 -0
- package/.cursorrules +21 -0
- package/CLAUDE.md +1046 -0
- package/README.md +70 -0
- package/dist/OmniDesignProvider.esm.js +2 -0
- package/dist/OmniDesignProvider.esm.js.map +1 -0
- package/dist/OmniDesignProvider.js +2 -0
- package/dist/OmniDesignProvider.js.map +1 -0
- package/dist/index.esm.js +42 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/types/OmniDesignProvider.d.ts +158 -0
- package/dist/types/components/Accordion/Accordion.d.ts +42 -0
- package/dist/types/components/Accordion/AccordionShowcase.d.ts +2 -0
- package/dist/types/components/Accordion/index.d.ts +2 -0
- package/dist/types/components/Alert/Alert.d.ts +14 -0
- package/dist/types/components/Alert/AlertShowcase.d.ts +2 -0
- package/dist/types/components/Alert/index.d.ts +2 -0
- package/dist/types/components/AppBar/AppBar.d.ts +43 -0
- package/dist/types/components/AppBar/AppBarShowcase.d.ts +2 -0
- package/dist/types/components/AppBar/index.d.ts +2 -0
- package/dist/types/components/Autocomplete/Autocomplete.d.ts +26 -0
- package/dist/types/components/Autocomplete/AutocompleteShowcase.d.ts +2 -0
- package/dist/types/components/Autocomplete/index.d.ts +2 -0
- package/dist/types/components/Avatar/Avatar.d.ts +29 -0
- package/dist/types/components/Avatar/AvatarShowcase.d.ts +2 -0
- package/dist/types/components/Avatar/defaultAvatar.d.ts +2 -0
- package/dist/types/components/Avatar/index.d.ts +3 -0
- package/dist/types/components/BackgroundPicker.d.ts +12 -0
- package/dist/types/components/Badge/Badge.d.ts +43 -0
- package/dist/types/components/Badge/BadgeShowcase.d.ts +1 -0
- package/dist/types/components/Badge/index.d.ts +2 -0
- package/dist/types/components/BevelText/BevelText.d.ts +15 -0
- package/dist/types/components/BevelText/BevelTextShowcase.d.ts +2 -0
- package/dist/types/components/BevelText/index.d.ts +2 -0
- package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +15 -0
- package/dist/types/components/BottomNavigation/BottomNavigationShowcase.d.ts +2 -0
- package/dist/types/components/BottomNavigation/index.d.ts +2 -0
- package/dist/types/components/Box/Box.d.ts +36 -0
- package/dist/types/components/Box/BoxShowcase.d.ts +2 -0
- package/dist/types/components/Box/index.d.ts +2 -0
- package/dist/types/components/Breadcrumbs/Breadcrumbs.d.ts +22 -0
- package/dist/types/components/Breadcrumbs/BreadcrumbsShowcase.d.ts +2 -0
- package/dist/types/components/Breadcrumbs/index.d.ts +2 -0
- package/dist/types/components/Button/Button.d.ts +66 -0
- package/dist/types/components/Button/index.d.ts +2 -0
- package/dist/types/components/ButtonGroup/ButtonGroup.d.ts +41 -0
- package/dist/types/components/ButtonGroup/index.d.ts +2 -0
- package/dist/types/components/Card/Card.d.ts +54 -0
- package/dist/types/components/Card/CardShowcase.d.ts +2 -0
- package/dist/types/components/Card/index.d.ts +2 -0
- package/dist/types/components/Checkbox/Checkbox.d.ts +51 -0
- package/dist/types/components/Checkbox/index.d.ts +2 -0
- package/dist/types/components/Chip/Chip.d.ts +42 -0
- package/dist/types/components/Chip/ChipShowcase.d.ts +2 -0
- package/dist/types/components/Chip/index.d.ts +2 -0
- package/dist/types/components/CircularProgress/CircularProgress.d.ts +12 -0
- package/dist/types/components/CircularProgress/CircularProgressShowcase.d.ts +2 -0
- package/dist/types/components/CircularProgress/index.d.ts +2 -0
- package/dist/types/components/CodeBlock/CodeBlock.d.ts +35 -0
- package/dist/types/components/Colors/Colors.d.ts +7 -0
- package/dist/types/components/Colors/index.d.ts +1 -0
- package/dist/types/components/Container/Container.d.ts +70 -0
- package/dist/types/components/Container/index.d.ts +1 -0
- package/dist/types/components/Copyright/Copyright.d.ts +11 -0
- package/dist/types/components/Copyright/CopyrightShowcase.d.ts +2 -0
- package/dist/types/components/Copyright/index.d.ts +2 -0
- package/dist/types/components/CurvedText/CurvedText.d.ts +23 -0
- package/dist/types/components/CurvedText/CurvedTextShowcase.d.ts +2 -0
- package/dist/types/components/CurvedText/index.d.ts +2 -0
- package/dist/types/components/Dialog/Dialog.d.ts +82 -0
- package/dist/types/components/Dialog/DialogShowcase.d.ts +2 -0
- package/dist/types/components/Dialog/index.d.ts +2 -0
- package/dist/types/components/Divider/Divider.d.ts +22 -0
- package/dist/types/components/Divider/DividerShowcase.d.ts +2 -0
- package/dist/types/components/Divider/index.d.ts +2 -0
- package/dist/types/components/Drawer/Drawer.d.ts +30 -0
- package/dist/types/components/Drawer/DrawerShowcase.d.ts +2 -0
- package/dist/types/components/Drawer/index.d.ts +2 -0
- package/dist/types/components/DropZone/DropZone.d.ts +15 -0
- package/dist/types/components/DropZone/index.d.ts +2 -0
- package/dist/types/components/Fab/Fab.d.ts +17 -0
- package/dist/types/components/Fab/FabShowcase.d.ts +2 -0
- package/dist/types/components/Fab/index.d.ts +2 -0
- package/dist/types/components/Footer/Footer.d.ts +14 -0
- package/dist/types/components/Footer/FooterShowcase.d.ts +2 -0
- package/dist/types/components/Footer/index.d.ts +2 -0
- package/dist/types/components/Gradient/Gradient.d.ts +38 -0
- package/dist/types/components/Gradient/GradientShowcase.d.ts +2 -0
- package/dist/types/components/Gradient/gradientUtils.d.ts +185 -0
- package/dist/types/components/Gradient/index.d.ts +3 -0
- package/dist/types/components/Grid/Grid.d.ts +112 -0
- package/dist/types/components/Grid/index.d.ts +1 -0
- package/dist/types/components/Header/Header.d.ts +53 -0
- package/dist/types/components/Header/index.d.ts +1 -0
- package/dist/types/components/Icon/Icon.d.ts +19 -0
- package/dist/types/components/Icon/IconShowcase.d.ts +2 -0
- package/dist/types/components/Icon/index.d.ts +2 -0
- package/dist/types/components/IconBadge/IconBadge.d.ts +10 -0
- package/dist/types/components/IconBadge/IconBadgeShowcase.d.ts +2 -0
- package/dist/types/components/IconBadge/index.d.ts +2 -0
- package/dist/types/components/Input/Input.d.ts +47 -0
- package/dist/types/components/Input/index.d.ts +2 -0
- package/dist/types/components/LinearProgress/LinearProgress.d.ts +9 -0
- package/dist/types/components/LinearProgress/LinearProgressShowcase.d.ts +2 -0
- package/dist/types/components/LinearProgress/index.d.ts +2 -0
- package/dist/types/components/Link/Link.d.ts +16 -0
- package/dist/types/components/Link/LinkShowcase.d.ts +2 -0
- package/dist/types/components/Link/index.d.ts +2 -0
- package/dist/types/components/List/List.d.ts +55 -0
- package/dist/types/components/List/ListShowcase.d.ts +2 -0
- package/dist/types/components/List/index.d.ts +2 -0
- package/dist/types/components/MainLayout/MainLayout.d.ts +28 -0
- package/dist/types/components/MainLayout/index.d.ts +1 -0
- package/dist/types/components/Menu/Menu.d.ts +37 -0
- package/dist/types/components/Menu/MenuShowcase.d.ts +2 -0
- package/dist/types/components/Menu/index.d.ts +2 -0
- package/dist/types/components/Modal/Modal.d.ts +18 -0
- package/dist/types/components/Modal/ModalShowcase.d.ts +2 -0
- package/dist/types/components/Modal/index.d.ts +2 -0
- package/dist/types/components/NumberField/NumberField.d.ts +22 -0
- package/dist/types/components/NumberField/NumberFieldShowcase.d.ts +2 -0
- package/dist/types/components/NumberField/index.d.ts +2 -0
- package/dist/types/components/Pagination/Pagination.d.ts +17 -0
- package/dist/types/components/Pagination/PaginationShowcase.d.ts +2 -0
- package/dist/types/components/Pagination/index.d.ts +2 -0
- package/dist/types/components/Paper/Paper.d.ts +111 -0
- package/dist/types/components/Paper/index.d.ts +1 -0
- package/dist/types/components/Popover/Popover.d.ts +31 -0
- package/dist/types/components/Popover/index.d.ts +1 -0
- package/dist/types/components/PreviewSurface.d.ts +18 -0
- package/dist/types/components/Radio/Radio.d.ts +55 -0
- package/dist/types/components/Radio/RadioShowcase.d.ts +2 -0
- package/dist/types/components/Radio/index.d.ts +2 -0
- package/dist/types/components/Rail/Rail.d.ts +15 -0
- package/dist/types/components/Rail/RailShowcase.d.ts +2 -0
- package/dist/types/components/Rail/index.d.ts +2 -0
- package/dist/types/components/Rating/Rating.d.ts +16 -0
- package/dist/types/components/Rating/RatingShowcase.d.ts +2 -0
- package/dist/types/components/Rating/index.d.ts +2 -0
- package/dist/types/components/Ratio/Ratio.d.ts +20 -0
- package/dist/types/components/Ratio/RatioShowcase.d.ts +2 -0
- package/dist/types/components/Ratio/index.d.ts +2 -0
- package/dist/types/components/SearchField/SearchField.d.ts +19 -0
- package/dist/types/components/SearchField/SearchFieldShowcase.d.ts +2 -0
- package/dist/types/components/SearchField/index.d.ts +2 -0
- package/dist/types/components/Section/Section.d.ts +44 -0
- package/dist/types/components/Section/SectionShowcase.d.ts +2 -0
- package/dist/types/components/Section/index.d.ts +2 -0
- package/dist/types/components/Select/Select.d.ts +23 -0
- package/dist/types/components/Select/SelectShowcase.d.ts +2 -0
- package/dist/types/components/Select/index.d.ts +2 -0
- package/dist/types/components/SettingsPanel.d.ts +2 -0
- package/dist/types/components/Sidebar/Sidebar.d.ts +53 -0
- package/dist/types/components/Sidebar/index.d.ts +1 -0
- package/dist/types/components/Slider/Slider.d.ts +79 -0
- package/dist/types/components/Slider/SliderShowcase.d.ts +2 -0
- package/dist/types/components/Slider/index.d.ts +2 -0
- package/dist/types/components/Snackbar/Snackbar.d.ts +17 -0
- package/dist/types/components/Snackbar/SnackbarShowcase.d.ts +2 -0
- package/dist/types/components/Snackbar/index.d.ts +2 -0
- package/dist/types/components/Spacing/Spacing.d.ts +16 -0
- package/dist/types/components/Spacing/index.d.ts +1 -0
- package/dist/types/components/SpeedDial/SpeedDial.d.ts +17 -0
- package/dist/types/components/SpeedDial/SpeedDialShowcase.d.ts +2 -0
- package/dist/types/components/SpeedDial/index.d.ts +2 -0
- package/dist/types/components/Stack/Stack.d.ts +52 -0
- package/dist/types/components/Stack/StackShowcase.d.ts +2 -0
- package/dist/types/components/Stack/index.d.ts +2 -0
- package/dist/types/components/Stepper/Stepper.d.ts +33 -0
- package/dist/types/components/Stepper/StepperShowcase.d.ts +2 -0
- package/dist/types/components/Stepper/index.d.ts +2 -0
- package/dist/types/components/Switch/Switch.d.ts +65 -0
- package/dist/types/components/Switch/SwitchShowcase.d.ts +2 -0
- package/dist/types/components/Switch/index.d.ts +2 -0
- package/dist/types/components/Table/Table.d.ts +20 -0
- package/dist/types/components/Table/TableShowcase.d.ts +2 -0
- package/dist/types/components/Table/index.d.ts +2 -0
- package/dist/types/components/Tabs/Tabs.d.ts +51 -0
- package/dist/types/components/Tabs/TabsShowcase.d.ts +2 -0
- package/dist/types/components/Tabs/index.d.ts +2 -0
- package/dist/types/components/Tag/Tag.d.ts +57 -0
- package/dist/types/components/Tag/TagShowcase.d.ts +2 -0
- package/dist/types/components/Tag/index.d.ts +2 -0
- package/dist/types/components/TextField/TextField.d.ts +105 -0
- package/dist/types/components/TextField/index.d.ts +1 -0
- package/dist/types/components/ToggleButton/ToggleButton.d.ts +94 -0
- package/dist/types/components/ToggleButton/index.d.ts +1 -0
- package/dist/types/components/ToggleButtonGroup/ToggleButtonGroup.d.ts +48 -0
- package/dist/types/components/Toolbar/Toolbar.d.ts +14 -0
- package/dist/types/components/Toolbar/ToolbarShowcase.d.ts +2 -0
- package/dist/types/components/Toolbar/index.d.ts +2 -0
- package/dist/types/components/Tooltip/Tooltip.d.ts +20 -0
- package/dist/types/components/Tooltip/TooltipShowcase.d.ts +2 -0
- package/dist/types/components/Tooltip/index.d.ts +2 -0
- package/dist/types/components/TreeView/TreeBranch.d.ts +14 -0
- package/dist/types/components/TreeView/TreeView.d.ts +82 -0
- package/dist/types/components/TreeView/TreeViewShowcase.d.ts +2 -0
- package/dist/types/components/TreeView/index.d.ts +3 -0
- package/dist/types/components/Typography/Typography.d.ts +492 -0
- package/dist/types/components/Typography/TypographyShowcase.d.ts +2 -0
- package/dist/types/components/Typography/index.d.ts +2 -0
- package/dist/types/components/_a11y/ContrastCheck.d.ts +15 -0
- package/dist/types/components/_bevelPresets.d.ts +92 -0
- package/dist/types/components/_shadows.d.ts +32 -0
- package/dist/types/components/index.d.ts +74 -0
- package/dist/types/theme/useThemeMode.d.ts +4 -0
- package/docs/components.md +797 -0
- package/docs/getting-started.md +409 -0
- package/docs/token-system.md +468 -0
- package/package.json +126 -0
- package/public/styles/Dark-Mode.css +13867 -0
- package/public/styles/Light-Mode.css +14091 -0
- package/public/styles/README.md +93 -0
- package/public/styles/base.css +261 -0
- package/public/styles/core.css +378 -0
- package/public/styles/foundation.css +72 -0
- package/public/styles/styles.css +6 -0
- package/public/styles/theme.js +234 -0
- package/public/styles/theme.json +12 -0
- package/public/styles/typography-tokens.css +720 -0
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
# Dyno Design System — Component Reference
|
|
2
|
+
|
|
3
|
+
## Component Manifest
|
|
4
|
+
|
|
5
|
+
| Component | Category | Variants | Colors | Sizes | WCAG AA |
|
|
6
|
+
|---|---|---|---|---|---|
|
|
7
|
+
| [Button](#button) | Inputs | solid, outline, light, ghost | 8 | 3 | ✅ |
|
|
8
|
+
| [ButtonGroup](#buttongroup) | Inputs | solid, outline, light, ghost | 8 | 3 | ✅ |
|
|
9
|
+
| [Checkbox](#checkbox) | Inputs | — | 8 | 3 | ✅ |
|
|
10
|
+
| [Input](#input) | Inputs | standard, floating label | 1 | 3 | ✅ |
|
|
11
|
+
| [Chip](#chip) | Display | solid, outline | 8 | 3 | ✅ |
|
|
12
|
+
| [Stack](#stack) | Layout | 11 sub-variants | — | — | ✅ |
|
|
13
|
+
| [Tabs](#tabs) | Navigation | solid, outline, light, ghost | 8 | 3 | ✅ |
|
|
14
|
+
| [Card](#card) | Layout | default, solid, light | 8 | — | ✅ |
|
|
15
|
+
|
|
16
|
+
### Color palette (applies to all `color` props)
|
|
17
|
+
|
|
18
|
+
`primary` · `secondary` · `tertiary` · `neutral` · `info` · `success` · `warning` · `error`
|
|
19
|
+
|
|
20
|
+
### Accessibility baseline
|
|
21
|
+
|
|
22
|
+
All components meet WCAG 2.1 AA. Plain and Ghost variants are excluded from
|
|
23
|
+
Checkbox because they fail WCAG 1.4.11 non-text contrast at ≥ 3:1. Focus rings
|
|
24
|
+
use `var(--Focus-Visible)` consistently across all interactive components.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Button
|
|
29
|
+
|
|
30
|
+
Solid, outline, and light variants across all 8 brand colors. Ghost is a
|
|
31
|
+
special chromeless variant for low-emphasis actions.
|
|
32
|
+
|
|
33
|
+
### Import
|
|
34
|
+
|
|
35
|
+
```jsx
|
|
36
|
+
import { Button } from '@dyno/components';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Props
|
|
40
|
+
|
|
41
|
+
| Prop | Type | Default | Options |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| `color` | string | `'primary'` | `primary` `secondary` `tertiary` `neutral` `info` `success` `warning` `error` |
|
|
44
|
+
| `variant` | string | `'solid'` | `solid` `outline` `light` `ghost` |
|
|
45
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
46
|
+
| `disabled` | boolean | `false` | — |
|
|
47
|
+
| `fullWidth` | boolean | `false` | — |
|
|
48
|
+
| `startIcon` | node | — | Any React node |
|
|
49
|
+
| `endIcon` | node | — | Any React node |
|
|
50
|
+
| `onClick` | function | — | — |
|
|
51
|
+
| `data-theme` | string | — | Overrides inherited theme |
|
|
52
|
+
| `aria-label` | string | — | Required for icon-only buttons |
|
|
53
|
+
|
|
54
|
+
### CSS variables consumed
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
--Buttons-{Color}-Button background (solid) / border (outline)
|
|
58
|
+
--Buttons-{Color}-Text foreground text
|
|
59
|
+
--Buttons-{Color}-Border border color
|
|
60
|
+
--Buttons-{Color}-Hover hover background
|
|
61
|
+
--Buttons-{Color}-Active active/pressed background
|
|
62
|
+
--Focus-Visible focus ring outline
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Examples
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
// Solid (default)
|
|
69
|
+
<Button color="primary">Save</Button>
|
|
70
|
+
|
|
71
|
+
// Outline
|
|
72
|
+
<Button color="secondary" variant="outline">Cancel</Button>
|
|
73
|
+
|
|
74
|
+
// Light — tinted background, useful on colored surfaces
|
|
75
|
+
<Button color="success" variant="light">Confirm</Button>
|
|
76
|
+
|
|
77
|
+
// Ghost — no background, no border; acts like a hotlink
|
|
78
|
+
<Button variant="ghost">Learn more</Button>
|
|
79
|
+
|
|
80
|
+
// Sizes
|
|
81
|
+
<Button size="small">Small</Button>
|
|
82
|
+
<Button size="large">Large</Button>
|
|
83
|
+
|
|
84
|
+
// Icon-only — aria-label required
|
|
85
|
+
<Button color="primary" startIcon={<DeleteIcon />} aria-label="Delete item" />
|
|
86
|
+
|
|
87
|
+
// Full-width
|
|
88
|
+
<Button color="primary" fullWidth>Submit</Button>
|
|
89
|
+
|
|
90
|
+
// Disabled
|
|
91
|
+
<Button color="primary" disabled>Unavailable</Button>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Accessibility notes
|
|
95
|
+
|
|
96
|
+
- Icon-only buttons must have `aria-label`.
|
|
97
|
+
- `disabled` sets `aria-disabled="true"` and keeps the button in tab order.
|
|
98
|
+
- Focus ring always uses `outline: 2px solid var(--Focus-Visible)` with
|
|
99
|
+
`outline-offset: 2px`.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## ButtonGroup
|
|
104
|
+
|
|
105
|
+
Groups two or more Buttons with consistent variant and size. Supports both
|
|
106
|
+
spaced and connected (border-collapsing) layouts.
|
|
107
|
+
|
|
108
|
+
### Import
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
import { ButtonGroup, Button } from '@dyno/components';
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Props
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Options |
|
|
117
|
+
|---|---|---|---|
|
|
118
|
+
| `variant` | string | `'solid'` | Same as Button |
|
|
119
|
+
| `color` | string | `'primary'` | Same as Button |
|
|
120
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
121
|
+
| `orientation` | string | `'horizontal'` | `horizontal` `vertical` |
|
|
122
|
+
| `spacing` | number | `0` | `0` = connected, `> 0` = gap in MUI spacing units |
|
|
123
|
+
| `disabled` | boolean | `false` | — |
|
|
124
|
+
| `fullWidth` | boolean | `false` | — |
|
|
125
|
+
| `aria-label` | string | — | Describes the group |
|
|
126
|
+
|
|
127
|
+
Variant and color props on `ButtonGroup` are passed down to all child `Button`
|
|
128
|
+
components. Individual child buttons can override with their own `color` or
|
|
129
|
+
`variant` props.
|
|
130
|
+
|
|
131
|
+
### Examples
|
|
132
|
+
|
|
133
|
+
```jsx
|
|
134
|
+
// Connected solid group
|
|
135
|
+
<ButtonGroup color="primary" aria-label="text formatting">
|
|
136
|
+
<Button startIcon={<BoldIcon />} aria-label="Bold" />
|
|
137
|
+
<Button startIcon={<ItalicIcon />} aria-label="Italic" />
|
|
138
|
+
<Button startIcon={<UnderlineIcon />} aria-label="Underline" />
|
|
139
|
+
</ButtonGroup>
|
|
140
|
+
|
|
141
|
+
// Spaced outline group
|
|
142
|
+
<ButtonGroup variant="outline" color="neutral" spacing={1} aria-label="view options">
|
|
143
|
+
<Button>Day</Button>
|
|
144
|
+
<Button>Week</Button>
|
|
145
|
+
<Button>Month</Button>
|
|
146
|
+
</ButtonGroup>
|
|
147
|
+
|
|
148
|
+
// Vertical
|
|
149
|
+
<ButtonGroup orientation="vertical" color="secondary">
|
|
150
|
+
<Button>Top</Button>
|
|
151
|
+
<Button>Middle</Button>
|
|
152
|
+
<Button>Bottom</Button>
|
|
153
|
+
</ButtonGroup>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Accessibility notes
|
|
157
|
+
|
|
158
|
+
- Always provide `aria-label` on the group describing its purpose.
|
|
159
|
+
- In connected mode (`spacing=0`), borders collapse via negative margin; hovered
|
|
160
|
+
and focused buttons get `z-index: 1` to appear above neighbors.
|
|
161
|
+
- Border radius is only applied to the outer edges of first and last buttons.
|
|
162
|
+
- Tab navigates sequentially through all buttons.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Checkbox
|
|
167
|
+
|
|
168
|
+
Single checkbox or group, with optional description. Excludes Plain and Ghost
|
|
169
|
+
variants as they fail WCAG 1.4.11 at 3:1 non-text contrast.
|
|
170
|
+
|
|
171
|
+
### Import
|
|
172
|
+
|
|
173
|
+
```jsx
|
|
174
|
+
import {
|
|
175
|
+
Checkbox,
|
|
176
|
+
CheckboxGroup,
|
|
177
|
+
CheckboxWithDescription,
|
|
178
|
+
IndeterminateCheckbox,
|
|
179
|
+
} from '@dyno/components';
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Checkbox Props
|
|
183
|
+
|
|
184
|
+
| Prop | Type | Default | Options |
|
|
185
|
+
|---|---|---|---|
|
|
186
|
+
| `label` | string | — | — |
|
|
187
|
+
| `checked` | boolean | `false` | — |
|
|
188
|
+
| `onChange` | function | — | `(event) => void` |
|
|
189
|
+
| `color` | string | `'primary'` | Same as Button |
|
|
190
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
191
|
+
| `disabled` | boolean | `false` | — |
|
|
192
|
+
| `indeterminate` | boolean | `false` | — |
|
|
193
|
+
| `required` | boolean | `false` | — |
|
|
194
|
+
|
|
195
|
+
### CheckboxGroup Props
|
|
196
|
+
|
|
197
|
+
| Prop | Type | Default | Options |
|
|
198
|
+
|---|---|---|---|
|
|
199
|
+
| `options` | array | — | `[{ label, value, disabled? }]` |
|
|
200
|
+
| `value` | array | `[]` | Selected values |
|
|
201
|
+
| `onChange` | function | — | `(values: string[]) => void` |
|
|
202
|
+
| `color` | string | `'primary'` | Same as Button |
|
|
203
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
204
|
+
| `direction` | string | `'vertical'` | `vertical` `horizontal` |
|
|
205
|
+
| `disabled` | boolean | `false` | — |
|
|
206
|
+
|
|
207
|
+
### CheckboxWithDescription Props
|
|
208
|
+
|
|
209
|
+
Extends Checkbox with a secondary description line below the label.
|
|
210
|
+
|
|
211
|
+
| Prop | Type | Default |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| `label` | string | — |
|
|
214
|
+
| `description` | string | — |
|
|
215
|
+
| `checked` | boolean | `false` |
|
|
216
|
+
| `onChange` | function | — |
|
|
217
|
+
| `color` | string | `'primary'` |
|
|
218
|
+
| `disabled` | boolean | `false` |
|
|
219
|
+
|
|
220
|
+
### IndeterminateCheckbox Props
|
|
221
|
+
|
|
222
|
+
| Prop | Type | Default |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| `label` | string | — |
|
|
225
|
+
| `checked` | boolean | `false` |
|
|
226
|
+
| `indeterminate` | boolean | `false` |
|
|
227
|
+
| `onChange` | function | — |
|
|
228
|
+
| `disabled` | boolean | `false` |
|
|
229
|
+
|
|
230
|
+
### CSS variables consumed
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
--Buttons-{Color}-Button checked fill
|
|
234
|
+
--Buttons-{Color}-Border checked border
|
|
235
|
+
--Buttons-{Color}-Text checkmark icon
|
|
236
|
+
--Border unchecked border
|
|
237
|
+
--Container-Low hover background
|
|
238
|
+
--Text label text
|
|
239
|
+
--Quiet description text (CheckboxWithDescription)
|
|
240
|
+
--Focus-Visible focus ring
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Examples
|
|
244
|
+
|
|
245
|
+
```jsx
|
|
246
|
+
// Basic
|
|
247
|
+
<Checkbox
|
|
248
|
+
label="Accept terms and conditions"
|
|
249
|
+
checked={accepted}
|
|
250
|
+
onChange={(e) => setAccepted(e.target.checked)}
|
|
251
|
+
/>
|
|
252
|
+
|
|
253
|
+
// Error color
|
|
254
|
+
<Checkbox label="Required item" color="error" checked={false} />
|
|
255
|
+
|
|
256
|
+
// Group — vertical (default)
|
|
257
|
+
<CheckboxGroup
|
|
258
|
+
options={[
|
|
259
|
+
{ label: 'Email', value: 'email' },
|
|
260
|
+
{ label: 'SMS', value: 'sms' },
|
|
261
|
+
{ label: 'Push', value: 'push', disabled: true },
|
|
262
|
+
]}
|
|
263
|
+
value={selected}
|
|
264
|
+
onChange={setSelected}
|
|
265
|
+
color="primary"
|
|
266
|
+
/>
|
|
267
|
+
|
|
268
|
+
// Group — horizontal
|
|
269
|
+
<CheckboxGroup
|
|
270
|
+
options={options}
|
|
271
|
+
value={selected}
|
|
272
|
+
onChange={setSelected}
|
|
273
|
+
direction="horizontal"
|
|
274
|
+
/>
|
|
275
|
+
|
|
276
|
+
// With description
|
|
277
|
+
<CheckboxWithDescription
|
|
278
|
+
label="Marketing emails"
|
|
279
|
+
description="Receive product updates and promotions"
|
|
280
|
+
checked={marketing}
|
|
281
|
+
onChange={(e) => setMarketing(e.target.checked)}
|
|
282
|
+
/>
|
|
283
|
+
|
|
284
|
+
// Indeterminate (select-all pattern)
|
|
285
|
+
<IndeterminateCheckbox
|
|
286
|
+
label="Select all"
|
|
287
|
+
checked={allChecked}
|
|
288
|
+
indeterminate={someChecked && !allChecked}
|
|
289
|
+
onChange={handleSelectAll}
|
|
290
|
+
/>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Input
|
|
296
|
+
|
|
297
|
+
Text input field. Supports standard (label above) and floating (label inside)
|
|
298
|
+
label positions, three sizes, and validation states.
|
|
299
|
+
|
|
300
|
+
### Import
|
|
301
|
+
|
|
302
|
+
```jsx
|
|
303
|
+
import { Input } from '@dyno/components';
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Props
|
|
307
|
+
|
|
308
|
+
| Prop | Type | Default | Options |
|
|
309
|
+
|---|---|---|---|
|
|
310
|
+
| `label` | string | — | — |
|
|
311
|
+
| `value` | string | — | — |
|
|
312
|
+
| `onChange` | function | — | `(event) => void` |
|
|
313
|
+
| `placeholder` | string | — | — |
|
|
314
|
+
| `labelPosition` | string | `'standard'` | `standard` `floating` |
|
|
315
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
316
|
+
| `type` | string | `'text'` | Any HTML input type |
|
|
317
|
+
| `validationState` | string | — | `success` `warning` `error` |
|
|
318
|
+
| `helperText` | string | — | Shown below input |
|
|
319
|
+
| `disabled` | boolean | `false` | — |
|
|
320
|
+
| `required` | boolean | `false` | — |
|
|
321
|
+
| `fullWidth` | boolean | `true` | — |
|
|
322
|
+
| `startAdornment` | node | — | Icon or text before input |
|
|
323
|
+
| `endAdornment` | node | — | Icon or text after input |
|
|
324
|
+
| `data-surface` | string | `'Container-Lowest'` | Must match parent surface |
|
|
325
|
+
|
|
326
|
+
### CSS variables consumed
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
--Border default border
|
|
330
|
+
--Buttons-Primary-Border focused border
|
|
331
|
+
--Buttons-Error-Border error border
|
|
332
|
+
--Buttons-Success-Border success border
|
|
333
|
+
--Buttons-Warning-Border warning border
|
|
334
|
+
--Text input text, label (focused/filled)
|
|
335
|
+
--Quiet placeholder, label (unfocused/empty)
|
|
336
|
+
--Container-Lowest input background
|
|
337
|
+
--Focus-Visible focus ring
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Important: data-surface must match
|
|
341
|
+
|
|
342
|
+
The Input sets `data-surface="Container-Lowest"` on its internal root by default.
|
|
343
|
+
This must match the surface of its parent — if the Input sits inside a
|
|
344
|
+
`Container-High` card, pass `data-surface="Container-High"` so the background
|
|
345
|
+
variable resolves correctly.
|
|
346
|
+
|
|
347
|
+
```jsx
|
|
348
|
+
// Inside a default card
|
|
349
|
+
<Input label="Name" value={name} onChange={setName} />
|
|
350
|
+
|
|
351
|
+
// Inside a Container-High surface
|
|
352
|
+
<Input
|
|
353
|
+
label="Name"
|
|
354
|
+
value={name}
|
|
355
|
+
onChange={setName}
|
|
356
|
+
data-surface="Container-High"
|
|
357
|
+
/>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Examples
|
|
361
|
+
|
|
362
|
+
```jsx
|
|
363
|
+
// Standard label
|
|
364
|
+
<Input label="Email address" value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
365
|
+
|
|
366
|
+
// Floating label
|
|
367
|
+
<Input label="Password" labelPosition="floating" type="password" value={pw} onChange={setPw} />
|
|
368
|
+
|
|
369
|
+
// Validation states
|
|
370
|
+
<Input label="Username" validationState="success" helperText="Username is available" value={u} />
|
|
371
|
+
<Input label="Username" validationState="error" helperText="Already taken" value={u} />
|
|
372
|
+
<Input label="Username" validationState="warning" helperText="Username may be taken" value={u} />
|
|
373
|
+
|
|
374
|
+
// With adornments
|
|
375
|
+
<Input
|
|
376
|
+
label="Search"
|
|
377
|
+
startAdornment={<SearchIcon />}
|
|
378
|
+
endAdornment={<ClearIcon />}
|
|
379
|
+
value={query}
|
|
380
|
+
onChange={setQuery}
|
|
381
|
+
/>
|
|
382
|
+
|
|
383
|
+
// Sizes
|
|
384
|
+
<Input label="Small" size="small" value={v} />
|
|
385
|
+
<Input label="Large" size="large" value={v} />
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Accessibility notes
|
|
389
|
+
|
|
390
|
+
- Label is always rendered in the DOM — never use `placeholder` as a substitute.
|
|
391
|
+
- Helper text and validation messages are linked to the input via `aria-describedby`.
|
|
392
|
+
- Error state adds `aria-invalid="true"`.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Chip
|
|
397
|
+
|
|
398
|
+
Non-interactive tags and interactive action chips. Solid and outline styles for
|
|
399
|
+
both. Excludes Plain and Ghost variants (fail WCAG 1.4.11).
|
|
400
|
+
|
|
401
|
+
### Import
|
|
402
|
+
|
|
403
|
+
```jsx
|
|
404
|
+
import { Chip } from '@dyno/components';
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Props
|
|
408
|
+
|
|
409
|
+
| Prop | Type | Default | Options |
|
|
410
|
+
|---|---|---|---|
|
|
411
|
+
| `label` | string | — | — |
|
|
412
|
+
| `color` | string | `'primary'` | Same as Button |
|
|
413
|
+
| `variant` | string | `'solid'` | `solid` `outline` |
|
|
414
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
415
|
+
| `clickable` | boolean | `false` | — |
|
|
416
|
+
| `deletable` | boolean | `false` | — |
|
|
417
|
+
| `onDelete` | function | — | Called when delete icon clicked |
|
|
418
|
+
| `onClick` | function | — | Required when `clickable={true}` |
|
|
419
|
+
| `icon` | node | — | Leading icon |
|
|
420
|
+
| `selected` | boolean | `false` | Visual selected state for clickable chips |
|
|
421
|
+
| `disabled` | boolean | `false` | — |
|
|
422
|
+
|
|
423
|
+
### CSS variables consumed
|
|
424
|
+
|
|
425
|
+
**Non-clickable solid:** `--Tags-{Color}-BG`, `--Tags-{Color}-Text`
|
|
426
|
+
|
|
427
|
+
**Non-clickable outline:** `--Tags-{Color}-BG` (border), `--Text`
|
|
428
|
+
|
|
429
|
+
**Clickable solid:** `--Buttons-{Color}-Button`, `--Buttons-{Color}-Text`,
|
|
430
|
+
`--Buttons-{Color}-Hover`, `--Buttons-{Color}-Active`
|
|
431
|
+
|
|
432
|
+
**Clickable outline:** `--Buttons-{Color}-Border`, `--Text`,
|
|
433
|
+
`--Buttons-{Color}-Outline-Hover`, `--Buttons-{Color}-Outline-Active`
|
|
434
|
+
|
|
435
|
+
### Examples
|
|
436
|
+
|
|
437
|
+
```jsx
|
|
438
|
+
// Non-clickable tag — status indicator
|
|
439
|
+
<Chip label="Active" color="success" />
|
|
440
|
+
<Chip label="Pending" color="warning" variant="outline" />
|
|
441
|
+
<Chip label="Archived" color="neutral" />
|
|
442
|
+
|
|
443
|
+
// Clickable — filter chip
|
|
444
|
+
<Chip
|
|
445
|
+
label="Design"
|
|
446
|
+
color="primary"
|
|
447
|
+
clickable
|
|
448
|
+
selected={selected}
|
|
449
|
+
onClick={() => setSelected(!selected)}
|
|
450
|
+
/>
|
|
451
|
+
|
|
452
|
+
// Deletable
|
|
453
|
+
<Chip
|
|
454
|
+
label="React"
|
|
455
|
+
color="info"
|
|
456
|
+
deletable
|
|
457
|
+
onDelete={() => removeTag('react')}
|
|
458
|
+
/>
|
|
459
|
+
|
|
460
|
+
// With icon
|
|
461
|
+
<Chip label="Verified" color="success" icon={<CheckIcon />} />
|
|
462
|
+
|
|
463
|
+
// Sizes
|
|
464
|
+
<Chip label="Small" size="small" color="primary" />
|
|
465
|
+
<Chip label="Large" size="large" color="secondary" />
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Accessibility notes
|
|
469
|
+
|
|
470
|
+
- Non-clickable chips have `role="status"` by default.
|
|
471
|
+
- Clickable chips use `role="button"` and are keyboard operable (Enter / Space).
|
|
472
|
+
- Delete button within a chip has `aria-label="Remove {label}"`.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Stack
|
|
477
|
+
|
|
478
|
+
Flexible layout primitive for arranging children in a row or column with
|
|
479
|
+
consistent spacing. Eleven named sub-variants cover the most common layout
|
|
480
|
+
patterns.
|
|
481
|
+
|
|
482
|
+
### Import
|
|
483
|
+
|
|
484
|
+
```jsx
|
|
485
|
+
import {
|
|
486
|
+
Stack,
|
|
487
|
+
HStack,
|
|
488
|
+
VStack,
|
|
489
|
+
CenteredStack,
|
|
490
|
+
SpaceBetweenStack,
|
|
491
|
+
ResponsiveStack,
|
|
492
|
+
GridStack,
|
|
493
|
+
StackDivider,
|
|
494
|
+
InsetStack,
|
|
495
|
+
ScrollStack,
|
|
496
|
+
WrapStack,
|
|
497
|
+
} from '@dyno/components';
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Stack Props
|
|
501
|
+
|
|
502
|
+
| Prop | Type | Default | Options |
|
|
503
|
+
|---|---|---|---|
|
|
504
|
+
| `direction` | string | `'column'` | `row` `column` `row-reverse` `column-reverse` |
|
|
505
|
+
| `spacing` | number | `2` | MUI spacing units (multiples of 8px) |
|
|
506
|
+
| `alignItems` | string | `'stretch'` | Any CSS `align-items` value |
|
|
507
|
+
| `justifyContent` | string | `'flex-start'` | Any CSS `justify-content` value |
|
|
508
|
+
| `wrap` | boolean | `false` | Enables `flex-wrap: wrap` |
|
|
509
|
+
| `divider` | node | — | Rendered between each child |
|
|
510
|
+
| `fullWidth` | boolean | `false` | `width: 100%` |
|
|
511
|
+
| `fullHeight` | boolean | `false` | `height: 100%` |
|
|
512
|
+
|
|
513
|
+
### Named sub-variants
|
|
514
|
+
|
|
515
|
+
| Component | Equivalent |
|
|
516
|
+
|---|---|
|
|
517
|
+
| `HStack` | `<Stack direction="row">` |
|
|
518
|
+
| `VStack` | `<Stack direction="column">` |
|
|
519
|
+
| `CenteredStack` | Row, centered both axes |
|
|
520
|
+
| `SpaceBetweenStack` | Row, `justifyContent="space-between"` |
|
|
521
|
+
| `WrapStack` | Row with `wrap={true}` |
|
|
522
|
+
| `GridStack` | CSS grid wrapper with configurable columns |
|
|
523
|
+
| `ScrollStack` | Column with `overflow-y: auto` |
|
|
524
|
+
| `InsetStack` | Column with padding inset |
|
|
525
|
+
| `StackDivider` | `<Divider>` for use as a `divider` prop value |
|
|
526
|
+
| `ResponsiveStack` | Column on mobile, row on desktop |
|
|
527
|
+
|
|
528
|
+
### Examples
|
|
529
|
+
|
|
530
|
+
```jsx
|
|
531
|
+
// Row of buttons with gap
|
|
532
|
+
<HStack spacing={2}>
|
|
533
|
+
<Button color="primary">Save</Button>
|
|
534
|
+
<Button color="neutral" variant="outline">Cancel</Button>
|
|
535
|
+
</HStack>
|
|
536
|
+
|
|
537
|
+
// Form fields
|
|
538
|
+
<VStack spacing={3}>
|
|
539
|
+
<Input label="First name" />
|
|
540
|
+
<Input label="Last name" />
|
|
541
|
+
<Input label="Email" />
|
|
542
|
+
</VStack>
|
|
543
|
+
|
|
544
|
+
// Space-between header
|
|
545
|
+
<SpaceBetweenStack>
|
|
546
|
+
<Heading>Dashboard</Heading>
|
|
547
|
+
<Button color="primary">New item</Button>
|
|
548
|
+
</SpaceBetweenStack>
|
|
549
|
+
|
|
550
|
+
// Dividers between items
|
|
551
|
+
<VStack spacing={0} divider={<StackDivider />}>
|
|
552
|
+
<ListItem />
|
|
553
|
+
<ListItem />
|
|
554
|
+
<ListItem />
|
|
555
|
+
</VStack>
|
|
556
|
+
|
|
557
|
+
// Responsive — column on mobile, row on desktop
|
|
558
|
+
<ResponsiveStack spacing={3}>
|
|
559
|
+
<Card>...</Card>
|
|
560
|
+
<Card>...</Card>
|
|
561
|
+
</ResponsiveStack>
|
|
562
|
+
|
|
563
|
+
// Wrapping chips/tags
|
|
564
|
+
<WrapStack spacing={1}>
|
|
565
|
+
{tags.map(tag => <Chip key={tag} label={tag} color="primary" />)}
|
|
566
|
+
</WrapStack>
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## Tabs
|
|
572
|
+
|
|
573
|
+
Tabbed navigation and content panels. Supports the same variant × color matrix
|
|
574
|
+
as Button.
|
|
575
|
+
|
|
576
|
+
### Import
|
|
577
|
+
|
|
578
|
+
```jsx
|
|
579
|
+
import { Tabs, TabPanel } from '@dyno/components';
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Tabs Props
|
|
583
|
+
|
|
584
|
+
| Prop | Type | Default | Options |
|
|
585
|
+
|---|---|---|---|
|
|
586
|
+
| `tabs` | array | — | `[{ label, value, icon?, disabled? }]` |
|
|
587
|
+
| `value` | string \| number | — | Active tab value |
|
|
588
|
+
| `onChange` | function | — | `(value) => void` |
|
|
589
|
+
| `variant` | string | `'solid'` | `solid` `outline` `light` `ghost` `underline` `pill` `segment` |
|
|
590
|
+
| `color` | string | `'primary'` | Same as Button |
|
|
591
|
+
| `size` | string | `'medium'` | `small` `medium` `large` |
|
|
592
|
+
| `orientation` | string | `'horizontal'` | `horizontal` `vertical` |
|
|
593
|
+
| `fullWidth` | boolean | `false` | Tabs fill container width |
|
|
594
|
+
| `scrollable` | boolean | `false` | Horizontal scroll for overflow |
|
|
595
|
+
|
|
596
|
+
### TabPanel Props
|
|
597
|
+
|
|
598
|
+
| Prop | Type | Default |
|
|
599
|
+
|---|---|---|
|
|
600
|
+
| `value` | string \| number | — |
|
|
601
|
+
| `activeValue` | string \| number | — |
|
|
602
|
+
| `children` | node | — |
|
|
603
|
+
| `keepMounted` | boolean | `false` |
|
|
604
|
+
|
|
605
|
+
### CSS variables consumed
|
|
606
|
+
|
|
607
|
+
```
|
|
608
|
+
--Buttons-{Color}-Button active tab background (solid)
|
|
609
|
+
--Buttons-{Color}-Text active tab text (solid)
|
|
610
|
+
--Buttons-{Color}-Border active indicator (underline/outline)
|
|
611
|
+
--Buttons-{Color}-Hover hover state
|
|
612
|
+
--Text inactive tab text
|
|
613
|
+
--Quiet inactive tab text (ghost/underline)
|
|
614
|
+
--Border tab group border
|
|
615
|
+
--Focus-Visible focus ring
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Examples
|
|
619
|
+
|
|
620
|
+
```jsx
|
|
621
|
+
const [tab, setTab] = useState('overview');
|
|
622
|
+
|
|
623
|
+
// Solid tabs
|
|
624
|
+
<Tabs
|
|
625
|
+
tabs={[
|
|
626
|
+
{ label: 'Overview', value: 'overview' },
|
|
627
|
+
{ label: 'Analytics', value: 'analytics' },
|
|
628
|
+
{ label: 'Settings', value: 'settings' },
|
|
629
|
+
]}
|
|
630
|
+
value={tab}
|
|
631
|
+
onChange={setTab}
|
|
632
|
+
color="primary"
|
|
633
|
+
/>
|
|
634
|
+
|
|
635
|
+
// Underline style
|
|
636
|
+
<Tabs tabs={tabs} value={tab} onChange={setTab} variant="underline" />
|
|
637
|
+
|
|
638
|
+
// Pill style
|
|
639
|
+
<Tabs tabs={tabs} value={tab} onChange={setTab} variant="pill" color="secondary" />
|
|
640
|
+
|
|
641
|
+
// With panels
|
|
642
|
+
<Tabs tabs={tabs} value={tab} onChange={setTab} />
|
|
643
|
+
<TabPanel value="overview" activeValue={tab}>
|
|
644
|
+
<p>Overview content</p>
|
|
645
|
+
</TabPanel>
|
|
646
|
+
<TabPanel value="analytics" activeValue={tab}>
|
|
647
|
+
<p>Analytics content</p>
|
|
648
|
+
</TabPanel>
|
|
649
|
+
|
|
650
|
+
// With icons
|
|
651
|
+
<Tabs
|
|
652
|
+
tabs={[
|
|
653
|
+
{ label: 'Home', value: 'home', icon: <HomeIcon /> },
|
|
654
|
+
{ label: 'Profile', value: 'profile', icon: <PersonIcon /> },
|
|
655
|
+
]}
|
|
656
|
+
value={tab}
|
|
657
|
+
onChange={setTab}
|
|
658
|
+
/>
|
|
659
|
+
|
|
660
|
+
// Vertical tabs
|
|
661
|
+
<HStack spacing={0} alignItems="flex-start">
|
|
662
|
+
<Tabs
|
|
663
|
+
orientation="vertical"
|
|
664
|
+
tabs={tabs}
|
|
665
|
+
value={tab}
|
|
666
|
+
onChange={setTab}
|
|
667
|
+
/>
|
|
668
|
+
<TabPanel value={tab} activeValue={tab}>...</TabPanel>
|
|
669
|
+
</HStack>
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### Accessibility notes
|
|
673
|
+
|
|
674
|
+
- Tabs use `role="tablist"` / `role="tab"` / `role="tabpanel"` markup.
|
|
675
|
+
- Arrow keys navigate between tabs when a tab has focus.
|
|
676
|
+
- Active tab has `aria-selected="true"`.
|
|
677
|
+
- `TabPanel` is linked to its tab via `aria-labelledby`.
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
681
|
+
## Card
|
|
682
|
+
|
|
683
|
+
Surface container for grouped content. Sets `data-theme` and `data-surface` so
|
|
684
|
+
all child components automatically inherit the correct color context.
|
|
685
|
+
|
|
686
|
+
### Import
|
|
687
|
+
|
|
688
|
+
```jsx
|
|
689
|
+
import { Card } from '@dyno/components';
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Props
|
|
693
|
+
|
|
694
|
+
| Prop | Type | Default | Options |
|
|
695
|
+
|---|---|---|---|
|
|
696
|
+
| `color` | string | `'neutral'` | Same as Button |
|
|
697
|
+
| `variant` | string | `'default'` | `default` `solid` `light` |
|
|
698
|
+
| `surface` | string | — | Overrides the resolved surface type |
|
|
699
|
+
| `elevation` | number | `2` | `0` – `5` maps to `--Effect-Level-{n}` |
|
|
700
|
+
| `padding` | string | `'medium'` | `none` `small` `medium` `large` |
|
|
701
|
+
| `radius` | string | `'medium'` | `none` `small` `medium` `large` `full` |
|
|
702
|
+
| `data-theme` | string | — | Explicit theme override |
|
|
703
|
+
| `data-surface` | string | — | Explicit surface override |
|
|
704
|
+
| `onClick` | function | — | Makes card interactive/clickable |
|
|
705
|
+
| `selected` | boolean | `false` | Visual selected state |
|
|
706
|
+
| `disabled` | boolean | `false` | — |
|
|
707
|
+
| `header` | node | — | Rendered in card header slot |
|
|
708
|
+
| `footer` | node | — | Rendered in card footer slot |
|
|
709
|
+
| `media` | node | — | Full-width media slot (image, video) |
|
|
710
|
+
|
|
711
|
+
### Variant → data-theme mapping
|
|
712
|
+
|
|
713
|
+
| variant | color | Resolved data-theme |
|
|
714
|
+
|---|---|---|
|
|
715
|
+
| `solid` | `primary` | `Primary` |
|
|
716
|
+
| `solid` | `secondary` | `Secondary` |
|
|
717
|
+
| `light` | `primary` | `Primary-Light` |
|
|
718
|
+
| `light` | `secondary` | `Secondary-Light` |
|
|
719
|
+
| `default` | any | Inherited from nearest ancestor |
|
|
720
|
+
|
|
721
|
+
### CSS variables consumed
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
--Container card background (default/light variants)
|
|
725
|
+
--Background solid variant background
|
|
726
|
+
--Text heading and body text
|
|
727
|
+
--Quiet secondary text
|
|
728
|
+
--Border card border (when elevation=0)
|
|
729
|
+
--Effect-Level-{n} box shadow
|
|
730
|
+
--Style-Border-Radius border radius
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### Examples
|
|
734
|
+
|
|
735
|
+
```jsx
|
|
736
|
+
// Default — inherits theme from parent
|
|
737
|
+
<Card>
|
|
738
|
+
<p>Simple content card</p>
|
|
739
|
+
</Card>
|
|
740
|
+
|
|
741
|
+
// Solid Primary — sets its own theme context
|
|
742
|
+
<Card variant="solid" color="primary">
|
|
743
|
+
<Button color="primary">Action</Button>
|
|
744
|
+
</Card>
|
|
745
|
+
|
|
746
|
+
// Light Secondary
|
|
747
|
+
<Card variant="light" color="secondary" padding="large">
|
|
748
|
+
<VStack spacing={2}>
|
|
749
|
+
<Input label="Name" />
|
|
750
|
+
<Button color="secondary" fullWidth>Submit</Button>
|
|
751
|
+
</VStack>
|
|
752
|
+
</Card>
|
|
753
|
+
|
|
754
|
+
// Elevated
|
|
755
|
+
<Card elevation={4}>
|
|
756
|
+
<p>Floating card</p>
|
|
757
|
+
</Card>
|
|
758
|
+
|
|
759
|
+
// With header and footer slots
|
|
760
|
+
<Card
|
|
761
|
+
header={<HStack spacing={1}><Avatar /><span>Jane Smith</span></HStack>}
|
|
762
|
+
footer={<HStack spacing={1}><Button variant="outline" color="neutral">Dismiss</Button><Button color="primary">Reply</Button></HStack>}
|
|
763
|
+
>
|
|
764
|
+
<p>Card body content goes here.</p>
|
|
765
|
+
</Card>
|
|
766
|
+
|
|
767
|
+
// Clickable / selectable card
|
|
768
|
+
<Card onClick={() => setSelected(id)} selected={selectedId === id}>
|
|
769
|
+
<p>Click to select</p>
|
|
770
|
+
</Card>
|
|
771
|
+
|
|
772
|
+
// Nested themes — inner card gets its own context
|
|
773
|
+
<Card variant="solid" color="primary">
|
|
774
|
+
<Card variant="default" surface="Container-High">
|
|
775
|
+
<Button color="primary">Inherits Primary-Light context</Button>
|
|
776
|
+
</Card>
|
|
777
|
+
</Card>
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
### Theme inheritance behavior
|
|
781
|
+
|
|
782
|
+
When `variant="default"`, Card uses DOM traversal to find the nearest ancestor
|
|
783
|
+
with a `data-theme` attribute and inherits it. This means a default card placed
|
|
784
|
+
inside a Primary solid card will automatically use the Primary token set without
|
|
785
|
+
any explicit props.
|
|
786
|
+
|
|
787
|
+
When `variant="solid"` or `variant="light"`, Card sets its own `data-theme`
|
|
788
|
+
based on the `color` prop regardless of the surrounding context.
|
|
789
|
+
|
|
790
|
+
An explicit `data-theme` prop always wins over both.
|
|
791
|
+
|
|
792
|
+
### Accessibility notes
|
|
793
|
+
|
|
794
|
+
- Clickable cards have `role="button"` and `tabIndex={0}`.
|
|
795
|
+
- Clickable cards are keyboard operable (Enter / Space).
|
|
796
|
+
- Selected state sets `aria-pressed="true"` on clickable cards.
|
|
797
|
+
- Disabled clickable cards set `aria-disabled="true"`.
|