@devalok/shilp-sutra 0.37.0 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/composed/inline-edit.d.ts.map +1 -1
  2. package/dist/composed/inline-edit.js +42 -40
  3. package/dist/composed/inline-edit.js.map +1 -1
  4. package/dist/test-utils/conformance.d.ts +37 -0
  5. package/dist/test-utils/conformance.d.ts.map +1 -0
  6. package/docs/components/composed/activity-feed.md +6 -0
  7. package/docs/components/composed/avatar-group.md +8 -0
  8. package/docs/components/composed/bulk-action-bar.md +6 -0
  9. package/docs/components/composed/command-palette.md +7 -0
  10. package/docs/components/composed/confirm-dialog.md +6 -0
  11. package/docs/components/composed/content-card.md +6 -0
  12. package/docs/components/composed/date-picker.md +10 -0
  13. package/docs/components/composed/deadline-indicator.md +7 -0
  14. package/docs/components/composed/emoji-picker.md +8 -0
  15. package/docs/components/composed/empty-state.md +8 -0
  16. package/docs/components/composed/error-boundary.md +7 -0
  17. package/docs/components/composed/file-preview.md +8 -0
  18. package/docs/components/composed/filter-bar.md +8 -0
  19. package/docs/components/composed/form-section.md +6 -0
  20. package/docs/components/composed/global-loading.md +6 -0
  21. package/docs/components/composed/inline-edit.md +8 -0
  22. package/docs/components/composed/loading-skeleton.md +7 -0
  23. package/docs/components/composed/markdown-viewer.md +9 -0
  24. package/docs/components/composed/master-detail.md +7 -0
  25. package/docs/components/composed/member-picker.md +7 -0
  26. package/docs/components/composed/multi-select-popover.md +11 -0
  27. package/docs/components/composed/page-header.md +7 -0
  28. package/docs/components/composed/page-skeletons.md +10 -0
  29. package/docs/components/composed/priority-indicator.md +7 -0
  30. package/docs/components/composed/responsive-overlay.md +7 -0
  31. package/docs/components/composed/rich-chat-input.md +12 -0
  32. package/docs/components/composed/rich-text-editor.md +9 -0
  33. package/docs/components/composed/schedule-view.md +8 -0
  34. package/docs/components/composed/simple-tooltip.md +7 -0
  35. package/docs/components/composed/status-badge.md +10 -0
  36. package/docs/components/shell/app-command-palette.md +8 -0
  37. package/docs/components/shell/bottom-navbar.md +12 -0
  38. package/docs/components/shell/command-registry.md +7 -0
  39. package/docs/components/shell/link-context.md +15 -0
  40. package/docs/components/shell/notification-center.md +10 -0
  41. package/docs/components/shell/notification-preferences.md +7 -0
  42. package/docs/components/shell/sidebar.md +11 -0
  43. package/docs/components/shell/top-bar.md +11 -0
  44. package/docs/components/ui/accordion.md +10 -0
  45. package/docs/components/ui/alert-dialog.md +10 -1
  46. package/docs/components/ui/alert.md +10 -2
  47. package/docs/components/ui/aspect-ratio.md +7 -0
  48. package/docs/components/ui/autocomplete.md +7 -0
  49. package/docs/components/ui/avatar.md +10 -0
  50. package/docs/components/ui/badge-group.md +7 -0
  51. package/docs/components/ui/badge-indicator.md +7 -0
  52. package/docs/components/ui/badge.md +12 -0
  53. package/docs/components/ui/banner.md +7 -0
  54. package/docs/components/ui/breadcrumb.md +8 -0
  55. package/docs/components/ui/button-group.md +24 -4
  56. package/docs/components/ui/button-processing.md +5 -0
  57. package/docs/components/ui/button.md +9 -0
  58. package/docs/components/ui/card.md +16 -4
  59. package/docs/components/ui/charts.md +9 -0
  60. package/docs/components/ui/chat.md +9 -0
  61. package/docs/components/ui/checkbox.md +15 -1
  62. package/docs/components/ui/chip.md +9 -0
  63. package/docs/components/ui/code.md +7 -0
  64. package/docs/components/ui/collapsible.md +9 -0
  65. package/docs/components/ui/color-input.md +8 -0
  66. package/docs/components/ui/color-swatch.md +7 -0
  67. package/docs/components/ui/combobox.md +16 -3
  68. package/docs/components/ui/container.md +11 -0
  69. package/docs/components/ui/context-menu.md +8 -0
  70. package/docs/components/ui/data-table-body.md +4 -0
  71. package/docs/components/ui/data-table-bulk-actions.md +4 -0
  72. package/docs/components/ui/data-table-card.md +4 -0
  73. package/docs/components/ui/data-table-context.md +4 -0
  74. package/docs/components/ui/data-table-header.md +4 -0
  75. package/docs/components/ui/data-table-pagination.md +4 -0
  76. package/docs/components/ui/data-table-toolbar.md +7 -0
  77. package/docs/components/ui/data-table.md +25 -0
  78. package/docs/components/ui/devalok-grain.md +8 -0
  79. package/docs/components/ui/dialog.md +10 -0
  80. package/docs/components/ui/dropdown-menu.md +10 -0
  81. package/docs/components/ui/file-upload.md +8 -0
  82. package/docs/components/ui/form.md +21 -0
  83. package/docs/components/ui/hover-card.md +9 -0
  84. package/docs/components/ui/icon-button.md +7 -0
  85. package/docs/components/ui/icon-context.md +7 -0
  86. package/docs/components/ui/icon-group.md +9 -0
  87. package/docs/components/ui/icon.md +7 -0
  88. package/docs/components/ui/input-otp.md +29 -7
  89. package/docs/components/ui/input.md +7 -0
  90. package/docs/components/ui/label.md +7 -1
  91. package/docs/components/ui/link.md +7 -0
  92. package/docs/components/ui/menubar.md +9 -0
  93. package/docs/components/ui/navigation-menu.md +9 -0
  94. package/docs/components/ui/number-input.md +10 -0
  95. package/docs/components/ui/pagination.md +10 -0
  96. package/docs/components/ui/popover.md +9 -0
  97. package/docs/components/ui/progress-ring.md +7 -0
  98. package/docs/components/ui/progress.md +7 -0
  99. package/docs/components/ui/radio.md +27 -2
  100. package/docs/components/ui/search-input.md +8 -0
  101. package/docs/components/ui/segmented-control.md +8 -0
  102. package/docs/components/ui/select.md +14 -3
  103. package/docs/components/ui/separator.md +7 -0
  104. package/docs/components/ui/sheet.md +10 -0
  105. package/docs/components/ui/sidebar.md +30 -0
  106. package/docs/components/ui/skeleton.md +7 -0
  107. package/docs/components/ui/slider.md +15 -1
  108. package/docs/components/ui/spinner.md +7 -0
  109. package/docs/components/ui/split-button.md +11 -0
  110. package/docs/components/ui/stack.md +8 -0
  111. package/docs/components/ui/stat-card.md +9 -0
  112. package/docs/components/ui/status-dot.md +9 -0
  113. package/docs/components/ui/stepper.md +8 -0
  114. package/docs/components/ui/switch.md +8 -0
  115. package/docs/components/ui/table.md +8 -0
  116. package/docs/components/ui/tabs.md +10 -2
  117. package/docs/components/ui/text.md +9 -4
  118. package/docs/components/ui/textarea.md +7 -1
  119. package/docs/components/ui/toast.md +9 -0
  120. package/docs/components/ui/toaster.md +8 -0
  121. package/docs/components/ui/toggle-group.md +13 -4
  122. package/docs/components/ui/toggle.md +10 -2
  123. package/docs/components/ui/tooltip.md +11 -1
  124. package/docs/components/ui/tree-view.md +12 -0
  125. package/docs/components/ui/visually-hidden.md +7 -0
  126. package/llms-full.txt +1116 -44
  127. package/package.json +1 -1
