@devalok/shilp-sutra 0.41.0 → 0.42.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/MIGRATION.md +8 -0
- package/llms-full.txt +1 -1
- package/make-kit/Guidelines.md +71 -0
- package/make-kit/components/badge.md +162 -0
- package/make-kit/components/button.md +125 -0
- package/make-kit/components/card.md +147 -0
- package/make-kit/components/dialog.md +167 -0
- package/make-kit/components/dropdown-menu.md +205 -0
- package/make-kit/components/form.md +189 -0
- package/make-kit/components/icon.md +152 -0
- package/make-kit/components/input.md +154 -0
- package/make-kit/components/overview.md +308 -0
- package/make-kit/components/popover.md +201 -0
- package/make-kit/components/select.md +148 -0
- package/make-kit/components/stack.md +165 -0
- package/make-kit/components/table.md +215 -0
- package/make-kit/components/tabs.md +162 -0
- package/make-kit/components/text.md +139 -0
- package/make-kit/components/toast.md +193 -0
- package/make-kit/foundations/color.md +128 -0
- package/make-kit/foundations/dark-mode.md +81 -0
- package/make-kit/foundations/icons.md +107 -0
- package/make-kit/foundations/motion.md +134 -0
- package/make-kit/foundations/radius.md +78 -0
- package/make-kit/foundations/spacing.md +110 -0
- package/make-kit/foundations/surfaces.md +121 -0
- package/make-kit/foundations/typography.md +120 -0
- package/make-kit/setup.md +130 -0
- package/package.json +5 -2
- package/skill/SKILL.md +1 -1
- package/skill/references/components-full.md +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Icon
|
|
2
|
+
|
|
3
|
+
Wrapper around Tabler icon components. Auto-sizes via `IconProvider` context.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Icon } from '@devalok/shilp-sutra/ui'
|
|
7
|
+
import { IconPlus, IconCheck, IconX } from '@tabler/icons-react'
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
For the broader icon system (which icons exist, how to register custom ones, the IconProvider tree), see `foundations/icons.md`. This guide covers the `<Icon>` component itself.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
- Any inline SVG icon — inside Button slots, IconButton, Badge slots, table cells, list rows.
|
|
15
|
+
- Need an interactive icon button? Use `<IconButton>`, not Icon wrapped in `<button>`.
|
|
16
|
+
- Need a static cluster of related icons? Use `<IconGroup>`.
|
|
17
|
+
- Need a status indicator? Use `<StatusDot>` or `<Badge dot>` — they're optimized for that.
|
|
18
|
+
|
|
19
|
+
Tabler-only. Don't mix icon libraries — see `foundations/icons.md` for the rationale.
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
|
|
23
|
+
| Prop | Type | Notes |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `icon` | `ForwardRefExoticComponent` (REQUIRED) | Tabler icon component (or any ForwardRef SVG icon matching the Tabler shape). |
|
|
26
|
+
| `size` | `'xs'\|'sm'\|'md'\|'lg'\|'xl'\|'2xl'` | Reads from `IconContext` if not set. |
|
|
27
|
+
| `stroke` | `'light'\|'regular'\|'bold'` | Reads from `IconContext` if not set. |
|
|
28
|
+
| `label` | `string` | Accessible label — sets `role="img"`, `aria-label`, and `<title>`. Without it, icon is `aria-hidden="true"`. |
|
|
29
|
+
| `animate` | `'spin'\|'pulse'\|'bounce'\|'draw'\|'none'` \| `{ rotate?, scale? }` | Static when undefined. |
|
|
30
|
+
| `state` | `'idle'\|'loading'\|'success'\|'error'` | State machine — overrides `animate` when both set. |
|
|
31
|
+
| `className` | `string` | |
|
|
32
|
+
|
|
33
|
+
## Size scale
|
|
34
|
+
|
|
35
|
+
| Size | Pixel | Default use |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `xs` | 14 | Inside `xs` buttons / badges, dense table cells. |
|
|
38
|
+
| `sm` | 16 | Inside `sm` buttons / badges, standard inline. |
|
|
39
|
+
| `md` (default) | 18 | Inside `md` buttons / inputs. |
|
|
40
|
+
| `lg` | 20 | Inside `lg` buttons / large inputs. |
|
|
41
|
+
| `xl` | 24 | Standalone icons in card headers. |
|
|
42
|
+
| `2xl` | 32 | Hero / illustration accents. |
|
|
43
|
+
|
|
44
|
+
Stroke weight varies by size — smaller icons use lighter strokes for clarity. Override via `stroke` only when the visual weight feels off.
|
|
45
|
+
|
|
46
|
+
## Accessibility
|
|
47
|
+
|
|
48
|
+
| Use | Result |
|
|
49
|
+
|---|---|
|
|
50
|
+
| No `label` (inside a labeled Button / IconButton) | `aria-hidden="true"` — screen readers skip. |
|
|
51
|
+
| With `label` (standalone) | `role="img"` + `aria-label` + SVG `<title>`. |
|
|
52
|
+
|
|
53
|
+
Inside `<IconButton aria-label="Edit">` the icon is decorative — don't set `label` on the Icon.
|
|
54
|
+
|
|
55
|
+
For standalone icons (status indicators, decorative bullets that convey meaning), pass `label`.
|
|
56
|
+
|
|
57
|
+
## Examples
|
|
58
|
+
|
|
59
|
+
**Inside a Button:**
|
|
60
|
+
```tsx
|
|
61
|
+
<Button startIcon={IconPlus}>New project</Button>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`startIcon` accepts the bare Tabler component — Button wraps it in `<Icon>` and provides size via IconProvider. You don't need to wrap manually.
|
|
65
|
+
|
|
66
|
+
**Inside an IconButton (requires `<Icon>` wrapper):**
|
|
67
|
+
```tsx
|
|
68
|
+
<IconButton
|
|
69
|
+
icon={<Icon icon={IconEdit} />}
|
|
70
|
+
variant="ghost"
|
|
71
|
+
aria-label="Edit item"
|
|
72
|
+
/>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
IconButton's `icon` prop expects a React element, so wrap in `<Icon icon={...} />`. Size flows from the button via IconProvider.
|
|
76
|
+
|
|
77
|
+
**Standalone with label (a11y):**
|
|
78
|
+
```tsx
|
|
79
|
+
<Icon icon={IconAlertCircle} label="Warning" size="lg" />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Renders `role="img"` with `aria-label="Warning"` — screen readers announce it.
|
|
83
|
+
|
|
84
|
+
**Loading spinner via state:**
|
|
85
|
+
```tsx
|
|
86
|
+
<Icon icon={IconRefresh} state="loading" />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`state="loading"` renders a bare Spinner regardless of the `icon` prop. Use for inline loading affordances.
|
|
90
|
+
|
|
91
|
+
**Success / error feedback:**
|
|
92
|
+
```tsx
|
|
93
|
+
<Icon icon={IconCheck} state="success" />
|
|
94
|
+
<Icon icon={IconX} state="error" />
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`state="success"` / `state="error"` render animated checkmark / cross via Framer Motion. Respects `prefers-reduced-motion`.
|
|
98
|
+
|
|
99
|
+
**Path-draw animation (check / X / circle-check only):**
|
|
100
|
+
```tsx
|
|
101
|
+
<Icon icon={IconCheck} animate="draw" />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Draws the stroke progressively (0.35s easeOut). Works with `IconCheck`, `IconX`, and `IconCircleCheck` only — other icons fall back to static render.
|
|
105
|
+
|
|
106
|
+
**Spin animation:**
|
|
107
|
+
```tsx
|
|
108
|
+
<Icon icon={IconLoader} animate="spin" />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For an actual loading state, prefer `state="loading"` — it renders the dedicated Spinner.
|
|
112
|
+
|
|
113
|
+
**Inside a row, auto-sized from input:**
|
|
114
|
+
```tsx
|
|
115
|
+
<Input
|
|
116
|
+
size="lg"
|
|
117
|
+
startSection={<Icon icon={IconSearch} />} {/* size: 'md' from IconProvider */}
|
|
118
|
+
placeholder="Search"
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Input's IconProvider sets size by input size: `xs` / `sm` input → `sm` icon, `md` / `lg` input → `md` icon. Don't pass `size` on the nested Icon.
|
|
123
|
+
|
|
124
|
+
**Status badge with custom-colored icon:**
|
|
125
|
+
```tsx
|
|
126
|
+
<Stack direction="horizontal" gap="ds-02" align="center">
|
|
127
|
+
<Icon icon={IconCircleFilled} size="xs" className="text-success-9" />
|
|
128
|
+
<Text variant="body-sm">Online</Text>
|
|
129
|
+
</Stack>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For most status displays prefer `<StatusDot>` — purpose-built. Use this pattern only when you need a specific icon shape.
|
|
133
|
+
|
|
134
|
+
## Composability
|
|
135
|
+
|
|
136
|
+
- **IconProvider cascade:** Button, IconButton, Badge, Input (start/endSection), NumberInput, IconGroup all wrap children in an `IconProvider`. Nested `<Icon>` reads size + stroke automatically. Don't pass `size` on those nested Icons.
|
|
137
|
+
- **Explicit props override context.** When you genuinely need a different size, pass `size` on the Icon — it wins.
|
|
138
|
+
- **State overrides animate.** When both are set, `state` wins. `state="loading"` renders a Spinner; `state="success"` / `state="error"` render path-drawn animations.
|
|
139
|
+
- **Reduced motion respected.** All animations fall back to static render under `prefers-reduced-motion: reduce`.
|
|
140
|
+
|
|
141
|
+
See `foundations/icons.md` for the icon-system overview (Tabler-only rationale, IconProvider tree, custom icons), `foundations/motion.md` for animation tokens.
|
|
142
|
+
|
|
143
|
+
## Rules
|
|
144
|
+
|
|
145
|
+
- Use Tabler icons only. See `foundations/icons.md` for the rationale and registry.
|
|
146
|
+
- Inside Button / IconButton / Badge slots, don't pass `size` on the nested Icon — IconProvider sets it.
|
|
147
|
+
- For standalone icons that convey meaning (not in a labeled button), pass `label` — without it, screen readers skip the icon.
|
|
148
|
+
- Inside `<IconButton aria-label="...">`, the Icon is decorative — don't set `label` on the Icon (would duplicate the announcement).
|
|
149
|
+
- For loading affordances, use `state="loading"` — it renders the dedicated Spinner.
|
|
150
|
+
- `animate="draw"` only works for `IconCheck`, `IconX`, `IconCircleCheck`. Other icons silently fall back to static.
|
|
151
|
+
- Don't wrap Icon in `<button>` — use `<IconButton>`.
|
|
152
|
+
- Stroke weight scales with size — only override `stroke` when the default truly feels off, not as a stylistic preference.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Input
|
|
2
|
+
|
|
3
|
+
Single-line text entry. Use instead of `<input type="text" | "email" | "url" | "tel" | "search" | "password">`.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Input } from '@devalok/shilp-sutra/ui/input'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
- Any single-line text capture: email, URL, search, name, password, phone.
|
|
12
|
+
- Multi-line input? Use `<Textarea>`.
|
|
13
|
+
- Number-only with steppers? Use `<NumberInput>`.
|
|
14
|
+
- One-time-code / PIN entry? Use `<InputOTP>`.
|
|
15
|
+
- Searchable list with selection? Use `<Combobox>` or `<Autocomplete>`.
|
|
16
|
+
|
|
17
|
+
Wrap in a `<FormField>` for automatic a11y wiring (state, `aria-describedby`, `aria-invalid`, `aria-required`).
|
|
18
|
+
|
|
19
|
+
## Sizes
|
|
20
|
+
|
|
21
|
+
| Size | Pixel height | When |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `xs` | 28 | Toolbar / inline filters. |
|
|
24
|
+
| `sm` | 32 | Dense forms. |
|
|
25
|
+
| `md` (default) | 40 | Standard. |
|
|
26
|
+
| `lg` | 48 | Marketing / spacious layouts. |
|
|
27
|
+
|
|
28
|
+
All sizes use 14 px text — sizes scale height + padding, not font.
|
|
29
|
+
|
|
30
|
+
## States
|
|
31
|
+
|
|
32
|
+
| State | Visual | Use |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `default` (default) | Subtle border. | Resting. |
|
|
35
|
+
| `error` | Red border + `aria-invalid="true"`. | Validation failure. |
|
|
36
|
+
| `warning` | Amber border. | Soft caution (caps lock on, weak password). |
|
|
37
|
+
| `success` | Green border. | Inline confirmation. |
|
|
38
|
+
|
|
39
|
+
## Props
|
|
40
|
+
|
|
41
|
+
| Prop | Type | Notes |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `size` | `'xs'\|'sm'\|'md'\|'lg'` | Default `md`. Excludes the HTML native `size` attribute. |
|
|
44
|
+
| `state` | `'default'\|'error'\|'warning'\|'success'` | Inherits from `<FormField>` context if present. |
|
|
45
|
+
| `startSection` | `ReactNode` | Leading slot — icon (React element) or label string. |
|
|
46
|
+
| `endSection` | `ReactNode` | Trailing slot — icon or label. |
|
|
47
|
+
| `startSectionType` | `'icon'\|'label'` | Auto-inferred from content type. Override only when needed. |
|
|
48
|
+
| `endSectionType` | `'icon'\|'label'` | Auto-inferred. |
|
|
49
|
+
| `startSectionClickable` | `boolean` | Enables pointer events on the section (e.g. clear button in slot). |
|
|
50
|
+
| `endSectionClickable` | `boolean` | Same for trailing slot. |
|
|
51
|
+
| `wrapperClassName` | `string` | Classes on the wrapper div (border, bg, ring live here). |
|
|
52
|
+
| `className` | `string` | Classes on the raw `<input>` element (transparent — text only). |
|
|
53
|
+
|
|
54
|
+
Plus all standard HTML input attributes except the native `size` (renamed to mean visual sizing).
|
|
55
|
+
|
|
56
|
+
## Section type inference
|
|
57
|
+
|
|
58
|
+
| Content | Renders as |
|
|
59
|
+
|---|---|
|
|
60
|
+
| React element (`<Icon icon={IconMail} />`) | `'icon'` — fixed-width centered cell. |
|
|
61
|
+
| String (`"https://"`, `".00"`) | `'label'` — tinted bg + border separator. |
|
|
62
|
+
|
|
63
|
+
Override via `startSectionType` / `endSectionType` when the inference is wrong.
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
**Standard, with leading icon:**
|
|
68
|
+
```tsx
|
|
69
|
+
<Input
|
|
70
|
+
type="email"
|
|
71
|
+
placeholder="you@example.com"
|
|
72
|
+
startSection={<Icon icon={IconMail} />}
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**URL prefix (label section):**
|
|
77
|
+
```tsx
|
|
78
|
+
<Input
|
|
79
|
+
startSection="https://"
|
|
80
|
+
placeholder="example.com"
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Currency with prefix icon + suffix label:**
|
|
85
|
+
```tsx
|
|
86
|
+
<Input
|
|
87
|
+
startSection={<Icon icon={IconCurrencyDollar} />}
|
|
88
|
+
endSection=".00"
|
|
89
|
+
placeholder="0"
|
|
90
|
+
inputMode="decimal"
|
|
91
|
+
/>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Clearable search (clickable trailing slot):**
|
|
95
|
+
```tsx
|
|
96
|
+
<Input
|
|
97
|
+
placeholder="Search projects"
|
|
98
|
+
startSection={<Icon icon={IconSearch} />}
|
|
99
|
+
endSection={
|
|
100
|
+
<button type="button" onClick={() => setValue('')} aria-label="Clear">
|
|
101
|
+
<Icon icon={IconX} />
|
|
102
|
+
</button>
|
|
103
|
+
}
|
|
104
|
+
endSectionClickable
|
|
105
|
+
value={value}
|
|
106
|
+
onChange={(e) => setValue(e.target.value)}
|
|
107
|
+
/>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Inside a FormField (auto-wired a11y):**
|
|
111
|
+
```tsx
|
|
112
|
+
<FormField state="error">
|
|
113
|
+
<Label htmlFor="email" required>Email</Label>
|
|
114
|
+
<Input id="email" type="email" />
|
|
115
|
+
<FormHelperText>Enter a valid work email.</FormHelperText>
|
|
116
|
+
</FormField>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The Input picks up `state="error"`, `aria-describedby` (linked to FormHelperText), `aria-invalid`, and `aria-required` from FormField context automatically.
|
|
120
|
+
|
|
121
|
+
**Password with reveal toggle:**
|
|
122
|
+
```tsx
|
|
123
|
+
const [visible, setVisible] = useState(false)
|
|
124
|
+
|
|
125
|
+
<Input
|
|
126
|
+
type={visible ? 'text' : 'password'}
|
|
127
|
+
placeholder="Password"
|
|
128
|
+
endSection={
|
|
129
|
+
<button type="button" onClick={() => setVisible((v) => !v)} aria-label={visible ? 'Hide password' : 'Show password'}>
|
|
130
|
+
<Icon icon={visible ? IconEyeOff : IconEye} />
|
|
131
|
+
</button>
|
|
132
|
+
}
|
|
133
|
+
endSectionClickable
|
|
134
|
+
/>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Composability
|
|
138
|
+
|
|
139
|
+
- **FormField:** Inside a `<FormField>`, Input auto-reads `state`, `aria-describedby`, `aria-invalid`, `aria-required` from context. Explicit props override.
|
|
140
|
+
- **IconProvider:** Icons in `startSection` / `endSection` are auto-sized via the input's `size`. Don't pass `size` on the nested `<Icon>`.
|
|
141
|
+
- **Container-first architecture:** Border, background, and focus ring live on the wrapper div, not the input element. Style overrides go through `wrapperClassName`, not `className`. The raw `<input>` is transparent.
|
|
142
|
+
|
|
143
|
+
See `foundations/color.md` for state-color tokens, `foundations/icons.md` for the IconProvider cascade.
|
|
144
|
+
|
|
145
|
+
## Rules
|
|
146
|
+
|
|
147
|
+
- Pair every Input with a `<Label htmlFor="x" />` and matching `<Input id="x" />`. FormField does NOT auto-wire labels.
|
|
148
|
+
- Use `wrapperClassName` for border / bg / ring overrides. `className` only changes the raw input text styling.
|
|
149
|
+
- Don't pass `size` on `<Icon>` inside a section — IconProvider sets it.
|
|
150
|
+
- Don't use the HTML native `size` attribute — it's excluded. Use CSS width or the size prop.
|
|
151
|
+
- For interactive sections (clear button, password toggle), set `startSectionClickable` / `endSectionClickable`. Without it, the slot is `pointer-events-none`.
|
|
152
|
+
- For status / validation, set `state` — it sets `aria-invalid` automatically when `state="error"`.
|
|
153
|
+
- Don't use the removed `startIcon` / `endIcon` props — they were removed in 0.38. Use `startSection` / `endSection`.
|
|
154
|
+
- Prefer FormField wrapping for any input with a label + helper — manual a11y wiring is error-prone.
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Components — catalog & decision trees
|
|
2
|
+
|
|
3
|
+
Catalog of every major component. Use this file to pick the right component before reaching for raw HTML. Per-component deep guides live alongside this file.
|
|
4
|
+
|
|
5
|
+
## Decision tree — actions
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
User wants to commit / cancel / submit?
|
|
9
|
+
→ primary CTA (1 per region) → <Button variant="solid" color="accent">
|
|
10
|
+
→ secondary action → <Button variant="soft"> (NOT outline — see preference)
|
|
11
|
+
→ tertiary / dismissive → <Button variant="ghost">
|
|
12
|
+
→ destructive action → <Button variant="solid" color="error">
|
|
13
|
+
→ link-styled action → <Button variant="link">
|
|
14
|
+
|
|
15
|
+
Action has a side-menu / overflow?
|
|
16
|
+
→ <SplitButton> — primary + adjacent dropdown trigger.
|
|
17
|
+
|
|
18
|
+
Action is icon-only?
|
|
19
|
+
→ <IconButton> — same as Button, square aspect, aria-label required.
|
|
20
|
+
|
|
21
|
+
Group of related actions?
|
|
22
|
+
→ <ButtonGroup> — attached or not. Propagates disabled / size.
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Decision tree — input
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Single-line text?
|
|
29
|
+
→ <Input> — type="text"/"email"/"password"/"number"/"tel"/"url"/"search"
|
|
30
|
+
→ For search specifically: <SearchInput> (has clear button + icon)
|
|
31
|
+
→ For OTP code: <InputOTP>
|
|
32
|
+
|
|
33
|
+
Multi-line text?
|
|
34
|
+
→ <Textarea>
|
|
35
|
+
|
|
36
|
+
Pick one from a list?
|
|
37
|
+
→ static list ≤7 items → <Select>
|
|
38
|
+
→ static list >7 items → <Combobox> (searchable)
|
|
39
|
+
→ async / large list → <Autocomplete>
|
|
40
|
+
→ enum of 2–4 options → <SegmentedControl> (always-visible) or <Tabs> (if scoping a section)
|
|
41
|
+
|
|
42
|
+
Pick many?
|
|
43
|
+
→ list with checkboxes → <Checkbox> per item
|
|
44
|
+
→ compact pills → <ToggleGroup type="multiple">
|
|
45
|
+
→ searchable → <Combobox multiple>
|
|
46
|
+
|
|
47
|
+
Boolean?
|
|
48
|
+
→ <Switch> (settings-style on/off) — instant action
|
|
49
|
+
→ <Checkbox> (form field) — confirmed-on-submit
|
|
50
|
+
→ <Toggle> (button-like toggled state)
|
|
51
|
+
|
|
52
|
+
Range / scalar?
|
|
53
|
+
→ <Slider> (single or multi-thumb range)
|
|
54
|
+
→ <NumberInput> (precise number with steppers)
|
|
55
|
+
|
|
56
|
+
Date / time?
|
|
57
|
+
→ <DatePicker> (single date)
|
|
58
|
+
→ <DateRangePicker> (range)
|
|
59
|
+
→ <DateTimePicker> (date + time)
|
|
60
|
+
|
|
61
|
+
Color?
|
|
62
|
+
→ <ColorInput> (popover swatch + manual hex)
|
|
63
|
+
→ <ColorSwatch> (display-only)
|
|
64
|
+
|
|
65
|
+
File?
|
|
66
|
+
→ <FileUpload> (drag-drop + click)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Decision tree — feedback
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Permanent inline message?
|
|
73
|
+
→ <Alert> — page-level notice (info / success / warning / error)
|
|
74
|
+
→ <Banner> — full-bleed page banner (system status, announcements)
|
|
75
|
+
→ <InfoBlock> — within a form / card (helper context)
|
|
76
|
+
|
|
77
|
+
Status of an item?
|
|
78
|
+
→ <Badge> — pill label (status / tag)
|
|
79
|
+
→ <StatusBadge> — colored dot + label (discriminated union: status="online"/"away"/...)
|
|
80
|
+
→ <StatusDot> — just the colored dot
|
|
81
|
+
|
|
82
|
+
Temporary notification?
|
|
83
|
+
→ toast.success / error / warning / info (imperative) — must have <Toaster /> mounted
|
|
84
|
+
|
|
85
|
+
Loading / pending?
|
|
86
|
+
→ <Spinner> — generic
|
|
87
|
+
→ <ProgressRing> — determinate ring
|
|
88
|
+
→ <Progress> — linear bar
|
|
89
|
+
→ <Skeleton> — content placeholder shimmer
|
|
90
|
+
→ <PageSkeletons.*> — pre-built page-level skeletons
|
|
91
|
+
→ <GlobalLoading> — app-wide loading overlay
|
|
92
|
+
|
|
93
|
+
Empty state?
|
|
94
|
+
→ <EmptyState> — icon + heading + body + action
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Decision tree — overlays
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Confirm a destructive action? → <AlertDialog> or <ConfirmDialog>
|
|
101
|
+
Show a form / detailed flow? → <Dialog> (auto fullScreen on mobile)
|
|
102
|
+
Show a side panel? → <Sheet> (auto bottom-drawer on mobile)
|
|
103
|
+
Show a small floating popup on click? → <Popover>
|
|
104
|
+
Show a small floating popup on hover? → <HoverCard>
|
|
105
|
+
Show a label on hover? → <Tooltip>
|
|
106
|
+
Show a menu from a button? → <DropdownMenu>
|
|
107
|
+
Show a menu from right-click? → <ContextMenu>
|
|
108
|
+
Show a menu in a toolbar? → <Menubar>
|
|
109
|
+
Show a command palette (cmd+K)? → <AppCommandPalette> (shell) or <CommandPalette> (composed)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Decision tree — navigation
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
Top of every page?
|
|
116
|
+
→ <TopBar> (shell)
|
|
117
|
+
|
|
118
|
+
Side nav (product)?
|
|
119
|
+
→ <AppSidebar> (shell) — collapsible, with sections, footer
|
|
120
|
+
|
|
121
|
+
Tabs within a page?
|
|
122
|
+
→ <Tabs> — horizontal default
|
|
123
|
+
→ <Tabs orientation="vertical"> — side-nav within a card
|
|
124
|
+
|
|
125
|
+
Pages within a flow?
|
|
126
|
+
→ <Stepper> — multi-step wizard, optional clickable
|
|
127
|
+
|
|
128
|
+
Breadcrumb trail?
|
|
129
|
+
→ <Breadcrumb>
|
|
130
|
+
|
|
131
|
+
Pagination?
|
|
132
|
+
→ <Pagination>
|
|
133
|
+
|
|
134
|
+
Mobile bottom nav?
|
|
135
|
+
→ <BottomNavbar>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Decision tree — layout
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
Page wrapper?
|
|
142
|
+
→ <Container size="..."> — max-width constraints (sm / md / lg / xl / 2xl / full)
|
|
143
|
+
|
|
144
|
+
Vertical / horizontal stack?
|
|
145
|
+
→ <Stack direction="col|row" gap="ds-*">
|
|
146
|
+
|
|
147
|
+
A card / panel?
|
|
148
|
+
→ <Card> — surface-raised + shadow-raised
|
|
149
|
+
→ <Card variant="..."> — tinted by color prop
|
|
150
|
+
|
|
151
|
+
A grid?
|
|
152
|
+
→ use native CSS grid utilities (grid grid-cols-12 gap-ds-05) — no kit primitive for this
|
|
153
|
+
|
|
154
|
+
Aspect-ratio box?
|
|
155
|
+
→ <AspectRatio ratio={16/9}>
|
|
156
|
+
|
|
157
|
+
Divider?
|
|
158
|
+
→ <Separator> (horizontal default; orientation="vertical")
|
|
159
|
+
|
|
160
|
+
Collapsible section?
|
|
161
|
+
→ <Collapsible> (single)
|
|
162
|
+
→ <Accordion> (group, single-open or multi-open)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Decision tree — data display
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
Tabular data?
|
|
169
|
+
→ <Table> — simple, hand-roll rows/cells
|
|
170
|
+
→ <DataTable> — full-featured (sort, paginate, select, filter, export, density, mobile-card)
|
|
171
|
+
|
|
172
|
+
Key-value display?
|
|
173
|
+
→ <StatCard> — single big stat
|
|
174
|
+
→ 4 StatCards in a row → use <Stack direction="row" gap="ds-05">
|
|
175
|
+
|
|
176
|
+
Activity / event log?
|
|
177
|
+
→ <ActivityFeed> — vertical timeline with dots
|
|
178
|
+
|
|
179
|
+
User avatars?
|
|
180
|
+
→ <Avatar> — single
|
|
181
|
+
→ <AvatarGroup> — stack with overflow
|
|
182
|
+
|
|
183
|
+
A list of selectable members?
|
|
184
|
+
→ <MemberPicker>
|
|
185
|
+
|
|
186
|
+
A chart?
|
|
187
|
+
→ BarChart / LineChart / AreaChart / PieChart / RadarChart / GaugeChart / Sparkline (from /ui/charts)
|
|
188
|
+
|
|
189
|
+
Code?
|
|
190
|
+
→ <Code> inline
|
|
191
|
+
→ <MarkdownViewer> for rendered markdown
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Component catalog by category
|
|
195
|
+
|
|
196
|
+
### Actions
|
|
197
|
+
| Component | Subpath | Purpose |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| Button | `/ui/button` | Primary action element. |
|
|
200
|
+
| IconButton | `/ui/icon-button` | Icon-only square button. |
|
|
201
|
+
| ButtonGroup | `/ui/button-group` | Visually attached group. |
|
|
202
|
+
| SplitButton | `/ui/split-button` | Action + dropdown. |
|
|
203
|
+
| OAuthButton | `/ui/oauth-button` | Brand-aware social login button. |
|
|
204
|
+
| Toggle | `/ui/toggle` | Toggled-state button. |
|
|
205
|
+
| ToggleGroup | `/ui/toggle-group` | Group of toggles (single / multiple). |
|
|
206
|
+
| Link | `/ui/link` | Themed anchor. |
|
|
207
|
+
|
|
208
|
+
### Inputs
|
|
209
|
+
| Component | Subpath |
|
|
210
|
+
|---|---|
|
|
211
|
+
| Input | `/ui/input` |
|
|
212
|
+
| Textarea | `/ui/textarea` |
|
|
213
|
+
| Select | `/ui/select` |
|
|
214
|
+
| Combobox | `/ui/combobox` |
|
|
215
|
+
| Autocomplete | `/ui/autocomplete` |
|
|
216
|
+
| SearchInput | `/ui/search-input` |
|
|
217
|
+
| NumberInput | `/ui/number-input` |
|
|
218
|
+
| InputOTP | `/ui/input-otp` |
|
|
219
|
+
| Checkbox | `/ui/checkbox` |
|
|
220
|
+
| Radio | `/ui/radio` |
|
|
221
|
+
| Switch | `/ui/switch` |
|
|
222
|
+
| Slider | `/ui/slider` |
|
|
223
|
+
| FileUpload | `/ui/file-upload` |
|
|
224
|
+
| ColorInput | `/ui/color-input` |
|
|
225
|
+
| ColorSwatch | `/ui/color-swatch` |
|
|
226
|
+
| DatePicker | `/composed/date-picker` |
|
|
227
|
+
| Label | `/ui/label` |
|
|
228
|
+
| Form / FormField | `/ui/form` |
|
|
229
|
+
| SegmentedControl | `/ui/segmented-control` |
|
|
230
|
+
|
|
231
|
+
### Overlays
|
|
232
|
+
| Component | Subpath |
|
|
233
|
+
|---|---|
|
|
234
|
+
| Dialog | `/ui/dialog` |
|
|
235
|
+
| AlertDialog | `/ui/alert-dialog` |
|
|
236
|
+
| Sheet | `/ui/sheet` |
|
|
237
|
+
| Popover | `/ui/popover` |
|
|
238
|
+
| HoverCard | `/ui/hover-card` |
|
|
239
|
+
| Tooltip | `/ui/tooltip` |
|
|
240
|
+
| DropdownMenu | `/ui/dropdown-menu` |
|
|
241
|
+
| ContextMenu | `/ui/context-menu` |
|
|
242
|
+
| Menubar | `/ui/menubar` |
|
|
243
|
+
|
|
244
|
+
### Feedback
|
|
245
|
+
| Component | Subpath |
|
|
246
|
+
|---|---|
|
|
247
|
+
| Alert | `/ui/alert` |
|
|
248
|
+
| Banner | `/ui/banner` |
|
|
249
|
+
| Toast / Toaster | `/ui/toast`, `/ui/toaster` |
|
|
250
|
+
| Spinner | `/ui/spinner` |
|
|
251
|
+
| Progress | `/ui/progress` |
|
|
252
|
+
| ProgressRing | `/ui/progress-ring` |
|
|
253
|
+
| Skeleton | `/ui/skeleton` |
|
|
254
|
+
| Badge | `/ui/badge` |
|
|
255
|
+
| StatusBadge | `/composed/status-badge` |
|
|
256
|
+
| StatusDot | `/ui/status-dot` |
|
|
257
|
+
| EmptyState | `/composed/empty-state` |
|
|
258
|
+
|
|
259
|
+
### Layout
|
|
260
|
+
| Component | Subpath |
|
|
261
|
+
|---|---|
|
|
262
|
+
| Container | `/ui/container` |
|
|
263
|
+
| Stack | `/ui/stack` |
|
|
264
|
+
| Card | `/ui/card` |
|
|
265
|
+
| AspectRatio | `/ui/aspect-ratio` |
|
|
266
|
+
| Separator | `/ui/separator` |
|
|
267
|
+
| Accordion | `/ui/accordion` |
|
|
268
|
+
| Collapsible | `/ui/collapsible` |
|
|
269
|
+
|
|
270
|
+
### Navigation
|
|
271
|
+
| Component | Subpath |
|
|
272
|
+
|---|---|
|
|
273
|
+
| Tabs | `/ui/tabs` |
|
|
274
|
+
| Breadcrumb | `/ui/breadcrumb` |
|
|
275
|
+
| Pagination | `/ui/pagination` |
|
|
276
|
+
| Stepper | `/ui/stepper` |
|
|
277
|
+
| NavigationMenu | `/ui/navigation-menu` |
|
|
278
|
+
| Sidebar (AppSidebar) | `/shell/sidebar` |
|
|
279
|
+
| TopBar | `/shell/top-bar` |
|
|
280
|
+
| BottomNavbar | `/shell/bottom-navbar` |
|
|
281
|
+
|
|
282
|
+
### Data display
|
|
283
|
+
| Component | Subpath |
|
|
284
|
+
|---|---|
|
|
285
|
+
| Table | `/ui/table` |
|
|
286
|
+
| DataTable | `/ui/data-table` |
|
|
287
|
+
| StatCard | `/ui/stat-card` |
|
|
288
|
+
| ActivityFeed | `/composed/activity-feed` |
|
|
289
|
+
| Avatar | `/ui/avatar` |
|
|
290
|
+
| AvatarGroup | `/composed/avatar-group` |
|
|
291
|
+
| Text | `/ui/text` |
|
|
292
|
+
| Code | `/ui/code` |
|
|
293
|
+
| Charts (bar / line / area / pie / radar / gauge / sparkline) | `/ui/charts/*` |
|
|
294
|
+
|
|
295
|
+
## Common props across components
|
|
296
|
+
|
|
297
|
+
| Prop | Type | Where |
|
|
298
|
+
|---|---|---|
|
|
299
|
+
| `className` | string | All. Use sparingly. |
|
|
300
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | Button, Input, Select, Card, Alert, Badge, Tabs, Checkbox, Radio, Slider, etc. Not all sizes exist on every component. |
|
|
301
|
+
| `color` | `'accent' \| 'error' \| 'success' \| 'warning' \| 'info' \| 'neutral'` | Button, Badge, Card, Tabs (subset), Alert. |
|
|
302
|
+
| `variant` | varies | Button (`solid|soft|outline|ghost|link`), Card, Alert, Badge, Select, etc. |
|
|
303
|
+
| `disabled` | boolean | All interactive. Propagates from ButtonGroup. |
|
|
304
|
+
| `loading` | boolean | Button, IconButton, OAuthButton, async-aware components. |
|
|
305
|
+
|
|
306
|
+
## Per-component guides
|
|
307
|
+
|
|
308
|
+
See `components/{button|card|input|dialog|badge|select|tabs|toast|form|table|dropdown-menu|popover|text|stack|icon}.md` for prop tables, examples, and rules.
|