@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.
@@ -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.