@@ -14,8 +14,14 @@
14
14
  <Label htmlFor="email" required>Email Address</Label>
15
15
  ```
16
16
 
17
+ ## Composability
18
+ - **Label is NOT auto-wired by FormField** — you must explicitly pair `<Label htmlFor="x" />` with the matching `<Input id="x" />` (or Checkbox/Radio/Switch/Select). Screen-reader label association depends on this.
19
+ - Radix Label primitive underneath — clicking the Label focuses its associated control, which is why the `htmlFor`/`id` pairing matters.
20
+ - `required={true}` only renders the red asterisk; it does NOT set `aria-required` on the associated control (that comes from FormField context on the control itself).
21
+ - Works with any input-like component in the library — pair with Input, Textarea, NumberInput, Checkbox, Radio, Switch, Select, Combobox, Autocomplete.
22
+
17
23
  ## Gotchas
18
- - Use with FormField for automatic aria wiring
24
+ - Use with FormField for automatic aria wiring on the control (but the Label-to-control association is always manual)
19
25
 
20
26
  ## Changes
21
27
  ### v0.2.0
@@ -18,8 +18,15 @@
18
18
  <Link asChild><NextLink href="/about">About</NextLink></Link>
19
19
  ```
20
20
 
21
+ ## Composability
22
+ - **Framework router integration via `asChild`:** `<Link asChild><NextLink href="/foo">...</NextLink></Link>` — Link's styling transfers to the child (NextLink/react-router Link/any `<a>`-like component) while preserving the child's navigation semantics. Don't use `asChild` for plain anchors — it's unnecessary and adds a layer.
23
+ - **inline vs block:** Default `inline` (display: inline) so Link composes naturally inside paragraphs and mixed text. Set `inline={false}` for full-width link regions (card wrappers, list items).
24
+ - No context, no cascade. Safe to use anywhere.
25
+ - For icon + text links, nest Icon inside — Link doesn't auto-size via IconProvider (unlike Button), so pass an explicit `size` to the Icon.
26
+
21
27
  ## Gotchas
