@devalok/shilp-sutra 0.37.0 → 0.38.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 +67 -0
- package/dist/_chunks/tiptap.js +977 -968
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/composed/index.d.ts +0 -2
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/index.js +5 -6
- package/dist/composed/inline-edit.d.ts.map +1 -1
- package/dist/composed/inline-edit.js +42 -40
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/test-utils/conformance.d.ts +37 -0
- package/dist/test-utils/conformance.d.ts.map +1 -0
- package/dist/ui/alert.d.ts +1 -2
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +1 -27
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/banner.d.ts +3 -5
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +13 -13
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.d.ts +1 -9
- package/dist/ui/input.d.ts.map +1 -1
- package/dist/ui/input.js +26 -27
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/segmented-control.d.ts +1 -1
- package/dist/ui/segmented-control.d.ts.map +1 -1
- package/dist/ui/segmented-control.js +2 -4
- package/dist/ui/segmented-control.js.map +1 -1
- package/docs/components/_header.md +1 -1
- package/docs/components/composed/activity-feed.md +6 -0
- package/docs/components/composed/avatar-group.md +8 -0
- package/docs/components/composed/bulk-action-bar.md +6 -0
- package/docs/components/composed/command-palette.md +7 -0
- package/docs/components/composed/confirm-dialog.md +6 -0
- package/docs/components/composed/content-card.md +6 -0
- package/docs/components/composed/date-picker.md +10 -0
- package/docs/components/composed/deadline-indicator.md +7 -0
- package/docs/components/composed/emoji-picker.md +8 -0
- package/docs/components/composed/empty-state.md +8 -0
- package/docs/components/composed/error-boundary.md +7 -0
- package/docs/components/composed/file-preview.md +8 -0
- package/docs/components/composed/filter-bar.md +8 -0
- package/docs/components/composed/form-section.md +6 -0
- package/docs/components/composed/global-loading.md +6 -0
- package/docs/components/composed/inline-edit.md +8 -0
- package/docs/components/composed/loading-skeleton.md +7 -0
- package/docs/components/composed/markdown-viewer.md +9 -0
- package/docs/components/composed/master-detail.md +7 -0
- package/docs/components/composed/member-picker.md +7 -0
- package/docs/components/composed/multi-select-popover.md +11 -0
- package/docs/components/composed/page-header.md +7 -0
- package/docs/components/composed/page-skeletons.md +10 -0
- package/docs/components/composed/priority-indicator.md +7 -0
- package/docs/components/composed/rich-chat-input.md +12 -0
- package/docs/components/composed/rich-text-editor.md +9 -0
- package/docs/components/composed/schedule-view.md +8 -0
- package/docs/components/composed/simple-tooltip.md +7 -0
- package/docs/components/composed/status-badge.md +10 -0
- package/docs/components/shell/app-command-palette.md +8 -0
- package/docs/components/shell/bottom-navbar.md +12 -0
- package/docs/components/shell/command-registry.md +7 -0
- package/docs/components/shell/link-context.md +15 -0
- package/docs/components/shell/notification-center.md +10 -0
- package/docs/components/shell/notification-preferences.md +7 -0
- package/docs/components/shell/sidebar.md +11 -0
- package/docs/components/shell/top-bar.md +11 -0
- package/docs/components/ui/accordion.md +10 -0
- package/docs/components/ui/alert-dialog.md +10 -1
- package/docs/components/ui/alert.md +13 -2
- package/docs/components/ui/aspect-ratio.md +7 -0
- package/docs/components/ui/autocomplete.md +7 -0
- package/docs/components/ui/avatar.md +10 -0
- package/docs/components/ui/badge-group.md +7 -0
- package/docs/components/ui/badge-indicator.md +7 -0
- package/docs/components/ui/badge.md +12 -0
- package/docs/components/ui/banner.md +10 -1
- package/docs/components/ui/breadcrumb.md +8 -0
- package/docs/components/ui/button-group.md +24 -4
- package/docs/components/ui/button-processing.md +5 -0
- package/docs/components/ui/button.md +9 -0
- package/docs/components/ui/card.md +16 -4
- package/docs/components/ui/charts.md +9 -0
- package/docs/components/ui/chat.md +9 -0
- package/docs/components/ui/checkbox.md +15 -1
- package/docs/components/ui/chip.md +9 -0
- package/docs/components/ui/code.md +7 -0
- package/docs/components/ui/collapsible.md +9 -0
- package/docs/components/ui/color-input.md +8 -0
- package/docs/components/ui/color-swatch.md +7 -0
- package/docs/components/ui/combobox.md +16 -3
- package/docs/components/ui/container.md +11 -0
- package/docs/components/ui/context-menu.md +8 -0
- package/docs/components/ui/data-table-body.md +4 -0
- package/docs/components/ui/data-table-bulk-actions.md +4 -0
- package/docs/components/ui/data-table-card.md +4 -0
- package/docs/components/ui/data-table-context.md +4 -0
- package/docs/components/ui/data-table-header.md +4 -0
- package/docs/components/ui/data-table-pagination.md +4 -0
- package/docs/components/ui/data-table-toolbar.md +7 -0
- package/docs/components/ui/data-table.md +25 -0
- package/docs/components/ui/devalok-grain.md +8 -0
- package/docs/components/ui/dialog.md +10 -0
- package/docs/components/ui/dropdown-menu.md +10 -0
- package/docs/components/ui/file-upload.md +8 -0
- package/docs/components/ui/form.md +21 -0
- package/docs/components/ui/hover-card.md +9 -0
- package/docs/components/ui/icon-button.md +7 -0
- package/docs/components/ui/icon-context.md +7 -0
- package/docs/components/ui/icon-group.md +9 -0
- package/docs/components/ui/icon.md +7 -0
- package/docs/components/ui/input-otp.md +29 -7
- package/docs/components/ui/input.md +11 -2
- package/docs/components/ui/label.md +7 -1
- package/docs/components/ui/link.md +7 -0
- package/docs/components/ui/menubar.md +9 -0
- package/docs/components/ui/navigation-menu.md +9 -0
- package/docs/components/ui/number-input.md +10 -0
- package/docs/components/ui/pagination.md +10 -0
- package/docs/components/ui/popover.md +9 -0
- package/docs/components/ui/progress-ring.md +7 -0
- package/docs/components/ui/progress.md +7 -0
- package/docs/components/ui/radio.md +27 -2
- package/docs/components/ui/search-input.md +8 -0
- package/docs/components/ui/segmented-control.md +21 -6
- package/docs/components/ui/select.md +14 -3
- package/docs/components/ui/separator.md +7 -0
- package/docs/components/ui/sheet.md +10 -0
- package/docs/components/ui/sidebar.md +30 -0
- package/docs/components/ui/skeleton.md +7 -0
- package/docs/components/ui/slider.md +15 -1
- package/docs/components/ui/spinner.md +7 -0
- package/docs/components/ui/split-button.md +11 -0
- package/docs/components/ui/stack.md +8 -0
- package/docs/components/ui/stat-card.md +9 -0
- package/docs/components/ui/status-dot.md +9 -0
- package/docs/components/ui/stepper.md +8 -0
- package/docs/components/ui/switch.md +8 -0
- package/docs/components/ui/table.md +8 -0
- package/docs/components/ui/tabs.md +10 -2
- package/docs/components/ui/text.md +9 -4
- package/docs/components/ui/textarea.md +7 -1
- package/docs/components/ui/toast.md +9 -0
- package/docs/components/ui/toaster.md +8 -0
- package/docs/components/ui/toggle-group.md +13 -4
- package/docs/components/ui/toggle.md +10 -2
- package/docs/components/ui/tooltip.md +11 -1
- package/docs/components/ui/tree-view.md +12 -0
- package/docs/components/ui/visually-hidden.md +7 -0
- package/docs/recipes/customize-brand.md +216 -0
- package/docs/recipes/index.md +51 -0
- package/docs/recipes/install-astro.md +178 -0
- package/docs/recipes/install-next-app-router.md +230 -0
- package/docs/recipes/install-next-pages.md +123 -0
- package/docs/recipes/install-remix.md +171 -0
- package/docs/recipes/install-tanstack-start.md +143 -0
- package/docs/recipes/install-vite.md +170 -0
- package/docs/recipes/server-components.md +209 -0
- package/docs/recipes/troubleshoot.md +217 -0
- package/llms-full.txt +1133 -88
- package/llms.txt +33 -16
- package/package.json +45 -35
- package/dist/composed/responsive-overlay.d.ts +0 -23
- package/dist/composed/responsive-overlay.d.ts.map +0 -1
- package/dist/composed/responsive-overlay.js +0 -40
- package/dist/composed/responsive-overlay.js.map +0 -1
- package/dist/hooks/use-toast.d.ts +0 -17
- package/dist/hooks/use-toast.d.ts.map +0 -1
- package/dist/hooks/use-toast.js +0 -3
- package/dist/tailwind/index.cjs +0 -41
- package/dist/tailwind/index.d.ts +0 -2
- package/dist/tailwind/index.d.ts.map +0 -1
- package/dist/tailwind/index.js +0 -2
- package/dist/tailwind/preset.d.ts +0 -25
- package/dist/tailwind/preset.d.ts.map +0 -1
- package/dist/tailwind/preset.js +0 -17
- package/dist/tailwind/preset.js.map +0 -1
- package/docs/components/composed/responsive-overlay.md +0 -34
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
- Server-safe: No
|
|
5
5
|
- Category: ui
|
|
6
6
|
|
|
7
|
+
## Props
|
|
8
|
+
### SidebarMenuButton
|
|
9
|
+
variant: "default" | "outline"
|
|
10
|
+
size: "sm" | "md" | "lg"
|
|
11
|
+
isActive: boolean (highlights as current nav item)
|
|
12
|
+
tooltip: ReactNode | string (shown when sidebar is collapsed)
|
|
13
|
+
asChild: boolean (render as Slot — common with next/link)
|
|
14
|
+
|
|
7
15
|
## Compound Components
|
|
8
16
|
SidebarProvider (context provider — must wrap everything)
|
|
9
17
|
Sidebar (root panel)
|
|
@@ -32,6 +40,9 @@
|
|
|
32
40
|
## Hook
|
|
33
41
|
useSidebar() => { state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar }
|
|
34
42
|
|
|
43
|
+
## Defaults
|
|
44
|
+
SidebarMenuButton variant="default", size="md"
|
|
45
|
+
|
|
35
46
|
## Example
|
|
36
47
|
```jsx
|
|
37
48
|
<SidebarProvider>
|
|
@@ -59,9 +70,28 @@
|
|
|
59
70
|
</SidebarProvider>
|
|
60
71
|
```
|
|
61
72
|
|
|
73
|
+
## Composability
|
|
74
|
+
The whole Sidebar ecosystem is driven by `SidebarContext` — the Provider owns the expand/collapse state and every descendant reads from it.
|
|
75
|
+
|
|
76
|
+
**Who reads the context:**
|
|
77
|
+
- `Sidebar` — applies collapsed / expanded / off-canvas styles based on `state`
|
|
78
|
+
- `SidebarTrigger` — calls `toggleSidebar()` on click; reflects aria-expanded
|
|
79
|
+
- `SidebarMenuButton` — uses `state === 'collapsed'` to show its `tooltip` (hidden label appears only when sidebar is icon-width)
|
|
80
|
+
- `SidebarInset` — main content area adjusts its left offset based on sidebar width + state
|
|
81
|
+
- `SidebarRail` — invisible hit target on the outer edge for click-to-toggle
|
|
82
|
+
- Any user component that calls `useSidebar()` — full access to open/isMobile/toggle
|
|
83
|
+
|
|
84
|
+
**Desktop vs mobile:** Context tracks `isMobile` via the `use-mobile` hook and branches behavior: on desktop the sidebar collapses to an icon rail; on mobile it becomes an off-canvas drawer controlled by `openMobile`.
|
|
85
|
+
|
|
86
|
+
**Controlled or uncontrolled:** `SidebarProvider` accepts `open` + `onOpenChange` (controlled) or `defaultOpen` (uncontrolled). State is synced to a cookie for cross-route persistence.
|
|
87
|
+
|
|
88
|
+
**Next.js / router integration:** `SidebarMenuButton` with `asChild` wraps any link element (`next/link`, `react-router Link`, plain `<a>`) — it transfers its styling + isActive state to the child while preserving the link's navigation semantics.
|
|
89
|
+
|
|
62
90
|
## Gotchas
|
|
63
91
|
- SidebarProvider MUST wrap both Sidebar and SidebarInset
|
|
64
92
|
- Use SidebarMenuButton for nav items (supports tooltip in collapsed state)
|
|
93
|
+
- `tooltip` is only visible when sidebar is collapsed — providing one doesn't duplicate the visible label
|
|
94
|
+
- Cookie-based state persistence means the sidebar defaults to its prior state on page reload — use `defaultOpen` to override if needed
|
|
65
95
|
|
|
66
96
|
## Changes
|
|
67
97
|
### v0.18.0
|
|
@@ -67,6 +67,13 @@
|
|
|
67
67
|
<SkeletonImage height="h-64" />
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
## Composability
|
|
71
|
+
- Server-safe — can render in RSC trees during server-side loading states.
|
|
72
|
+
- **Pattern:** One SkeletonGroup per load region (wraps with `role="status"` + `aria-busy="true"` + announces the `label`). Inside, compose the individual shape skeletons (Avatar, Text, Button, Chart, Image) to mirror the structure that will appear when loaded.
|
|
73
|
+
- Use LoadingSkeleton (composed) instead for pre-built layouts — CardSkeleton, TableSkeleton, ListSkeleton, BoardSkeleton — or PageSkeletons for full-page placeholders.
|
|
74
|
+
- `animation="none"` disables animation entirely — useful when placed inside components that already have their own load animation.
|
|
75
|
+
- No context cascade — each skeleton is independent. If you want to drive multiple skeletons from one "reduced motion" setting, either set `animation="none"` on each or rely on the `useReducedMotion` hook (shimmer already respects it automatically).
|
|
76
|
+
|
|
70
77
|
## Gotchas
|
|
71
78
|
- shimmer respects prefers-reduced-motion
|
|
72
79
|
- SkeletonGroup adds role="status" and aria-busy="true" — wrap multiple skeletons for a11y
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
- Category: ui
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
|
-
|
|
8
|
+
size: "sm" | "md" | "lg" (track height and thumb dimensions)
|
|
9
|
+
color: "accent" | "success" | "warning" | "error" (thumb border + focus ring color)
|
|
10
|
+
(plus standard Radix Slider props: value, onValueChange, defaultValue, min, max, step, aria-label)
|
|
11
|
+
|
|
12
|
+
## Defaults
|
|
13
|
+
size="md", color="accent"
|
|
9
14
|
|
|
10
15
|
## Example
|
|
11
16
|
```jsx
|
|
@@ -13,9 +18,18 @@
|
|
|
13
18
|
<Slider defaultValue={[25, 75]} max={100} step={1} /> {/* range slider */}
|
|
14
19
|
```
|
|
15
20
|
|
|
21
|
+
## Composability
|
|
22
|
+
- Radix Slider primitive — keyboard navigation (arrow keys, Home/End, PageUp/PageDown) pre-wired.
|
|
23
|
+
- **Value is always an array** — single-thumb: `[50]`; range: `[25, 75]`. Don't pass a plain number.
|
|
24
|
+
- **Multi-thumb range:** Pass `[start, end]` — renders two thumbs that can cross each other by default. Use `minStepsBetweenThumbs` to enforce a gap.
|
|
25
|
+
- **FormField:** Slider does NOT auto-consume FormField state. No validation UX — sliders usually don't need it (values are always valid by construction).
|
|
26
|
+
- **No label pairing via Label** — use `aria-label` or `aria-labelledby` directly on the Slider. The thumb is the focusable/labeled element.
|
|
27
|
+
- Not portal-rendered — inline; overflow rules of parents apply.
|
|
28
|
+
|
|
16
29
|
## Gotchas
|
|
17
30
|
- value is number[] (array), not a single number
|
|
18
31
|
- Multi-thumb: Pass array `defaultValue={[25, 75]}` for range sliders — renders one thumb per value
|
|
32
|
+
- Slider does NOT auto-consume FormField — sliders don't have validation state visuals by design
|
|
19
33
|
|
|
20
34
|
## Changes
|
|
21
35
|
### v0.18.0
|
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
<Spinner variant="bare" /> {/* uses currentColor, for embedding in buttons */}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Composability
|
|
28
|
+
- **Prefer Button's `loading` prop** for inline button spinners — Button's integration is automatic (disables, sets aria-busy, positions the spinner). Manual Spinner inside Button is more work for no gain.
|
|
29
|
+
- **`variant="bare"`** uses `currentColor` — drop it into any surface (button, toolbar, badge, icon group) and it picks up the parent's text color automatically.
|
|
30
|
+
- **State transitions:** `spinning → success → idle` / `spinning → error → idle`. Use the state machine for async operation feedback (the success checkmark, error X animate in). Pair with `onComplete` to trigger next-step logic after the transition.
|
|
31
|
+
- **delay for flicker prevention:** Set `delay={150}` so very fast operations don't flash a spinner. The spinner mounts only after the delay elapses — if the operation completes first, the user never sees it.
|
|
32
|
+
- **Icon.state="loading" uses Spinner internally** — same underlying component. If you're inside an Icon context, prefer `<Icon state="loading" />` for consistent sizing.
|
|
33
|
+
|
|
27
34
|
## Gotchas
|
|
28
35
|
- Renders role="status" with sr-only "Loading..." text — no need for aria-label
|
|
29
36
|
- Button has built-in loading prop — prefer that over manual Spinner composition
|
|
@@ -35,6 +35,17 @@ import { SplitButton } from '@devalok/shilp-sutra'
|
|
|
35
35
|
| dropdownLabel | string | 'More options' | aria-label for trigger |
|
|
36
36
|
| dropdownIcon | ReactNode | chevron-down | Custom trigger icon |
|
|
37
37
|
|
|
38
|
+
## Composability
|
|
39
|
+
- **Two-in-one button:** visually unified `[Action | ▼]` with the left half being the primary click and the right half opening a dropdown. Use for actions that have a most-common choice plus alternatives (Save vs. Save-As-Draft, Send vs. Schedule).
|
|
40
|
+
- **Built on Button + Popover internally** — inherits Button's variant/color/size vocabulary and Popover's placement prop (`top-end` default works for most top-of-page toolbars).
|
|
41
|
+
- **Dropdown content is consumer-provided** — pass any JSX via `dropdownContent` (typically a DropdownMenu, list of actions, a custom panel, or a small form). Don't try to shove a full-featured menu into the chevron; keep it focused on 2–5 alternatives.
|
|
42
|
+
- **ButtonGroup compatibility:** Put SplitButton inside a `<ButtonGroup>` — it inherits variant/color/size from the group context just like Button does. Position-aware corners work too.
|
|
43
|
+
- **Controlled dropdown:** Pass `open` + `onOpenChange` for controlled state; omit for uncontrolled. Useful when the dropdown must close programmatically after a selection.
|
|
44
|
+
|
|
45
|
+
## Gotchas
|
|
46
|
+
- Always provide `dropdownLabel` (aria-label on the chevron trigger) — defaults to "More options" but context-specific labels are better
|
|
47
|
+
- `triggerSide="left"` flips the chevron to the left — rare, but useful for RTL layouts or when the primary action is the secondary emphasis
|
|
48
|
+
|
|
38
49
|
## Changes
|
|
39
50
|
|
|
40
51
|
### v0.33.0
|
|
@@ -23,6 +23,14 @@
|
|
|
23
23
|
</Stack>
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
## Composability
|
|
27
|
+
- **Server-safe layout primitive.** Nothing to hydrate — works anywhere.
|
|
28
|
+
- **Pattern:** Stack wraps child elements in a flex container. Swap between vertical/horizontal without rewriting the child layout.
|
|
29
|
+
- **Polymorphic via `as`:** Use `as="ul"` / `as="ol"` for list semantics with flex styling; `as="section"` for major page divisions; etc.
|
|
30
|
+
- **gap is design-system tokenized** — use token strings (`"ds-04"`) or numeric shortcuts (`4` → `"ds-04"`). Raw numbers map 1:1 to the `ds-0N` token set.
|
|
31
|
+
- **Responsive direction:** Not built in — for responsive direction changes use Tailwind's `flex-col md:flex-row` directly on a plain div, or wrap multiple Stacks with display-toggling.
|
|
32
|
+
- Container vs Stack: Container centers + caps width; Stack arranges children. Compose them: `<Container><Stack>...</Stack></Container>`.
|
|
33
|
+
|
|
26
34
|
## Gotchas
|
|
27
35
|
- "row" and "column" are aliases for "horizontal" and "vertical"
|
|
28
36
|
- gap accepts both token strings and numeric values
|
|
@@ -47,6 +47,15 @@
|
|
|
47
47
|
/>
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
## Composability
|
|
51
|
+
- **High-density metric card** — optimized for dashboards. Everything optional except `value`. Mix and match features (delta, sparkline, progress, secondary label, footer) per metric's needs.
|
|
52
|
+
- **Router integration via href:** Internally uses `LinkContext` to resolve framework-specific Link components (Next.js, react-router). Set `href` in a LinkProvider-wrapped tree to get seamless client-side navigation without custom asChild wiring.
|
|
53
|
+
- **Interactive modes:** `onClick` makes the entire card a button; `href` makes it a link. Mutually exclusive — href wins if both are set.
|
|
54
|
+
- **Accent bar semantic:** Use `accent` to signal metric health at a glance (success for positive, warning for at-risk, error for over-target). Combine with delta.direction for layered emphasis.
|
|
55
|
+
- **Sparkline:** Pure SVG, lightweight — no chart library. For rich charts use Chart components. Minimum 2 data points.
|
|
56
|
+
- **Icon auto-sizing:** Accepts `ComponentType<{ className }>` OR `ReactNode`. The component prop (e.g. `icon={IconBolt}`) is preferred — icon is rendered at a consistent size.
|
|
57
|
+
- **Loading state:** `loading={true}` renders the full card skeleton — use during initial data fetch.
|
|
58
|
+
|
|
50
59
|
## Gotchas
|
|
51
60
|
- delta.direction "up" = green, "down" = red, "neutral" = grey
|
|
52
61
|
- `label` and `title` are aliases — use either, not both
|
|
@@ -21,6 +21,15 @@
|
|
|
21
21
|
<StatusDot status="warning" size="lg" label="Elevated load" />
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Composability
|
|
25
|
+
- **Server-safe presentational dot** — simple status indicator, pairs with inline text.
|
|
26
|
+
- **Status semantics map to color:** healthy=success, warning=warning, critical=error, neutral=muted surface, inactive=dimmed. The pulse animation calls attention to "healthy" by default (active presence); you can flip it for other statuses by setting pulse explicitly.
|
|
27
|
+
- **StatusDot vs BadgeIndicator vs StatusBadge:**
|
|
28
|
+
- StatusDot = tiny presence/status indicator with optional inline label (e.g. "Service online")
|
|
29
|
+
- BadgeIndicator = overlay on another element (notification dot on a bell icon)
|
|
30
|
+
- StatusBadge (composed) = full pill-style badge with colored bg and label text (e.g. ticket status)
|
|
31
|
+
- **Label composability:** If you pass `label`, it renders inline after the dot. Use `labelClassName` for custom typography (e.g. font-mono for status codes).
|
|
32
|
+
|
|
24
33
|
## Gotchas
|
|
25
34
|
- The `pulse` prop auto-enables for "healthy" status — pass `pulse={false}` to suppress
|
|
26
35
|
- Status type is exported as `StatusDotStatus` if you need it in consumer code
|
|
@@ -37,8 +37,16 @@
|
|
|
37
37
|
</Stepper>
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
## Composability
|
|
41
|
+
- `Stepper` passes `activeStep` + `orientation` + each step's index down to every `Step` child via `StepperContext`. Each Step derives its own status (completed / active / pending) from its position vs `activeStep`.
|
|
42
|
+
- Step index is assigned by position in children — order matters. Don't conditionally render Steps via `&&` or `.filter()`; it shifts the indices and breaks the active highlight.
|
|
43
|
+
- `StepperContent` is separate from `Stepper` — it's the animated panel surface that shows one child per step index. Pass the same `activeStep` value to both.
|
|
44
|
+
- `orientation="vertical"` swaps the Step layout (stacked with connecting line on the left) AND changes how StepperContent animates (vertical crossfade instead of horizontal slide).
|
|
45
|
+
- Custom icons via `Step.icon` override the default number/checkmark — the icon slot still receives the status-based styling (muted for pending, accent for active/completed).
|
|
46
|
+
|
|
40
47
|
## Gotchas
|
|
41
48
|
- Steps before activeStep are "completed", at activeStep is "active", after is "pending"
|
|
49
|
+
- Don't conditionally render Step children — position is the index contract
|
|
42
50
|
|
|
43
51
|
## Changes
|
|
44
52
|
### v0.18.0
|
|
@@ -22,9 +22,17 @@
|
|
|
22
22
|
<Switch size="lg" color="success" thumbIcon={<IconCheck size={14} />} />
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Composability
|
|
26
|
+
- Radix Switch primitive — `checked` / `onCheckedChange` / `defaultChecked` standard control model.
|
|
27
|
+
- **FormField:** Switch does NOT auto-consume FormField state (same as Checkbox/Radio — form-library convention for toggles). Pass `error` explicitly when needed.
|
|
28
|
+
- **thumbIcon slot:** Any ReactNode renders inside the thumb circle — commonly used for check/X glyphs that animate with the thumb position.
|
|
29
|
+
- **Label pairing:** Manual — pair with `<Label htmlFor="x" />` + `<Switch id="x" />`, or wrap both in a `<label>` for click-to-toggle.
|
|
30
|
+
- Pair with FormHelperText (outside FormField wiring) for custom validation messages.
|
|
31
|
+
|
|
25
32
|
## Gotchas
|
|
26
33
|
- Use error prop for validation states (matches Checkbox API)
|
|
27
34
|
- `error` overrides `color` — when error is true, checked state always uses error-9
|
|
35
|
+
- Switch does NOT auto-consume FormField — pass `error` explicitly inside a FormField
|
|
28
36
|
|
|
29
37
|
## Changes
|
|
30
38
|
### v0.29.0
|
|
@@ -33,8 +33,16 @@
|
|
|
33
33
|
</Table>
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
## Composability
|
|
37
|
+
- **Server-safe pure HTML wrappers** — Table and sub-components are thin semantic wrappers around `<table>`, `<thead>`, `<tbody>`, etc. No state, no context. Safe in RSC trees.
|
|
38
|
+
- **Table vs DataTable:** Table is presentational — you control every row, cell, header. DataTable (from `ui/data-table`) is feature-rich — sorting, filtering, pagination, selection, virtualization built in. Pick by whether you need that machinery.
|
|
39
|
+
- **Use cases for bare Table:** Static data displays, marketing comparison tables, documentation tables, small lists where DataTable would be overkill.
|
|
40
|
+
- **Composes with UI primitives inside cells:** Badge for status pills, Avatar for user cells, IconButton for row actions, StatusDot for state indicators. All server-safe if the table is server-rendered.
|
|
41
|
+
- **TableCaption** renders as HTML `<caption>` — useful for a summary description that screen readers announce before the table content.
|
|
42
|
+
|
|
36
43
|
## Gotchas
|
|
37
44
|
- Table headers automatically have scope="col" for screen reader navigation
|
|
45
|
+
- For anything beyond trivial display, prefer DataTable — don't rebuild sorting/pagination/selection on top of bare Table
|
|
38
46
|
|
|
39
47
|
## Changes
|
|
40
48
|
### v0.18.0
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
### TabsList
|
|
14
14
|
variant: "line" | "contained"
|
|
15
|
+
size: "sm" | "md" | "lg"
|
|
16
|
+
orientation: "horizontal" | "vertical"
|
|
15
17
|
|
|
16
18
|
### TabsTrigger
|
|
17
19
|
value: string (REQUIRED)
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
TabsContent (value)
|
|
28
30
|
|
|
29
31
|
## Defaults
|
|
30
|
-
TabsList variant
|
|
32
|
+
TabsList variant="line", size="md", orientation="horizontal"
|
|
31
33
|
|
|
32
34
|
## Example
|
|
33
35
|
```jsx
|
|
@@ -41,8 +43,14 @@
|
|
|
41
43
|
</Tabs>
|
|
42
44
|
```
|
|
43
45
|
|
|
46
|
+
## Composability
|
|
47
|
+
- TabsList propagates `variant`, `size`, and `orientation` to every TabsTrigger child via `TabsListContext`. TabsTrigger reads all three from context; explicit props on a trigger override the inherited value.
|
|
48
|
+
- `orientation="vertical"` on TabsList changes the TabsList layout (flex-col + left border) AND the `roving-tabindex` keyboard behavior (ArrowUp/Down navigate, not ArrowLeft/Right).
|
|
49
|
+
- Tabs (root) is just the Radix Tabs.Root — state props (value, defaultValue, onValueChange) live there; styling props live on TabsList.
|
|
50
|
+
- Tabs content is rendered inline (not portalled) — container-scoped queries work fine in tests.
|
|
51
|
+
|
|
44
52
|
## Gotchas
|
|
45
|
-
- variant
|
|
53
|
+
- variant/size/orientation go on TabsList, NOT on Tabs root or individual TabsTrigger
|
|
46
54
|
- Normally omit `variant` on TabsTrigger — it inherits from TabsList via context. You CAN set it per-trigger to override.
|
|
47
55
|
|
|
48
56
|
## Changes
|
|
@@ -5,12 +5,9 @@
|
|
|
5
5
|
- Category: ui
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
|
-
variant:
|
|
8
|
+
variant: "heading-2xl" | "heading-xl" | "heading-lg" | "heading-md" | "heading-sm" | "heading-xs" | "body-lg" | "body-md" | "body-sm" | "body-xs" | "label-lg" | "label-md" | "label-sm" | "label-xs" | "label-plain-lg" | "label-plain-md" | "label-plain-sm" | "caption" | "overline" | "code"
|
|
9
9
|
as: ElementType (override the auto-selected HTML element)
|
|
10
10
|
|
|
11
|
-
## Types
|
|
12
|
-
TextVariant = 'heading-2xl' | 'heading-xl' | 'heading-lg' | 'heading-md' | 'heading-sm' | 'heading-xs' | 'body-lg' | 'body-md' | 'body-sm' | 'body-xs' | 'label-lg' | 'label-md' | 'label-sm' | 'label-xs' | 'caption' | 'overline'
|
|
13
|
-
|
|
14
11
|
## Defaults
|
|
15
12
|
variant: "body-md"
|
|
16
13
|
|
|
@@ -25,9 +22,17 @@
|
|
|
25
22
|
<Text variant="label-sm" className="text-text-secondary">SECTION LABEL</Text>
|
|
26
23
|
```
|
|
27
24
|
|
|
25
|
+
## Composability
|
|
26
|
+
- **Server-safe** (one of few components in the library that is). Can render in RSC trees without `"use client"`.
|
|
27
|
+
- No context consumption, no context cascade — pure typography primitive.
|
|
28
|
+
- **Semantic HTML by default:** Each variant maps to a meaningful HTML element (h1 through p, span, code). The `as` prop overrides for visual-only demotion: e.g. `<Text variant="heading-xl" as="div">` renders h2-sized text inside a div, useful when the element already has a heading ancestor but you want the visual weight.
|
|
29
|
+
- **Underpins many components:** Card's CardTitle, Alert's title, PageHeader, EmptyState, SectionHeader all render Text internally with specific variants. Don't wrap another Text inside them — variants cascade structurally, not via context.
|
|
30
|
+
- Pairs with Code for inline code spans inside body text: `<Text>Call <Code>onClick</Code> to...</Text>`.
|
|
31
|
+
|
|
28
32
|
## Gotchas
|
|
29
33
|
- label-* and overline variants are automatically uppercase
|
|
30
34
|
- Use "as" prop to override the HTML element when needed
|
|
35
|
+
- Don't use Text inside headings that already have semantic meaning (e.g. CardTitle) — the double-element wraps are redundant and break screen-reader heading navigation
|
|
31
36
|
|
|
32
37
|
## Changes
|
|
33
38
|
### v0.2.0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- Category: ui
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
|
-
size: "sm" | "md" | "lg"
|
|
8
|
+
size: "xs" | "sm" | "md" | "lg"
|
|
9
9
|
state: "default" | "error" | "warning" | "success"
|
|
10
10
|
(plus standard textarea attributes except native "size")
|
|
11
11
|
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
<Textarea size="lg" state="error" placeholder="Describe the issue..." />
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## Composability
|
|
21
|
+
- **FormField auto-consumption:** Same pattern as Input — inside `<FormField>`, Textarea inherits `state`, `aria-describedby`, `aria-invalid`, `aria-required`. Explicit props override.
|
|
22
|
+
- **Resize:** Vertically resizable by default (`resize-y`); override with `className="resize-none"` if needed.
|
|
23
|
+
- **Label pairing:** Manual — `<Label htmlFor="x" />` + `<Textarea id="x" />`. FormField doesn't auto-wire.
|
|
24
|
+
- No IconProvider cascade (no icon slots — different from Input).
|
|
25
|
+
|
|
20
26
|
## Gotchas
|
|
21
27
|
- state="error" sets aria-invalid automatically; all sizes are vertically resizable
|
|
22
28
|
- Inside FormField: auto-inherits state, aria-describedby, aria-required from context (explicit props override)
|
|
@@ -41,6 +41,15 @@ toast.error('Upload failed', { description: 'File too large' })
|
|
|
41
41
|
toast.undo('Task deleted', { onUndo: () => restoreTask(id) })
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
## Composability
|
|
45
|
+
- **Imperative API only** — `toast.success(...)`, `toast.error(...)`, etc. NO JSX invocation. This is by design (Sonner-based) — you call from event handlers, not render.
|
|
46
|
+
- **Requires Toaster mounted once** at app root. Without it, `toast.*` calls are no-ops. Render `<Toaster />` in the root layout, not inside route components.
|
|
47
|
+
- **toast.promise** orchestrates async flows: `toast.promise(fetch(...), { loading: 'Saving', success: 'Saved', error: 'Failed' })`. One toast, three states. Beats manually calling `.loading()` + `.success()`/`.error()`.
|
|
48
|
+
- **toast.undo** adds an inline Undo button with 8s default duration — pair with state management that supports reversal (soft-delete with restore, last-action redo).
|
|
49
|
+
- **toast.upload** is specifically for file-upload progress — per-file progress bars, retry on error, remove from list. Replaces the old `UploadProgress` composed component.
|
|
50
|
+
- **toast.custom** is the escape hatch — render arbitrary JSX. Use sparingly; prefer the typed methods for consistency.
|
|
51
|
+
- **Distinction from Alert/Banner:** Toast = transient, auto-dismissing, non-interactive-dismissible floating notification. Alert = inline in-flow announcement. Banner = page-level strip. Pick by persistence + position.
|
|
52
|
+
|
|
44
53
|
## Gotchas
|
|
45
54
|
- DO NOT use useToast() hook — it is deprecated, use imperative toast.* methods
|
|
46
55
|
- DO NOT use toast({ title, color }) object syntax — use toast.success('message') etc.
|
|
@@ -33,9 +33,17 @@ export default function RootLayout({ children }) {
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
## Composability
|
|
37
|
+
- **Mount once, use everywhere.** Render `<Toaster />` in the root layout file once. Every `toast.*` call anywhere in the tree routes to this single container.
|
|
38
|
+
- **Global config lives here.** Set `position`, `duration`, `visibleToasts` on Toaster to control default behavior for all toasts. Individual `toast.*` calls can override `duration` per toast.
|
|
39
|
+
- **Keyboard shortcut:** `hotkey` prop sets a global shortcut to focus the toast region (default: Alt+T). Useful for keyboard users to review recent notifications.
|
|
40
|
+
- **Next.js / App Router:** Mount inside your root `app/layout.tsx`'s `<body>`. It's marked `'use client'` so it doesn't render on the server (Toaster is client-only).
|
|
41
|
+
- **Portal rendering:** z-toast (highest layer) — Toaster content appears above Dialog, Popover, everything. Don't wrap it in a stacking context.
|
|
42
|
+
|
|
36
43
|
## Gotchas
|
|
37
44
|
- Must be mounted once at the layout root for toast notifications to work
|
|
38
45
|
- Use the `toast` import from `@devalok/shilp-sutra/ui/toast` to trigger toasts
|
|
46
|
+
- NOT server-safe — mounts with 'use client'; rendering during SSR has no visual effect
|
|
39
47
|
|
|
40
48
|
## Changes
|
|
41
49
|
### v0.18.0
|
|
@@ -16,8 +16,11 @@
|
|
|
16
16
|
value: string
|
|
17
17
|
|
|
18
18
|
## Compound Components
|
|
19
|
-
ToggleGroup (root)
|
|
20
|
-
ToggleGroupItem (value: string)
|
|
19
|
+
ToggleGroup (root — variant, size propagated to items via context)
|
|
20
|
+
ToggleGroupItem (value: string — reads variant/size from context)
|
|
21
|
+
|
|
22
|
+
## Defaults
|
|
23
|
+
variant="default", size="md"
|
|
21
24
|
|
|
22
25
|
## Example
|
|
23
26
|
```jsx
|
|
@@ -28,9 +31,15 @@
|
|
|
28
31
|
</ToggleGroup>
|
|
29
32
|
```
|
|
30
33
|
|
|
34
|
+
## Composability
|
|
35
|
+
- ToggleGroup passes `variant` and `size` to every ToggleGroupItem via `ToggleGroupContext`. Items read both from context; explicit props on a child override.
|
|
36
|
+
- `type="single"` enforces one-selected-at-a-time (value: string); `type="multiple"` allows many (value: string[]). Radix Toggle Group underpins this — it's the same role + keyboard model as Radix.
|
|
37
|
+
- Built on top of the plain `Toggle` component's CVA — the `variant` and `size` axes of ToggleGroupItem match Toggle exactly (`default | outline`, `sm | md | lg`).
|
|
38
|
+
|
|
31
39
|
## Gotchas
|
|
32
|
-
- type is required — "single" or "multiple"
|
|
33
|
-
- variant and size propagate from ToggleGroup to items
|
|
40
|
+
- `type` is required — "single" or "multiple" — and drives the value shape
|
|
41
|
+
- variant and size propagate from ToggleGroup to items; setting them on a ToggleGroupItem overrides that item only
|
|
42
|
+
- Unlike Tabs (where TabsList is the styling surface), ToggleGroup itself is the styling surface — there's no intermediate List component
|
|
34
43
|
|
|
35
44
|
## Changes
|
|
36
45
|
### v0.18.0
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
## Props
|
|
8
8
|
variant: "default" | "outline"
|
|
9
9
|
size: "sm" | "md" | "lg"
|
|
10
|
+
color: "accent" | "error" | "success" | "neutral" (pressed-state bg + text color)
|
|
10
11
|
pressed: boolean
|
|
11
12
|
onPressedChange: (pressed: boolean) => void
|
|
12
13
|
defaultPressed: boolean
|
|
13
14
|
|
|
14
15
|
## Defaults
|
|
15
|
-
variant
|
|
16
|
-
size: "md"
|
|
16
|
+
variant="default", size="md", color="accent"
|
|
17
17
|
|
|
18
18
|
## Example
|
|
19
19
|
```jsx
|
|
@@ -22,8 +22,16 @@
|
|
|
22
22
|
</Toggle>
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Composability
|
|
26
|
+
- Radix Toggle primitive — `pressed` / `onPressedChange` / `defaultPressed`. Not the same as Switch (boolean value doesn't map to on/off semantically — Toggle is "this action is currently active").
|
|
27
|
+
- **Pairs with ToggleGroup** for mutually-exclusive or multi-select toggle clusters — ToggleGroupItem inherits variant + size from ToggleGroup via context. Don't set variant on a ToggleGroupItem directly.
|
|
28
|
+
- **No context consumption as a standalone** — when rendered outside a ToggleGroup, Toggle is fully independent.
|
|
29
|
+
- **Icon content:** Commonly wraps a single `<Icon>` for formatting toolbar toggles (Bold, Italic, AlignLeft). Pair with IconGroup for a horizontal cluster of independent toggles (vs. ToggleGroup for related state).
|
|
30
|
+
- **aria-label is required** — icon-only toggles need an accessible name.
|
|
31
|
+
|
|
25
32
|
## Gotchas
|
|
26
33
|
- Always provide aria-label for accessibility
|
|
34
|
+
- Toggle is not Switch — Toggle means "this action is active right now"; Switch means "this setting is on"
|
|
27
35
|
|
|
28
36
|
## Changes
|
|
29
37
|
### v0.18.0
|
|
@@ -20,8 +20,18 @@
|
|
|
20
20
|
</TooltipProvider>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## Composability
|
|
24
|
+
- Built on Radix Tooltip — accepts `delayDuration`, `skipDelayDuration` (on TooltipProvider), and `open`/`onOpenChange`/`defaultOpen` (on Tooltip root).
|
|
25
|
+
- **Auto-provider (v0.22.0+):** If no ancestor TooltipProvider exists, `<Tooltip>` auto-wraps itself with one. Explicit TooltipProvider is still recommended at layout root for shared `delayDuration` tuning.
|
|
26
|
+
- **Trigger:** `<TooltipTrigger asChild>` around the element that should show the tooltip on hover/focus. Icon-only buttons are the canonical use case.
|
|
27
|
+
- **Not interactive:** TooltipContent is for non-interactive text labels — don't put buttons/links inside. Use HoverCard or Popover when the popped content needs interaction.
|
|
28
|
+
- **Positioning:** TooltipContent accepts `side`, `align`, `sideOffset`, and arrow via `<TooltipArrow>` (optional).
|
|
29
|
+
- **Portal rendering:** z-index is `z-tooltip` (highest in the stack — above Popover and Dialog).
|
|
30
|
+
|
|
23
31
|
## Gotchas
|
|
24
|
-
- TooltipProvider is REQUIRED —
|
|
32
|
+
- TooltipProvider is REQUIRED at the layout level OR auto-created per-tooltip — but having a single root provider is better for consistent delays
|
|
33
|
+
- Don't use Tooltip for critical information — hover-triggered UI is invisible to touch users. Pair with a visible label or aria-description
|
|
34
|
+
- TooltipContent children must be inert — no buttons, no links, no focusable elements
|
|
25
35
|
|
|
26
36
|
## Changes
|
|
27
37
|
### v0.22.0
|
|
@@ -51,8 +51,20 @@
|
|
|
51
51
|
</TreeView>
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
## Composability
|
|
55
|
+
- **Two rendering modes:**
|
|
56
|
+
- **Data-driven:** Pass `items: TreeNode[]` with nested `children`. Good for server-fetched or programmatic trees.
|
|
57
|
+
- **Declarative:** Use `<TreeItem>` children directly. Good for hardcoded nav, readable JSX.
|
|
58
|
+
- Don't mix — pick one per TreeView instance.
|
|
59
|
+
- **useTree hook** lets you drive TreeView state externally (e.g. sync with URL, persist expanded state, drive from Redux). Pass `defaultExpanded`/`defaultSelected` initially OR manage state via the hook's return value.
|
|
60
|
+
- **TreeItem composability:** Each TreeItem has `icon`, `label`, `secondaryLabel`, and `actions` slots — rich rows without custom render props. `actions` reveals on row hover (same pattern as Message.Actions).
|
|
61
|
+
- **multiSelect + checkboxes:** Set both to turn TreeView into a file-picker style tree with checkboxes instead of single-select highlighting.
|
|
62
|
+
- **Keyboard navigation:** Full `role="tree"` spec — Arrow Up/Down to move, Right to expand/descend, Left to collapse/ascend, Enter to select. Pre-wired; no manual key handling needed.
|
|
63
|
+
|
|
54
64
|
## Gotchas
|
|
55
65
|
- Supports both data-driven (items prop) and declarative (children) modes
|
|
66
|
+
- Don't mix data-driven and declarative in the same TreeView — pick one
|
|
67
|
+
- For a simple flat checkbox list, use RadioGroup/Checkbox + Stack — TreeView is overkill for non-hierarchical data
|
|
56
68
|
|
|
57
69
|
## Changes
|
|
58
70
|
### v0.4.2
|
|
@@ -12,9 +12,16 @@
|
|
|
12
12
|
<VisuallyHidden>Screen reader only text</VisuallyHidden>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Composability
|
|
16
|
+
- Server-safe. Works anywhere — no context, no cascade.
|
|
17
|
+
- Canonical use: wrap a DialogTitle / SheetTitle that must exist for a11y but shouldn't show visually (`<DialogTitle asChild><VisuallyHidden>...</VisuallyHidden></DialogTitle>`).
|
|
18
|
+
- Also useful inside IconButton to provide a text alternative when the icon already has an aria-label (redundant label is harmless and helps some screen readers).
|
|
19
|
+
- Uses the `sr-only` CSS pattern under the hood — content is in the DOM, just positioned off-screen.
|
|
20
|
+
|
|
15
21
|
## Gotchas
|
|
16
22
|
- Content is visually hidden but accessible to screen readers
|
|
17
23
|
- Useful for providing accessible labels without visual UI
|
|
24
|
+
- Don't use for content you want hidden entirely — that's `hidden` or conditional rendering
|
|
18
25
|
|
|
19
26
|
## Changes
|
|
20
27
|
### v0.1.0
|