22
28
  - Use asChild with framework-specific Link components (e.g. Next.js Link)
29
+ - Don't nest interactive elements (buttons, form controls) inside a Link — that's invalid HTML and breaks screen-reader navigation
23
30
 
24
31
  ## Changes
25
32
  ### v0.18.0
@@ -30,8 +30,17 @@
30
30
  </Menubar>
31
31
  ```
32
32
 
33
+ ## Composability
34
+ - Radix Menubar — shares the item-variant vocabulary with DropdownMenu and ContextMenu (checkbox items, radio groups, sub-menus, labels, separators, shortcuts).
35
+ - **Key difference from DropdownMenu:** Menubar is the horizontal top-bar-menu pattern (File / Edit / View / Help). Multiple MenubarMenu children sit side-by-side at the root; opening one closes the others, and arrow keys move between them.
36
+ - **Typical use:** Desktop app-like UIs where the menu is always visible at the top (code editors, design tools). For a single collapsed trigger, use DropdownMenu instead.
37
+ - **Controlled open:** Pass `value` + `onValueChange` to Menubar root to control which MenubarMenu is open (value = menu's `value` prop or falsy for none).
38
+ - **Portal + z-index:** z-popover (1400).
39
+
33
40
  ## Gotchas
34
41
  - Follows the standard Radix Menubar compound pattern
42
+ - Don't use Menubar for a single dropdown — use DropdownMenu instead
43
+ - MenubarShortcut is decorative (same as DropdownMenuShortcut) — bind shortcuts separately
35
44
 
36
45
  ## Changes
37
46
  ### v0.18.0
@@ -31,8 +31,17 @@
31
31
  </NavigationMenu>
32
32
  ```
33
33
 
34
+ ## Composability
35
+ - **Radix NavigationMenu** underneath — keyboard model (Tab between items, Arrow for panel navigation, Esc to close) is pre-wired.
36
+ - **NavigationMenuLink vs NavigationMenuTrigger:** Use Link for simple nav items (no dropdown); use Trigger + Content for items with a panel of sub-links.
37
+ - **NavigationMenuViewport** is the animated container that holds the active Content panel — it auto-positions below the triggers. NavigationMenuIndicator is the small arrow/caret pointing from trigger to viewport.
38
+ - **Purpose:** Top-level site navigation (Products, Solutions, Resources) with rich dropdowns containing links grouped by category. Don't use for context menus (use DropdownMenu) or action toolbars (use ButtonGroup).
39
+ - **Router integration:** Use `<NavigationMenuLink asChild><NextLink href="/...">...</NextLink></NavigationMenuLink>` for framework-specific Link components.
40
+ - **Portal + z-popover (1400)** — content panels portal to body and stack above Dialog/Sheet.
41
+
34
42
  ## Gotchas
35
43
  - Uses Framer Motion for enter/exit animations (v0.18.0)
44
+ - NavigationMenu is NOT for sidebar nav — use Sidebar; NOT for mobile nav — use Sheet or BottomNavbar
36
45
 
37
46
  ## Changes
38
47
  ### v0.18.0
@@ -7,6 +7,8 @@
7
7
  ## Props
8
8
  value: number (default: 0)
9
9
  onValueChange: (value: number) => void
10
+ size: "xs" | "sm" | "md" | "lg"
11
+ state: "default" | "error" | "warning" | "success" (border color)
10
12
  min: number
11
13
  max: number
12
14
  step: number (default: 1)
@@ -14,6 +16,8 @@
14
16
 
15
17
  ## Defaults
16
18
  value: 0
19
+ size: "md"
20
+ state: "default"
17
21
  step: 1
18
22
  min: Number.MIN_SAFE_INTEGER
19
23
  max: Number.MAX_SAFE_INTEGER
@@ -23,6 +27,12 @@
23
27
  <NumberInput value={qty} onValueChange={setQty} min={1} max={99} />
24
28
  ```
25
29
 
30
+ ## Composability
31
+ - **FormField auto-consumption:** Inside `<FormField>`, inherits `aria-describedby`, `aria-invalid`, `aria-required`. `state` from FormField context drives the border color unless overridden.
32
+ - **IconProvider cascade:** The `+` and `−` stepper icons auto-size via IconProvider per the input size (xs/sm/md/lg → xs/sm/sm/md icons).
33
+ - **Controlled only** (design choice): no `defaultValue` — pair `value` + `onValueChange` every time. The min/max bounds disable the stepper buttons automatically when reached.
34
+ - **Label pairing:** Manual via `<Label htmlFor="x" />` + `<NumberInput id="x" />`.
35
+
26
36
  ## Gotchas
27
37
  - Controlled only — buttons won't work without onValueChange
28
38
 
@@ -36,8 +36,18 @@
36
36
  </PaginationRoot>
37
37
  ```
38
38
 
39
+ ## Composability
40
+ - **Two APIs in one component:**
41
+ - Low-level compound (PaginationRoot + Content + Item + Link + Previous/Next/Ellipsis) — full control over rendering
42
+ - High-level `PaginationNav` — pass `totalPages` + `currentPage` + `onPageChange` and it renders the whole thing using `generatePagination`
43
+ - **Use PaginationNav for 95% of cases.** Reach for the compound API when you need custom page-button rendering (e.g. pagination with input "jump to page" or custom ellipsis handling).
44
+ - **generatePagination** utility — pass `current`, `total`, `siblingCount` to get the `[1, ..., 5, 6, 7, ..., 20]` structure. Use it standalone if rendering pagination elsewhere (e.g. in a DataTable's footer).
45
+ - **Router integration:** Each PaginationLink accepts `asChild` — wrap with NextLink/react-router Link for URL-based pagination.
46
+ - **DataTable already has built-in pagination** — don't add Pagination separately; use DataTable's `pagination` prop.
47
+
39
48
  ## Gotchas
40
49
  - Root component is PaginationRoot (NOT Pagination)
50
+ - PaginationNav is the convenience wrapper — prefer it unless you need custom rendering
41
51
 
42
52
  ## Changes
43
53
  ### v0.1.1
@@ -18,8 +18,17 @@
18
18
  </Popover>
19
19
  ```
20
20
 
21
+ ## Composability
22
+ - Built on Radix Popover — accepts `open`, `onOpenChange`, `defaultOpen`, `modal`.
23
+ - **Trigger:** `<PopoverTrigger asChild>` wraps any focusable element.
24
+ - **PopoverAnchor:** Optional — decouples the visual anchor from the interactive trigger. Useful when the trigger is small (e.g. an icon button) but you want the popover to position relative to a larger surrounding element.
25
+ - **Positioning:** PopoverContent accepts `side` (top / right / bottom / left), `align` (start / center / end), `sideOffset`, and `collisionPadding` — all forwarded to Floating UI via Radix.
26
+ - **Portal rendering:** Content portals to body; z-index is `z-popover` (1400) — above Dialog (`z-dialog`) so nested popovers-in-dialogs work correctly.
27
+ - **Not for tooltips** — use Tooltip for transient hover-label content; Popover is for interactive content (forms, menus, pickers).
28
+
21
29
  ## Gotchas
22
30
  - Uses Framer Motion for enter/exit animations (v0.18.0)
31
+ - If content needs to be modal (backdrop, focus trap), pass `modal={true}` to the root Popover
23
32
 
24
33
  ## Changes
25
34
  ### v0.18.0
@@ -35,6 +35,13 @@
35
35
  />
36
36
  ```
37
37
 
38
+ ## Composability
39
+ - **SVG-based circular progress** — pure SVG, no chart library dependency.
40
+ - **MultiProgressRing** — concentric rings for multi-metric visualization (Apple Activity style: Move + Exercise + Stand). Don't stack more than 4-5 rings at a size; the innermost rings become too thin. Size auto-allocates ring stroke; pass `size="lg"` for more room.
41
+ - **ProgressRing vs Progress:** Use ProgressRing for dashboard tiles, at-a-glance status, multi-metric visualizations. Use Progress for linear "percentage filled" UIs.
42
+ - **`showValue={true}`** renders the percentage in the center (ProgressRing only). For MultiProgressRing, use external labels since center would conflict with multiple values.
43
+ - **Label for a11y:** `label` falls back to `"{n}% progress"` so screen readers always get meaningful context.
44
+
38
45
  ## Gotchas
39
46
  - Uses Framer Motion for the animated fill — not server-safe
40
47
  - Value is clamped to `[0, max]` internally
@@ -22,6 +22,13 @@
22
22
  <Progress size="sm" /> {/* indeterminate */}
23
23
  ```
24
24
 
25
+ ## Composability
26
+ - **Radix Progress** underneath — `value` (determinate) or absent (indeterminate). Standard ARIA: role=progressbar, aria-valuenow/min/max.
27
+ - **autoColor semantic signal:** Maps value thresholds to color so consumers don't have to manually compute: 0–59=default, 60–84=warning, 85–100=success, >100=error. Useful for storage meters, budget trackers, goal progress.
28
+ - **Indeterminate:** Omit `value` to get a continuous animated indeterminate bar. Use for unknown-duration loads.
29
+ - **Progress vs ProgressRing:** Progress is a linear bar (horizontal). ProgressRing is circular. ProgressRing offers multi-ring stacked variants; Progress doesn't.
30
+ - **Inside Card/StatCard:** StatCard has a `progress` prop that renders a thin inline version — use that inside StatCards instead of a separate Progress.
31
+
25
32
  ## Gotchas
26
33
  - Omit value (or pass undefined) for indeterminate animation
27
34
  - `autoColor` overrides `color` when `value` is set — do not pass both unless you want autoColor to win
@@ -4,9 +4,26 @@
4
4
  - Server-safe: No
5
5
  - Category: ui
6
6
 
7
+ ## Props
8
+ ### RadioGroup
9
+ value: string (controlled)
10
+ onValueChange: (value: string) => void
11
+ defaultValue: string
12
+ disabled: boolean (propagates to all items)
13
+ orientation: "horizontal" | "vertical"
14
+ name: string (form name for all items)
15
+
16
+ ### RadioGroupItem
17
+ value: string (REQUIRED — what's selected when this item is checked)
18
+ size: "sm" | "md" | "lg"
19
+ disabled: boolean (item-level override)
20
+
7
21
  ## Compound Components
8
- RadioGroup (root, value, onValueChange, defaultValue)
9
- RadioGroupItem (value: string, REQUIRED)
22
+ RadioGroup (root value, onValueChange, defaultValue, disabled propagated)
23
+ RadioGroupItem (value REQUIRED, size/disabled individually overridable)
24
+
25
+ ## Defaults
26
+ RadioGroupItem size="md"
10
27
 
11
28
  ## Example
12
29
  ```jsx
@@ -22,9 +39,17 @@
22
39
  </RadioGroup>
23
40
  ```
24
41
 
42
+ ## Composability
43
+ - Radix RadioGroup — keyboard navigation (arrow keys to move between items, space to select) is pre-wired.
44
+ - **RadioGroup propagates** `disabled` to every RadioGroupItem; items can opt back in with `disabled={false}` for granular control (rare).
45
+ - **Labels:** RadioGroupItem has no intrinsic label — pair each with `<Label htmlFor="x" />` + `<RadioGroupItem id="x" value="..." />`. Screen readers announce the group label (from FormField or aria-labelledby on RadioGroup) plus each item's label.
46
+ - **Form libraries:** RadioGroup works with react-hook-form via Controller (onValueChange maps to field.onChange). The `name` prop puts a hidden form input per item for native form serialization.
47
+ - **FormField integration:** RadioGroup does NOT auto-consume FormField error state. For error visuals, style the RadioGroup surround (e.g. via aria-invalid on a wrapping fieldset) — individual radios don't show red borders the way Inputs do.
48
+
25
49
  ## Gotchas
26
50
  - Each RadioGroupItem needs a unique `value` prop
27
51
  - Pair each item with a Label for accessibility
52
+ - RadioGroup does NOT auto-inherit FormField error state — handle error styling at the group level
28
53
 
29
54
  ## Changes
30
55
  ### v0.4.2
@@ -26,8 +26,16 @@
26
26
  />
27
27
  ```
28
28
 
29
+ ## Composability
30
+ - Purpose-built variant of Input for search — renders the leading search icon and a contextual clear/loading trailing slot. For anything more custom, use Input with explicit `startSection` / `endSection`.
31
+ - **`onClear` makes the X button appear** only when `value` is non-empty. Pair them so users can reset.
32
+ - **`loading={true}` swaps the clear button for a spinner** with `aria-busy="true"` on the input — useful for debounced/async search.
33
+ - Doesn't auto-consume FormField (no `state` prop) — wrap a regular Input inside FormField for validated search fields.
34
+ - Keyboard: Escape auto-triggers `onClear` when wired (handled via `type="search"`'s native behavior on most browsers).
35
+
29
36
  ## Gotchas
30
37
  - HTML native "size" attribute is excluded — use CSS width instead
38
+ - Clear button only appears when both `onClear` is provided AND `value` is non-empty
31
39
 
32
40
  ## Changes
33
41
  ### v0.15.0
@@ -31,9 +31,17 @@
31
31
  />
32
32
  ```
33
33
 
34
+ ## Composability
35
+ - **Data-driven, not compound** — unlike Tabs/ToggleGroup, SegmentedControl takes an `options` array rather than children. This makes it easier to render from a list but harder to customize per-option styling; use Tabs if you need compound children.
36
+ - **When to use vs Tabs:** SegmentedControl is for mutually-exclusive VIEW-MODE toggles (List/Grid/Kanban) — short labels, no associated content panel. Tabs is for content switching where each tab has a corresponding TabsContent. Both render `role="tablist"`.
37
+ - **Option icons** auto-size based on the `size` prop — don't set explicit icon sizes.
38
+ - Fully controlled — there's no `defaultSelectedId`. Manage state in parent.
39
+ - Built from scratch (no Radix primitive) — standard HTML buttons with `aria-selected` and roving tabindex.
40
+
34
41
  ## Gotchas
35
42
  - Controlled only — selectedId + onSelect are required
36
43
  - Uses data-driven API (options prop), not compound children
44
+ - Use Tabs (not SegmentedControl) when you need associated content panels per option
37
45
 
38
46
  ## Changes
39
47
  ### v0.18.0
@@ -6,11 +6,13 @@
6
6
 
7
7
  ## Props
8
8
  ### SelectTrigger
9
- size: "sm" | "md" | "lg"
9
+ variant: "default" | "outline" | "ghost"
10
+ color: "default" | "error" | "success" | "warning" (sets aria-invalid when error)
11
+ size: "xs" | "sm" | "md" | "lg"
10
12
 
11
13
  ## Compound Components
12
14
  Select (root — value, onValueChange, defaultValue)
13
- SelectTrigger (size goes HERE, not on Select root)
15
+ SelectTrigger (variant/color/size go HERE, not on Select root)
14
16
  SelectValue (placeholder)
15
17
  SelectContent
16
18
  SelectGroup (optional grouping)
@@ -19,7 +21,7 @@
19
21
  SelectSeparator
20
22
 
21
23
  ## Defaults
22
- SelectTrigger size: "md"
24
+ SelectTrigger variant="default", color="default", size="md"
23
25
 
24
26
  ## Example
25
27
  ```jsx
@@ -34,6 +36,15 @@
34
36
  </Select>
35
37
  ```
36
38
 
39
+ ## Composability
40
+ - **Radix Select** underneath — `value`/`onValueChange`/`defaultValue`/`open`/`onOpenChange` standard state.
41
+ - **Styling props live on SelectTrigger, not Select root.** The Select root owns value/state; the Trigger owns appearance (variant/color/size). Setting `<Select size="lg">` silently does nothing — TypeScript won't catch it.
42
+ - **SelectItem requires `value`** — unique within the Select. Labels are the children of SelectItem.
43
+ - **SelectGroup + SelectLabel:** Organize options into sections with a non-interactive section heading.
44
+ - **FormField integration:** Set `color="error"` on SelectTrigger for error visuals. Not auto-consumed from FormField (same as Checkbox/Radio — form-library convention for select controls).
45
+ - **Portal + z-popover (1400):** content portals to body, stacks above Dialog/Sheet/other overlays.
46
+ - **Select vs Combobox vs Autocomplete:** Select = short fixed list, click-to-open, no typeahead. Combobox = searchable, forced selection. Autocomplete = searchable, free text. Pick by list size and search need.
47
+
37
48
  ## Gotchas
38
49
  - Size goes on SelectTrigger, NOT on Select root
39
50
  - `<Select size="lg">` is silently ignored (no TypeScript error)
@@ -18,8 +18,15 @@
18
18
  <Separator orientation="vertical" className="h-6" />
19
19
  ```
20
20
 
21
+ ## Composability
22
+ - Radix Separator — no context, no cascade. Drop it anywhere; it inherits its stretch dimension from its parent container (full width for horizontal, full height for vertical — but vertical needs an explicit height from the parent flexbox).
23
+ - `decorative={true}` (default) sets `role="none"` — screen readers skip it. Set `decorative={false}` for semantic separators (e.g. between navigation sections) so screen readers announce the boundary.
24
+ - Gradient variants compose cleanly with any surface color — they use `bg-transparent` + inline linear-gradient, so the underlying `bg-*` of the parent shows through.
25
+ - Common inside Menu/DropdownMenu/Sheet components; their internal *Separator subcomponents already wrap this one.
26
+
21
27
  ## Gotchas
22
28
  - When decorative is true, the separator is hidden from screen readers
29
+ - Vertical separator needs an explicit height from the parent flex container (`h-6`, `h-full`, etc.)
23
30
 
24
31
  ## Changes
25
32
  ### v0.22.0
@@ -32,8 +32,18 @@
32
32
  </Sheet>
33
33
  ```
34
34
 
35
+ ## Defaults
36
+ side="right"
37
+
38
+ ## Composability
39
+ - Same primitives as Dialog — open/onOpenChange/defaultOpen, trigger asChild, portal rendering, focus trap.
40
+ - `side` controls both the enter-from edge and the layout: top/bottom sides full-width, left/right sides ~75% of viewport (capped at sm breakpoint).
41
+ - Use Sheet for side-anchored drawers (settings panels, mobile navigation); use Dialog for centered modals.
42
+ - On mobile (`isMobile` from use-mobile), consider Sheet as the mobile-friendly equivalent of a Dialog/Popover — more thumb-reachable on tall screens.
43
+
35
44
  ## Gotchas
36
45
  - Uses Framer Motion for slide enter/exit animations (v0.18.0)
46
+ - SheetTitle is required for accessibility (same rule as Dialog)
37
47
 
38
48
  ## Changes
39
49
  ### v0.18.0
@@ -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
- Standard Radix Slider props (value, onValueChange, defaultValue, min, max, step, aria-label)
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: "line"
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 goes on TabsList, NOT on individual TabsTrigger (propagates via context)
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