@devalok/shilp-sutra 0.37.1 → 0.39.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.
Files changed (260) hide show
  1. package/MIGRATION.md +185 -0
  2. package/dist/_chunks/badge-group.js +4 -4
  3. package/dist/_chunks/badge-group.js.map +1 -1
  4. package/dist/_chunks/chat.js +14 -14
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/date-picker.js +9 -9
  7. package/dist/_chunks/date-picker.js.map +1 -1
  8. package/dist/_chunks/document-preview.js +2 -2
  9. package/dist/_chunks/document-preview.js.map +1 -1
  10. package/dist/_chunks/file-preview.js +11 -11
  11. package/dist/_chunks/file-preview.js.map +1 -1
  12. package/dist/_chunks/image-preview.js +2 -2
  13. package/dist/_chunks/image-preview.js.map +1 -1
  14. package/dist/_chunks/mention-suggestion.js +5 -5
  15. package/dist/_chunks/mention-suggestion.js.map +1 -1
  16. package/dist/_chunks/popover.js +3 -3
  17. package/dist/_chunks/popover.js.map +1 -1
  18. package/dist/_chunks/rich-chat-input.js +33 -33
  19. package/dist/_chunks/rich-chat-input.js.map +1 -1
  20. package/dist/_chunks/shared.js +5 -5
  21. package/dist/_chunks/shared.js.map +1 -1
  22. package/dist/_chunks/text.js +2 -2
  23. package/dist/_chunks/text.js.map +1 -1
  24. package/dist/_chunks/tiptap.js +977 -968
  25. package/dist/_chunks/tiptap.js.map +1 -1
  26. package/dist/_chunks/tree-view.js +1 -1
  27. package/dist/_chunks/tree-view.js.map +1 -1
  28. package/dist/_chunks/use-calendar.js +5 -5
  29. package/dist/_chunks/use-calendar.js.map +1 -1
  30. package/dist/ai/command-bar.js +10 -10
  31. package/dist/ai/command-bar.js.map +1 -1
  32. package/dist/ai/conversation.js +4 -4
  33. package/dist/ai/conversation.js.map +1 -1
  34. package/dist/composed/activity-feed.js +5 -5
  35. package/dist/composed/activity-feed.js.map +1 -1
  36. package/dist/composed/avatar-group.js +4 -4
  37. package/dist/composed/avatar-group.js.map +1 -1
  38. package/dist/composed/bulk-action-bar.js +1 -1
  39. package/dist/composed/bulk-action-bar.js.map +1 -1
  40. package/dist/composed/command-palette.js +5 -5
  41. package/dist/composed/command-palette.js.map +1 -1
  42. package/dist/composed/content-card.js +1 -1
  43. package/dist/composed/content-card.js.map +1 -1
  44. package/dist/composed/emoji-picker.js +4 -4
  45. package/dist/composed/emoji-picker.js.map +1 -1
  46. package/dist/composed/empty-state.js +1 -1
  47. package/dist/composed/empty-state.js.map +1 -1
  48. package/dist/composed/error-boundary.js +3 -3
  49. package/dist/composed/error-boundary.js.map +1 -1
  50. package/dist/composed/filter-bar.js +1 -1
  51. package/dist/composed/filter-bar.js.map +1 -1
  52. package/dist/composed/index.d.ts +0 -2
  53. package/dist/composed/index.d.ts.map +1 -1
  54. package/dist/composed/index.js +5 -6
  55. package/dist/composed/inline-edit.js +1 -1
  56. package/dist/composed/inline-edit.js.map +1 -1
  57. package/dist/composed/loading-skeleton.js +9 -9
  58. package/dist/composed/loading-skeleton.js.map +1 -1
  59. package/dist/composed/markdown-viewer.js +3 -3
  60. package/dist/composed/markdown-viewer.js.map +1 -1
  61. package/dist/composed/multi-select-popover.js +1 -1
  62. package/dist/composed/multi-select-popover.js.map +1 -1
  63. package/dist/composed/page-header.js +1 -1
  64. package/dist/composed/page-header.js.map +1 -1
  65. package/dist/composed/page-skeletons.js +15 -15
  66. package/dist/composed/page-skeletons.js.map +1 -1
  67. package/dist/composed/priority-indicator.js +3 -3
  68. package/dist/composed/priority-indicator.js.map +1 -1
  69. package/dist/composed/rich-text-editor.js +11 -11
  70. package/dist/composed/rich-text-editor.js.map +1 -1
  71. package/dist/composed/schedule-view.js +3 -3
  72. package/dist/composed/schedule-view.js.map +1 -1
  73. package/dist/composed/status-badge.js +3 -3
  74. package/dist/composed/status-badge.js.map +1 -1
  75. package/dist/hooks/index.d.ts +2 -2
  76. package/dist/hooks/index.d.ts.map +1 -1
  77. package/dist/hooks/index.js +0 -1
  78. package/dist/shell/bottom-navbar.js +6 -6
  79. package/dist/shell/bottom-navbar.js.map +1 -1
  80. package/dist/shell/notification-center.js +8 -8
  81. package/dist/shell/notification-center.js.map +1 -1
  82. package/dist/shell/notification-preferences.js +1 -1
  83. package/dist/shell/notification-preferences.js.map +1 -1
  84. package/dist/shell/sidebar.js +6 -6
  85. package/dist/shell/sidebar.js.map +1 -1
  86. package/dist/shell/top-bar.js +4 -4
  87. package/dist/shell/top-bar.js.map +1 -1
  88. package/dist/tokens/semantic.css +82 -9
  89. package/dist/ui/accordion.js +1 -1
  90. package/dist/ui/accordion.js.map +1 -1
  91. package/dist/ui/alert-dialog.js +3 -3
  92. package/dist/ui/alert-dialog.js.map +1 -1
  93. package/dist/ui/alert.d.ts +1 -2
  94. package/dist/ui/alert.d.ts.map +1 -1
  95. package/dist/ui/alert.js +3 -29
  96. package/dist/ui/alert.js.map +1 -1
  97. package/dist/ui/autocomplete.js +2 -2
  98. package/dist/ui/autocomplete.js.map +1 -1
  99. package/dist/ui/avatar.js +11 -11
  100. package/dist/ui/avatar.js.map +1 -1
  101. package/dist/ui/badge-indicator.js +1 -1
  102. package/dist/ui/badge-indicator.js.map +1 -1
  103. package/dist/ui/banner.d.ts +3 -5
  104. package/dist/ui/banner.d.ts.map +1 -1
  105. package/dist/ui/banner.js +14 -14
  106. package/dist/ui/banner.js.map +1 -1
  107. package/dist/ui/breadcrumb.js +1 -1
  108. package/dist/ui/breadcrumb.js.map +1 -1
  109. package/dist/ui/button.d.ts +2 -2
  110. package/dist/ui/button.js +14 -14
  111. package/dist/ui/button.js.map +1 -1
  112. package/dist/ui/card.js +5 -5
  113. package/dist/ui/card.js.map +1 -1
  114. package/dist/ui/charts/index.js +5 -5
  115. package/dist/ui/charts/index.js.map +1 -1
  116. package/dist/ui/checkbox.js +1 -1
  117. package/dist/ui/checkbox.js.map +1 -1
  118. package/dist/ui/code.js +2 -2
  119. package/dist/ui/code.js.map +1 -1
  120. package/dist/ui/color-input.js +10 -10
  121. package/dist/ui/color-input.js.map +1 -1
  122. package/dist/ui/color-swatch.js +3 -3
  123. package/dist/ui/color-swatch.js.map +1 -1
  124. package/dist/ui/combobox.js +5 -5
  125. package/dist/ui/combobox.js.map +1 -1
  126. package/dist/ui/context-menu.js +6 -6
  127. package/dist/ui/context-menu.js.map +1 -1
  128. package/dist/ui/data-table-body.js +1 -1
  129. package/dist/ui/data-table-body.js.map +1 -1
  130. package/dist/ui/data-table-bulk-actions.js +2 -2
  131. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  132. package/dist/ui/data-table-card.js +2 -2
  133. package/dist/ui/data-table-card.js.map +1 -1
  134. package/dist/ui/data-table-header.js +2 -2
  135. package/dist/ui/data-table-header.js.map +1 -1
  136. package/dist/ui/data-table-pagination.js +3 -3
  137. package/dist/ui/data-table-pagination.js.map +1 -1
  138. package/dist/ui/data-table-toolbar.js +1 -1
  139. package/dist/ui/data-table-toolbar.js.map +1 -1
  140. package/dist/ui/data-table.js +1 -1
  141. package/dist/ui/data-table.js.map +1 -1
  142. package/dist/ui/devalok-grain.d.ts +1 -1
  143. package/dist/ui/devalok-grain.js.map +1 -1
  144. package/dist/ui/dialog.js +2 -2
  145. package/dist/ui/dialog.js.map +1 -1
  146. package/dist/ui/dropdown-menu.js +6 -6
  147. package/dist/ui/dropdown-menu.js.map +1 -1
  148. package/dist/ui/file-upload.js +4 -4
  149. package/dist/ui/file-upload.js.map +1 -1
  150. package/dist/ui/hover-card.js +1 -1
  151. package/dist/ui/hover-card.js.map +1 -1
  152. package/dist/ui/icon-button.js +1 -1
  153. package/dist/ui/icon-button.js.map +1 -1
  154. package/dist/ui/index.d.ts +1 -1
  155. package/dist/ui/index.d.ts.map +1 -1
  156. package/dist/ui/index.js +2 -2
  157. package/dist/ui/index.js.map +1 -1
  158. package/dist/ui/input-otp.js +1 -1
  159. package/dist/ui/input-otp.js.map +1 -1
  160. package/dist/ui/input.d.ts +1 -9
  161. package/dist/ui/input.d.ts.map +1 -1
  162. package/dist/ui/input.js +28 -29
  163. package/dist/ui/input.js.map +1 -1
  164. package/dist/ui/link.js +1 -1
  165. package/dist/ui/link.js.map +1 -1
  166. package/dist/ui/menubar.js +8 -8
  167. package/dist/ui/menubar.js.map +1 -1
  168. package/dist/ui/navigation-menu.js +3 -3
  169. package/dist/ui/navigation-menu.js.map +1 -1
  170. package/dist/ui/number-input.js +3 -3
  171. package/dist/ui/number-input.js.map +1 -1
  172. package/dist/ui/pagination.js +1 -1
  173. package/dist/ui/pagination.js.map +1 -1
  174. package/dist/ui/progress.js +1 -1
  175. package/dist/ui/progress.js.map +1 -1
  176. package/dist/ui/radio.js +1 -1
  177. package/dist/ui/radio.js.map +1 -1
  178. package/dist/ui/segmented-control.d.ts +1 -1
  179. package/dist/ui/segmented-control.d.ts.map +1 -1
  180. package/dist/ui/segmented-control.js +5 -7
  181. package/dist/ui/segmented-control.js.map +1 -1
  182. package/dist/ui/select.js +3 -3
  183. package/dist/ui/select.js.map +1 -1
  184. package/dist/ui/sheet.js +2 -2
  185. package/dist/ui/sheet.js.map +1 -1
  186. package/dist/ui/sidebar.js +11 -11
  187. package/dist/ui/sidebar.js.map +1 -1
  188. package/dist/ui/skeleton.js +9 -9
  189. package/dist/ui/skeleton.js.map +1 -1
  190. package/dist/ui/slider.js +2 -2
  191. package/dist/ui/slider.js.map +1 -1
  192. package/dist/ui/split-button.js +7 -7
  193. package/dist/ui/split-button.js.map +1 -1
  194. package/dist/ui/stat-card.js +7 -7
  195. package/dist/ui/stat-card.js.map +1 -1
  196. package/dist/ui/status-dot.js +2 -2
  197. package/dist/ui/status-dot.js.map +1 -1
  198. package/dist/ui/stepper.js +2 -2
  199. package/dist/ui/stepper.js.map +1 -1
  200. package/dist/ui/switch.js +2 -2
  201. package/dist/ui/switch.js.map +1 -1
  202. package/dist/ui/tabs.js +3 -3
  203. package/dist/ui/tabs.js.map +1 -1
  204. package/dist/ui/textarea.js +1 -1
  205. package/dist/ui/textarea.js.map +1 -1
  206. package/dist/ui/toast.js +8 -8
  207. package/dist/ui/toast.js.map +1 -1
  208. package/dist/ui/toggle.js +1 -1
  209. package/dist/ui/toggle.js.map +1 -1
  210. package/dist/ui/tooltip.js +1 -1
  211. package/dist/ui/tooltip.js.map +1 -1
  212. package/docs/components/_header.md +91 -2
  213. package/docs/components/ui/alert.md +4 -1
  214. package/docs/components/ui/banner.md +3 -1
  215. package/docs/components/ui/input.md +4 -2
  216. package/docs/components/ui/segmented-control.md +13 -6
  217. package/docs/recipes/customize-brand.md +297 -0
  218. package/docs/recipes/index.md +51 -0
  219. package/docs/recipes/install-astro.md +178 -0
  220. package/docs/recipes/install-next-app-router.md +230 -0
  221. package/docs/recipes/install-next-pages.md +123 -0
  222. package/docs/recipes/install-remix.md +171 -0
  223. package/docs/recipes/install-tanstack-start.md +143 -0
  224. package/docs/recipes/install-vite.md +170 -0
  225. package/docs/recipes/server-components.md +209 -0
  226. package/docs/recipes/troubleshoot.md +217 -0
  227. package/llms-full.txt +116 -54
  228. package/llms.txt +42 -17
  229. package/package.json +46 -35
  230. package/skill/README.md +99 -0
  231. package/skill/SKILL.md +144 -0
  232. package/skill/install.sh +59 -0
  233. package/skill/references/components-full.md +6997 -0
  234. package/skill/references/components.md +673 -0
  235. package/skill/references/customize-brand.md +299 -0
  236. package/skill/references/server-components.md +211 -0
  237. package/skill/references/setup-astro.md +180 -0
  238. package/skill/references/setup-next-app-router.md +232 -0
  239. package/skill/references/setup-next-pages.md +125 -0
  240. package/skill/references/setup-remix.md +173 -0
  241. package/skill/references/setup-tanstack-start.md +145 -0
  242. package/skill/references/setup-vite.md +172 -0
  243. package/skill/references/troubleshoot.md +219 -0
  244. package/dist/composed/responsive-overlay.d.ts +0 -23
  245. package/dist/composed/responsive-overlay.d.ts.map +0 -1
  246. package/dist/composed/responsive-overlay.js +0 -40
  247. package/dist/composed/responsive-overlay.js.map +0 -1
  248. package/dist/hooks/use-toast.d.ts +0 -17
  249. package/dist/hooks/use-toast.d.ts.map +0 -1
  250. package/dist/hooks/use-toast.js +0 -3
  251. package/dist/tailwind/index.cjs +0 -41
  252. package/dist/tailwind/index.d.ts +0 -2
  253. package/dist/tailwind/index.d.ts.map +0 -1
  254. package/dist/tailwind/index.js +0 -2
  255. package/dist/tailwind/preset.d.ts +0 -25
  256. package/dist/tailwind/preset.d.ts.map +0 -1
  257. package/dist/tailwind/preset.js +0 -17
  258. package/dist/tailwind/preset.js.map +0 -1
  259. package/docs/components/composed/responsive-overlay.md +0 -41
  260. /package/{LICENSE → skill/LICENSE} +0 -0
@@ -0,0 +1,673 @@
1
+ <!-- Source: packages/core/llms.txt — do not edit directly. Regenerate with `node scripts/build-skill.mjs`. -->
2
+
3
+ # @devalok/shilp-sutra
4
+
5
+ > Radix UI + Tailwind 4 (CSS-first) + CVA design system for Devalok apps.
6
+ > Built on the same primitives as shadcn/ui but with key API differences.
7
+ > Read this file BEFORE writing any UI code. Do NOT guess from shadcn/ui knowledge.
8
+
9
+ ## QUICK SETUP (AI agents — start here)
10
+
11
+ If you are setting up shilp-sutra in a consumer project for the first time, **do not improvise**. Use a recipe.
12
+
13
+ When the package is installed, recipes ship at `node_modules/@devalok/shilp-sutra/docs/recipes/`. Pick one based on the consumer's framework:
14
+
15
+ | Framework | Recipe file |
16
+ |---|---|
17
+ | Next.js (App Router) | `install-next-app-router.md` |
18
+ | Next.js (Pages Router) | `install-next-pages.md` |
19
+ | Vite + React | `install-vite.md` |
20
+ | Astro | `install-astro.md` |
21
+ | Remix | `install-remix.md` |
22
+ | TanStack Start | `install-tanstack-start.md` |
23
+ | Other React + Tailwind | start from `install-vite.md` and adapt |
24
+
25
+ Other recipes:
26
+
27
+ - `customize-brand.md` — token override cookbook (color, radius, font, spacing)
28
+ - `server-components.md` — RSC-safety matrix and import patterns
29
+ - `troubleshoot.md` — decision tree for the 8 most common breakages
30
+
31
+ The repo URL for these files is `https://github.com/devalok-design/shilp-sutra/tree/main/packages/core/docs/recipes`. Consumer projects should also have an `AGENTS.md` at their root with the rules above pre-loaded — read that first if it exists.
32
+
33
+ ## NEW (v0.39.0)
34
+
35
+ - **Shape presets (`[data-shape]`).** Set on `<html>` (or any subtree) to re-skin roundness across the whole UI. Three ship by default: `sharp` (technical, 2/4/6 px), `slightly-rounded` (default, 6/10/16 px), `rounded` (consumer, 10/16/24 px). Pill shapes (Badge, Switch, Radio, Avatar circle) stay pill regardless.
36
+ - **Semantic radius role tokens.** New: `--radius-control`, `--radius-control-inner`, `--radius-surface`, `--radius-overlay-sm`, `--radius-overlay`, `--radius-overlay-lg`, `--radius-pill`, `--radius-bubble`. Consumers override any role globally or scoped — e.g. `:root { --radius-control: 4px; }`.
37
+ - **Visual changes (no API breaks).** Button no longer scales radius with size (md/lg/xl/lg → all 6px); Input lg matches Button at same height; SegmentedControl items now actually pill; Tabs trigger (contained) matches Button; Tooltip belongs to its own `overlay-sm` tier with Toast; Menubar trigger matches DropdownMenu item; Autocomplete listbox matches Popover. If you preferred old chunky big controls, set `data-shape="rounded"` for v0.38-era feel.
38
+ - **Pre-publish audit gate.** Components in `src/ui/` can no longer use `rounded-ds-*` or bare `rounded-full` — must use semantic roles. Composed/shell migration is v0.40.0 (gate scoped accordingly).
39
+ - See `customize-brand.md` recipe for the full role token list and how to define your own preset.
40
+
41
+ ## BREAKING CHANGES (v0.37.0 — Tailwind 4 CSS-first)
42
+
43
+ **Setup migration only — component APIs unchanged.** See `MIGRATION.md` at the root of this package (or https://github.com/devalok-design/shilp-sutra/blob/main/MIGRATION.md#v0370--tailwind-4-css-first-migration) for the full guide.
44
+
45
+ - **No more JS preset.** `tailwind.config.ts` with `presets: [shilpSutra]` is gone. Tokens ship as TW4 `@theme` CSS via a single CSS import. Consumer setup becomes:
46
+ ```css
47
+ @import "tailwindcss";
48
+ @import "@devalok/shilp-sutra/css";
49
+ ```
50
+ The `./tailwind` export has been removed in 0.38. Delete any `tailwind.config.ts` that referenced the preset and switch to the CSS import above.
51
+ - **framer-motion is now a required peer dep.** Previously bundled. Install: `pnpm add framer-motion`. Module-scoped React contexts (MotionConfig, LayoutGroup, AnimatePresence) must be single-copy — the peer declaration forces pnpm to dedupe against the consumer's version.
52
+ - **sonner is now an optional peer dep.** Install only if you render `<Toaster />`: `pnpm add sonner`.
53
+ - **tailwindcss peer tightened to `^4.0.0`.** No more `^3.4.0 || ^4.0.0`.
54
+ - **use-sync-external-store moved to our `dependencies`** (from optional peer). Auto-installed transitively.
55
+ - **Node engines floor dropped.** No `engines.node` declared — use any Node 18+.
56
+ - **New export `@devalok/shilp-sutra/css`** — primary consumer entry for TW4 setup.
57
+ - **Source class hygiene:** `w-[--var]` → `w-(--var)`, `theme(spacing.N)` → literal, `bg-gradient-to-*` → `bg-linear-to-*`, bare `shadow` → explicit like `shadow-raised`. Codemod your own code; grep: `grep -rn 'w-\[--\|bg-gradient-to-\|theme(spacing' src/`.
58
+ - **Tokens now expose TW4 namespaces.** Spacing is `--spacing-ds-*` (so `p-ds-03`, not `p-3`). Typography uses `--text-ds-*`, `--leading-ds-*`. Radius has TWO layers: primitive scale (`--radius-ds-sm/md/lg/xl/2xl/full`) AND semantic roles (`--radius-control`, `--radius-surface`, `--radius-overlay-sm/md/lg`, `--radius-pill`, `--radius-bubble`). Components reference roles — consumers swap roles via `[data-shape]` presets or override individual tokens. Z-layer utilities are custom-generated (`z-popover`, `z-dropdown`, etc.).
59
+ - **Dark mode variant:** `@custom-variant dark (&:where(.dark *))` — identical semantics to old `darkMode: 'class'`. `.dark` on `<html>` or `<body>` activates everything below.
60
+
61
+ ## NEW (v0.36.0)
62
+
63
+ - **Forced-colors (Windows high-contrast) support.** Every semantic color token remaps to system keywords (`Canvas`, `CanvasText`, `Highlight`, `HighlightText`, `LinkText`, `GrayText`, `Mark`, `ButtonText`, `VisitedText`) under `@media (forced-colors: active)`. Focus ring forced via `outline: 2px solid Highlight`, interactive elements get visible borders, decorative grain + skeleton shimmer suppressed. Zero runtime impact when inactive.
64
+ - **FormField auto-wires Label ↔ Input via context.** `<FormField>` now publishes an `inputId`; `<Label>` reads `htmlFor` and `<Input>` reads `id` from context unless either is explicit on the child. Drops the need to hand-generate matching ids.
65
+ - **Toast error assertive a11y.** `toast.error()` renders `role="alert"` + `aria-live="assertive"` + `aria-atomic="true"` so screen readers interrupt speech. Other types remain `role="status"` + polite.
66
+ - **Dev-mode missing-`<Toaster />` warning.** `toast()` called without a mounted `Toaster` logs a one-time console warning in dev. Production-silent.
67
+ - **Design default:** prefer `variant="soft"` over `variant="outline"` for non-primary Button actions. Captured in this file's Component Quick Reference and CLAUDE.md. Outline remains valid on colored bg, toolbars, primary-adjacent hierarchy.
68
+
69
+ ## FIXES (v0.36.0)
70
+
71
+ - **Alert solid body text illegible.** Was forcing `text-surface-fg-muted` (grey) on top of step-9 saturated bgs and using `text-accent-fg` for warning (white-on-amber failed contrast). Now per-color `text-{info|success|warning|error}-fg` on the root + drops the muted override on solid/filled variants.
72
+ - **Button processing ants drifting outside the button.** Overlay SVG now sized to measured `btnEl.offsetWidth/offsetHeight` with a `ResizeObserver` — no more `calc(100% - 2px)` against the wrapper diverging from the button during width transitions / async-feedback icon swaps.
73
+ - **Per-color `-fg` tokens on non-accent status backgrounds.** Button async success/error, BottomNavbar + TopBar error badges now use `text-error-fg` / `text-success-fg` (not `text-accent-fg`) — brand-swap safe.
74
+ - **Documentation truth fixes.** 6 `data-table-*.md` shipped literal bash template headers (`# $(echo $f | sed ...)`) in `llms-full.txt`; fixed. Button Props block had fake `variant="default"` / `"destructive"` alias claims (removed in 0.32.0); stripped. Badge `truncate` prop added to Props block. `packages/core/CHANGELOG.md` reconstructed from 0.33.x → 0.35.0. README component counts + tech stack updated.
75
+
76
+ ## BREAKING CHANGES (v0.35.0 — World-Class Audit)
77
+
78
+ - **Dark mode colors:** Solid variant backgrounds darkened for WCAG AA. Step-9 L=0.63→0.54. Warning amber L=0.72→0.57. All solid buttons/badges are noticeably darker in dark mode.
79
+ - **Responsive typography:** Heading sizes 3xl–6xl use `clamp()` for fluid scaling. Headings shrink on mobile.
80
+ - **Body letter spacing:** body-lg (-0.01em), body-md (0em), body-sm (+0.01em), body-xs (+0.02em). Was all -0.02em.
81
+ - **surface-fg-subtle:** Darkened from neutral-8 to neutral-9 in light mode. Tertiary text is more visible.
82
+ - **MessageList:** `isLoadingMore` renamed to `loadingMore`.
83
+ - **AppCommandPalette:** Default Karm routes removed. Use `CommandRegistryProvider` for page registration. `SearchResult` type adds optional `href` field.
84
+ - **NumberInput:** Shape changed from pill to rounded rectangle.
85
+ - **Dependencies:** `@floating-ui/dom`, `@tiptap/*`, `prosemirror-state` moved to devDeps (bundled; consumers no longer install them).
86
+
87
+ ## NEW (v0.35.0)
88
+
89
+ - **Size props:** Combobox (xs/sm/md/lg), NumberInput (xs/sm/md/lg + state), Slider (sm/md/lg + color), InputOTP (sm/md/lg + state).
90
+ - **Toggle color:** `color` prop on Toggle/ToggleGroup (accent/error/success/neutral).
91
+ - **Tabs vertical:** `orientation="vertical"` for side-nav layout.
92
+ - **Stepper clickable:** `onStepClick` callback for navigating to completed steps.
93
+ - **AlertDialog responsive:** `responsive` prop for mobile bottom-sheet.
94
+ - **Typography:** `code`, `label-plain-lg/md/sm` variants. Tailwind composite utilities: `text-heading-xl`, `text-body-md`, `text-code`, etc.
95
+ - **Layout spacing:** `--spacing-page-x` (responsive 16→24→40px), `--spacing-section-gap`, `--spacing-card-gap`.
96
+ - **Link colors:** `--color-link`, `--color-link-hover`, `--color-link-visited` tokens.
97
+ - **useFormField:** Now wired into Select, Combobox, Autocomplete, Checkbox, Radio, Switch, Slider, InputOTP.
98
+ - **Chart a11y:** Keyboard tooltip access on BarChart/LineChart. `ariaDescription` on ChartContainer.
99
+ - **Dev warnings:** Token-missing CSS detection + MotionProvider hint (dev mode only).
100
+
101
+ ## HISTORICAL: BREAKING CHANGES (v0.33.x — Tailwind 4 + Toolchain)
102
+
103
+ > **Note:** The v0.33 peer range `^3.4.0 || ^4.0.0` and `@config` directive requirement are superseded by v0.37 (TW4-only, CSS-first, no `@config`). Keep reading if you're upgrading from < 0.33; otherwise skip to v0.37 above.
104
+
105
+ - **Tailwind CSS 3 → 4:** `outline-none` → `outline-hidden`, `rounded-sm` → `rounded-xs`, `backdrop-blur-sm` → `backdrop-blur-xs`, `!prefix` → `suffix!` important syntax. Consumers using our preset: add `@import "tailwindcss"` + `@config` to your CSS, replace `darkMode: 'class'` with `@variant dark (&:is(.dark *))` in CSS. Peer dep accepts both `^3.4.0 || ^4.0.0`.
106
+ - **tailwind-merge 3.0 → 3.5:** Required for TW4 class recognition.
107
+ - **TypeScript 5.7 → 6.0.2:** `types` defaults to `[]` in TS6. Add explicit `"types": ["node"]` to tsconfig if needed.
108
+ - **ESLint 9 → 10:** Config file lookup starts from linted file directory (not CWD). Verify monorepo configs.
109
+ - **react-zoom-pan-pinch 3 → 4:** `onTransformed` renamed to `onTransform`. Peer dep `^3.0.0 || ^4.0.0`.
110
+
111
+ ## CHANGES (v0.33.1 / v0.33.2)
112
+
113
+ - Bumped: React 19.2.5, Storybook 10.3.5, Vitest 4.1.4, framer-motion 12.38, @floating-ui/dom 1.7.6, @tabler/icons-react 3.41.1, esbuild 0.28, jsdom 29, Playwright 1.59.1, PostCSS 8.5.9, Prettier 3.8.2, vite-plugin-dts 4.5.4.
114
+
115
+ ## BREAKING CHANGES (v0.33.0)
116
+
117
+ - **EmojiSuggestion:** Named export removed. Use `createEmojiSuggestion(set?)` factory. Default: `createEmojiSuggestion()` (native set).
118
+ - **Emoji HTML output:** Non-native `emojiSet` renders emoji as `<span data-emoji-id="..." data-emoji-set="..." role="img">native</span>` nodes, not raw Unicode. `plainText` still returns Unicode.
119
+
120
+ ## CHANGES (v0.33.0)
121
+
122
+ - **RichChatInput v2** — Complete rewrite. Structured output (`html`, `plainText`, `attachments?`, `voiceNote?`). Zone architecture. 4 variants: `compact` (default), `expanded`, `minimal`, `inline`. Props: `onSubmit`, `onSchedule?(msg, date)`, `mentions?`, `slashCommands?`, `onFileUpload?`, `onImageUpload?`, `onVoiceRecord?`, `onTranscribe?`, `replyTo?`, `toolbar?`, `emojiSet?`, `actionButton?`, `enterBehavior?`, `maxLength?`, `isStreaming?`, `disclaimer?`, `sendOptions?`, `leadingSlot?`, `trailingSlot?`.
123
+ - **Custom EmojiNode** — TipTap inline atom node. Renders emoji via spritesheet images for consistent Apple/Google/Twitter/Facebook art styles. `emojiSet` prop on `EmojiPicker`, `EmojiPickerPopover`, `RichChatInput`, `RichTextEditor`. Sets: `native` (default), `apple`, `google`, `twitter`, `facebook`.
124
+ - **SplitButton** (`ui/`) — `[Action | ▼]` button with dropdown. Props: `variant(solid|soft|outline)`, `color`, `size`, `triggerSide(left|right)`, `triggerWidth`, `placement` (Floating UI), `dropdownContent`. Proper ARIA: `role="group"`, `aria-haspopup`, `aria-expanded`.
125
+ - **Schedule Send** — `onSchedule?(msg, date)` on RichChatInput. Smart presets (time-of-day aware) + DateTimePicker. Banner shows scheduled time. Send button morphs to SplitButton.
126
+ - **ButtonGroup rebuild** — Compound component pattern. Button reads position from context, applies radius inline. New props: `disabled` (propagates), `attached` (true/false), `fullWidth`. Tonal dividers for solid/soft/ghost variants. Focus z-index isolation.
127
+ - **TipTap v2 → v3** — `useEditorState`, `immediatelyRender: false` (SSR-safe), `ListKit`. Fixes React 19 `removeChild` crash.
128
+ - **Composable toolbar** — Exported: `ToolbarButton`, `ToolbarDivider`, `ToolbarGroup`, `BoldButton`, `ItalicButton`, `UnderlineButton`, `StrikeButton`, `HighlightButton`, `CodeButton`, `BulletListButton`, `OrderedListButton`, `BlockquoteButton`, `LinkButton`, `EmojiButton`.
129
+ - **Button `disabled`** — Now inherited from ButtonGroup context.
130
+
131
+ ## BREAKING CHANGES (v0.32.0)
132
+
133
+ - **Button:** `variant="default"` removed (use `"solid"`), `variant="destructive"` removed (use `variant="solid" color="error"`), `color="default"` removed (use `"accent"`).
134
+ - **Chip:** Removed. Use `Badge` instead.
135
+ - **SegmentedControl:** Rewritten. Variants are `"default"` (white pill) and `"solid"` (brand pill). `SegmentedControlItem` no longer exported.
136
+ - **TopBar:** Now renders as `<header>` (was `<div>`).
137
+ - **Sidebar:** Now renders as `<aside>` (was `<div>`).
138
+ - **InfoBlock:** `role="status"` (was `role="alert"`).
139
+ - **Border tokens:** One step darker system-wide.
140
+ - **Dark mode button text:** Pure white `neutral-0` (#fff) on brand-colored buttons.
141
+ - **BottomNavbar:** Bottom padding is now `pb-safe` (safe-area-inset).
142
+ - **iOS inputs:** Forced to `font-size: max(16px, 1em)` on mobile via preset.
143
+
144
+ ## CHANGES (v0.32.0)
145
+
146
+ - **Mobile Responsiveness:**
147
+ - Dialog auto-fullScreens on mobile (<768px). Opt out: `<DialogContent responsive={false}>`.
148
+ - Sheet auto-bottom with swipe-to-dismiss on mobile. Drag handle, 30% threshold. Opt out: `<SheetContent responsive={false}>`.
149
+ - Popover renders as bottom drawer on mobile automatically.
150
+ - `.touch-target` utility — 44px invisible hit area for Apple HIG compliance.
151
+ - `.pt-safe`, `.pb-safe`, `.pl-safe`, `.pr-safe`, `.p-safe` — safe area inset utilities.
152
+ - `useTouchDevice()` — detects touch capability (vs viewport width).
153
+ - `useViewportHeight()` — dynamic viewport height via Visual Viewport API.
154
+ - Sidebar has swipe-to-close on mobile.
155
+ - **DataTable `mobileView="card"`** — Rows render as stacked cards below 640px. First column = card title, rest = label-value pairs.
156
+ - **DataTable `aria-sort`** — Sortable column headers include `aria-sort`.
157
+ - **Charts `ariaLabel` prop** — Configurable screen reader label on all chart components.
158
+ - **SegmentedControl** — Redesigned: `variant="default"` (white pill + shadow-raised) | `variant="solid"` (brand pill). Inset radius, snappy spring animation.
159
+ - **`--shadow-kbd` token** — Keyboard shortcut badge shadow. Use `shadow-kbd` utility.
160
+ - **Checkbox/Radio `size` prop** — `sm | md (default) | lg`.
161
+
162
+ ## CHANGES (v0.31.0)
163
+ - **Alert `size` prop** — `sm | md (default) | lg`. Scales padding, gap, icon, text.
164
+ - **Card `color` prop** — `default | accent | error | success | warning | info | neutral`. Semantic border color.
165
+ - **Card `size` prop** — `sm | md (default) | lg`. Propagated to sub-components via context.
166
+ - **Select `variant` prop** — `default | outline | ghost` on SelectTrigger.
167
+ - **Select `color` prop** — `default | error | success | warning` on SelectTrigger. Sets `aria-invalid` when error.
168
+ - **Tabs `color` prop** — `accent (default) | neutral`. Affects line variant indicator.
169
+ - **Tabs `size` prop** — `sm | md (default) | lg`. Scales height and padding.
170
+ - **Badge `truncate` prop** — Enables ellipsis truncation. Combine with fixed width or `maxWidth`.
171
+ - **New subpath exports** — `./ui/icon`, `./ui/icon-context`, `./ui/icon-group`, `./ui/badge-group`, `./ui/badge-indicator`, `./ui/devalok-grain`, `./ai/types`.
172
+ - **Server-safe fix** — `empty-state`, `priority-indicator`, `status-badge` now correctly get `"use client"` (were incorrectly omitted).
173
+ - **Server-safe detection** — Hardcoded allowlist replaced with `// @server-safe` source annotations.
174
+
175
+ ## CHANGES (v0.30.0)
176
+ - **RichTextEditor `toolbar` prop** — `toolbar?: ToolbarItem[]` whitelist of toolbar items to display. Omit to show all (default). `ToolbarItem` type exported.
177
+ - **`@devalok/shilp-sutra-karm` removed** — Domain components moved to Karm app repo. npm package deprecated.
178
+ - **Warning dark mode fixed** — `warning-*` tokens now have proper dark mode values (higher chroma than category amber).
179
+ - **tailwind-merge fix** — All `text-ds-*` sizes now correctly registered. `cn('text-ds-lg', 'text-accent-11')` no longer strips the color.
180
+ - **AvatarGroup fixes** — Overflow badge text matches avatar size, indicator dots scale with size, aria-labels added.
181
+
182
+ ## BREAKING CHANGES (v0.27.0 — Externalized Dependencies)
183
+
184
+ FilePreview and MarkdownViewer dependencies are now **external** (not bundled).
185
+ Install them if you use these components:
186
+
187
+ ```bash
188
+ pnpm add react-pdf react-zoom-pan-pinch react-syntax-highlighter
189
+ ```
190
+
191
+ These are optional peerDependencies — consumers who don't use FilePreview or MarkdownViewer are unaffected.
192
+
193
+ **Next.js optimization:** Add to your `next.config.js`:
194
+ ```js
195
+ optimizePackageImports: ['@devalok/shilp-sutra']
196
+ ```
197
+
198
+ ## BREAKING CHANGES (v0.23.0 — Semantic Surface & Shadow Tokens)
199
+
200
+ **Surface tokens renamed:** Numeric `surface-1..4` replaced with semantic names.
201
+ | Old | New | Usage |
202
+ |-----|-----|-------|
203
+ | `bg-surface-1` | `bg-surface-base` | Page background |
204
+ | `bg-surface-1` | `bg-surface-sunken` | Shell chrome (sidebar, topbar), board columns |
205
+ | `bg-surface-1` | `bg-surface-overlay` | Dialogs, popovers, dropdowns, inputs |
206
+ | `bg-surface-2` | `bg-surface-raised` | Cards, widgets, panels |
207
+ | `bg-surface-3` | `bg-surface-raised-hover` | Hover states on raised elements |
208
+ | `bg-surface-4` | `bg-surface-raised-active` | Active/pressed states |
209
+
210
+ Same pattern for `border-surface-*`, `text-surface-*`, `ring-surface-*`.
211
+
212
+ **Shadow tokens renamed:** Numeric `shadow-01..05` replaced with semantic names.
213
+ | Old | New |
214
+ |-----|-----|
215
+ | `shadow-01` | `shadow-raised` |
216
+ | `shadow-02` | `shadow-raised-hover` |
217
+ | `shadow-03` | `shadow-floating` |
218
+ | `shadow-04` | `shadow-overlay` |
219
+ | `shadow-05` | (removed — was unused) |
220
+
221
+ **New surface tokens:**
222
+ - `bg-surface-sunken` — recessed areas (sidebar, board columns, segmented track)
223
+ - `bg-surface-overlay` — floating elements (dialogs, popovers, inputs). Diverges from base in dark mode.
224
+ - `bg-surface-inverted` / `text-surface-inverted-fg` — tooltips, inverted badges
225
+ - `bg-surface-disabled` / `text-surface-fg-disabled` — disabled elements
226
+ - `border-surface-border-subtle` — hairline dividers
227
+ - `bg-backdrop` — dialog/sheet backdrop overlay
228
+
229
+ **New shadow tokens:**
230
+ - `shadow-glow` — selection/focus accent glow
231
+ - `shadow-inset` — toggle/segmented track deboss
232
+ - `shadow-ring` / `shadow-ring-sm` — focus ring / subtle separator
233
+
234
+ **Hard rule: never combine explicit border + shadow.** Shadows include a 1px ring layer. Adding a CSS border creates a 2px edge. Use shadow OR border, never both.
235
+
236
+ **Breaking:** Old numeric aliases (`--color-surface-1..4`, `--shadow-01..05`, Tailwind `bg-surface-1..4`, `shadow-01..05`) have been removed. Use the semantic names listed above.
237
+
238
+ **Component Decision Matrix:**
239
+ | Building... | Surface | Shadow |
240
+ |-------------|---------|--------|
241
+ | Page/layout | `surface-base` | none |
242
+ | Shell (sidebar/topbar) | `surface-sunken` | `shadow-raised` |
243
+ | Card/widget/panel | `surface-raised` | `shadow-raised` |
244
+ | Card hover | `surface-raised` | `shadow-raised-hover` |
245
+ | Board column/well | `surface-sunken` | none |
246
+ | Popover/menu/dropdown | `surface-overlay` | `shadow-floating` |
247
+ | Dialog/modal/sheet | `surface-overlay` | `shadow-overlay` |
248
+ | Tooltip | `surface-inverted` | `shadow-floating` |
249
+ | Toast | `surface-overlay` | `shadow-floating` |
250
+ | Input (rest) | `surface-overlay` | none |
251
+ | Input (focus) | `surface-overlay` | `shadow-ring` |
252
+ | Button (solid) | accent colors | `shadow-raised` |
253
+ | Button (disabled) | `surface-disabled` | none |
254
+ | Segmented track | `surface-sunken` | `shadow-inset` |
255
+ | Selected item | current surface | `shadow-glow` |
256
+
257
+ ## BREAKING CHANGES (v0.18.0 — Framer Motion + OKLCH)
258
+
259
+ **New runtime dependency:** `framer-motion@^12.36.0` (bundled). Karm consumers must install `framer-motion@^12.0.0` as peer dep.
260
+
261
+ **Transitions removed:** `Fade`, `Collapse`, `Grow`, `Slide` from `./ui/transitions` no longer exist. Use `MotionFade`, `MotionCollapse`, `MotionSlide` from `@devalok/shilp-sutra/motion/primitives`.
262
+
263
+ **CSS keyframe animations removed:** 18 keyframes (`fade-in`, `fade-out`, `slide-up`, `scale-in`, etc.) and their `animate-*` utilities removed from Tailwind preset. Use motion primitives instead.
264
+
265
+ **`useReducedMotion()` removed:** Use `<MotionProvider reducedMotion="user">` at app root.
266
+
267
+ **New motion system:**
268
+ - `import { MotionProvider, springs, tweens } from '@devalok/shilp-sutra/motion'`
269
+ - `import { MotionFade, MotionCollapse, MotionSlide, MotionPop, MotionScale, MotionStagger } from '@devalok/shilp-sutra/motion/primitives'`
270
+ - Springs: `springs.snappy`, `springs.smooth`, `springs.bouncy`, `springs.gentle`
271
+ - Tweens: `tweens.fade`, `tweens.colorShift`
272
+
273
+ **Spinner v2:** New props `state?: 'spinning' | 'success' | 'error'`, `variant?: 'filled' | 'bare'`, `delay?: number`, `onComplete?: () => void`
274
+
275
+ **Button `onClickAsync`:** New prop `onClickAsync?: (e) => Promise<void>` — auto-manages loading → success/error → idle states. `asyncFeedbackDuration?: number` (default 1500ms).
276
+
277
+ **Server safety changes:** EmptyState, StatusBadge, PriorityIndicator, Spinner are NOT server-safe (they use Framer Motion). Do NOT import from RSC.
278
+
279
+ **Build:** `framer-motion` and `sonner` moved from `dependencies` to `devDependencies` (bundled at build time — no consumer install needed for core).
280
+
281
+ **New APIs in v0.18.0:**
282
+ - Combobox: `accessibleLabel?: string` — custom aria-label for trigger (falls back to placeholder)
283
+ - Slider: multi-thumb support — pass array `defaultValue={[25, 75]}` for range sliders
284
+
285
+ ## CHANGES (v0.16.0)
286
+ - **DataTable server-side features**: `onSort` callback (manual sorting), `pagination` prop (server-side pagination with page/total/onPageChange), `selectedIds` + `selectableFilter` (controlled selection), `loading` shimmer, `emptyState` ReactNode, `singleExpand`, `stickyHeader`, `onRowClick`, `bulkActions` floating bar
287
+ - **DataTable display**: `density?: 'compact' | 'standard' | 'comfortable'` (compact=4px padding, standard=16px, comfortable=32px). `toolbar?: boolean` (column visibility + density + export controls). Column `meta: { align: 'right' }` for numeric columns (auto-applies text-right tabular-nums). Column `meta: { hideBelow: 'md' }` for responsive column hiding (hidden below breakpoint). `selectableFilter?: (row) => boolean` to disable selection on certain rows (e.g. only PENDING rows selectable).
288
+ - **ActivityFeed**: New composed component — `@devalok/shilp-sutra/composed/activity-feed` — vertical timeline with colored dots, actor avatars, expandable detail, compact mode, load more
289
+ - EmptyState: `iconSize?: 'sm' | 'md' | 'lg'` prop for icon dimension control
290
+ - BottomNavbar: `badge?: number` on BottomNavItem for notification counts (99+ cap)
291
+ - AppSidebar: `preFooterClassName?: string` for scrollable preFooterSlot
292
+
293
+ ## CHANGES (v0.15.0)
294
+ - **Input font standardization**: All input sizes (sm, md, lg) now use text-ds-md (14px). Previously lg used text-ds-lg (18px). Affects Input, Select, SearchInput, Textarea.
295
+ - CommandPalette: Staggered slide-up animations for items, fade-in for groups, scale-in search icon, active item color transitions
296
+
297
+ ## CHANGES (v0.14.0)
298
+ - **BREAKING z-index**: Select, Combobox, Autocomplete, DropdownMenu, ContextMenu, Menubar, HoverCard promoted from z-dropdown (1000) to z-popover (1400). Fixes dropdowns rendering behind Sheet/Dialog. If you had custom z-index overrides (e.g. `[data-radix-popper-content-wrapper] { z-index: 1400 !important }`) you can now remove them.
299
+ - TabsTrigger: Added gap-ds-02 (4px) between icon and label
300
+ - AppSidebar: footer.version now accepts string | { label, href } for clickable version links
301
+
302
+ ## CHANGES (v0.13.0)
303
+ - EmptyState: icon prop now accepts ComponentType (e.g. Tabler icon references) in addition to ReactNode
304
+ - NotificationCenter: Notification.actions?: NotificationAction[] — inline action buttons (Approve/Deny) per notification
305
+ - NotificationCenter: Tier dot now doubles as read/unread marker; separate unread dot removed
306
+ - AppSidebar: footer.promo?: SidebarPromo — dismissable promo banner with icon, text, action button
307
+ - AppSidebar: Footer links + version render on same line with · dividers
308
+ - Collapsible: Now uses height-based expand/collapse animation (animate-collapsible-down/up)
309
+ - Tailwind preset: 4 new keyframes + utilities — accordion-down, accordion-up, collapsible-down, collapsible-up
310
+
311
+ ## CHANGES (v0.12.0)
312
+ - Input: Softer resting border (border-subtle instead of border), subtler focus ring (ring-1 ring-focus/50 instead of ring-2 ring-focus)
313
+ - Tailwind preset: 9 animation keyframes + utilities (fade-in, fade-out, slide-up, slide-right, scale-in, scale-out, glow-pulse, scale-bounce, lift)
314
+ - Tailwind preset: Stagger plugins — .delay-stagger (30ms × --stagger-index), .delay-stagger-50 (50ms × --stagger-index)
315
+
316
+ ## BREAKING CHANGES (v0.11.0 — dark mode)
317
+ - Dark mode interactive colors shifted: --color-interactive pink-400→pink-500, --color-interactive-hover pink-300→pink-600, --color-interactive-active pink-200→pink-700, --color-interactive-subtle pink-950→pink-1000
318
+ - Dark mode text status colors shifted: --color-text-error red-200→red-300, --color-text-success green-200→green-300, --color-text-warning yellow-200→yellow-300, --color-text-link blue-200→blue-300, --color-text-brand pink-300→pink-400
319
+ - New primitive token: --pink-1000 (#150208) near-black
320
+
321
+ ## BREAKING CHANGES (v0.8.0)
322
+ - Combobox: Now uses discriminated union. Single: `multiple?: false, value: string, onValueChange: (v: string) => void`. Multiple: `multiple: true, value: string[], onValueChange: (v: string[]) => void`. No more `v as string[]` casts.
323
+ - StatusBadge: Pass either `status` OR `color`, not both (discriminated union).
324
+ - Input/Textarea: Now auto-inherit state, aria-describedby, aria-required from FormField context. Explicit props override.
325
+
326
+ ## BREAKING CHANGES (v0.18.0 — OKLCH token migration, continued)
327
+ - All color primitives migrated from hex (50-950 shades) to OKLCH (12 functional steps)
328
+ - Old shade numbers: --pink-50..950. New step numbers: --pink-1..12 (OKLCH values)
329
+ - Step purposes: 1=app-bg, 2=subtle-bg, 3=component-bg, 4=hover, 5=active, 6=border-subtle, 7=border, 8=border-strong, 9=solid/accent, 10=solid-hover, 11=lo-contrast-text, 12=hi-contrast-text
330
+ - New semantic tokens: --color-accent-{1-12}, --color-secondary-{1-12}, --color-surface-{base,raised,raised-hover,raised-active,sunken,overlay,inverted,disabled}, --color-surface-fg/fg-muted/fg-subtle/border/border-subtle
331
+ - Status tokens: --color-error-{3,7,9,11,fg}, --color-success-{3,7,9,11,fg}, --color-warning-{3,7,9,11,fg}, --color-info-{3,7,9,11,fg}
332
+ - New Tailwind utilities: accent-1..12, secondary-1..12, surface-base/raised/sunken/overlay/inverted/disabled, status/category step utilities
333
+ - Backward compat: ALL old semantic token names preserved as aliases. --color-interactive still works → maps to --color-accent-9
334
+ - Consumer rebranding: override --color-accent-1..12 CSS vars OR use generateScale() utility with a seed color
335
+ - Dark mode: algorithmically derived (OKLCH curves), NOT hex overrides. Surfaces lighten with elevation.
336
+ - If you reference --pink-500 etc directly, migrate: 50→1, 100→2, 200→3, 300→4, 400→5, 500→7, 600→8, 700→9, 800→10, 900→11, 950→12
337
+
338
+ ## v0.22.0 — UI Polish & Micro-Refinement
339
+
340
+ **Shadows**: All shadow tokens now use 3-layer stacks. Visual change only — same token names. Shadow tokens renamed in v0.23.0 (see breaking changes above).
341
+
342
+ **Transitions**: All CSS transitions use `ease-productive-standard` easing. Tween presets aligned: `tweens.fade` = 0.11s, `tweens.colorShift` = 0.07s.
343
+
344
+ **New Tailwind utilities**:
345
+ - `.focus-ring` — double-ring (2px surface + 2px accent), use on custom interactive elements (buttons, cards)
346
+ - `.focus-ring-inset` — inset ring, use on buttons over solid backgrounds
347
+ - `.focus-ring-sm` — 1px subtle ring, use on inputs and small controls
348
+ - `.tabular-nums` — aligned numbers via `font-variant-numeric: tabular-nums`
349
+
350
+ **Category color utilities** (standalone, not tied to Badge/Chip):
351
+ - 7 colors: teal, amber, slate, indigo, cyan, orange, emerald
352
+ - 4 steps each: bg-category-{color}-{3|7|9|11}, text-category-{color}-{3|7|9|11}, border-category-{color}-{3|7|9|11}
353
+ - Use for: board column accents, status indicators, tag colors, category chips
354
+
355
+ **Dense size variant (xs)** added to Input, Select, SearchInput, Button, Textarea:
356
+ - xs = 28px height (h-ds-xs-plus), 12px text (text-ds-sm), compact padding
357
+ - Designed for filter bars, toolbar controls, and dense UI contexts
358
+ - Button also gets icon-xs (28×28) for compact icon buttons
359
+ - Size matrix: xs=28px | sm=32px | md=40px (default) | lg=48px
360
+
361
+ **Separator**: New `variant` prop — `"gradient" | "gradient-left" | "gradient-right"`. Default unchanged.
362
+
363
+ **Checkbox**: Path-draw animation (stroke draws progressively). Uncontrolled usage now works.
364
+
365
+ **Tooltip**: Auto-wraps with `<TooltipProvider>` — no manual provider needed. Text color fixed for dark mode.
366
+
367
+ **Avatar fallback**: Now respects `shape` prop (was always circle). Font size auto-scales with avatar size (v0.22.3).
368
+
369
+ **AvatarGroup renderAvatar**: Wrapper is positioning-only — pass `size` directly to your Avatar, do NOT use `className="h-full w-full"` (v0.22.3).
370
+
371
+ **New hover states**: Checkbox, Radio, Switch track, Select items, DropdownMenu items, Combobox trigger.
372
+
373
+ ## AI Command System (v0.25.0+)
374
+
375
+ New `@devalok/shilp-sutra/ai` module — composable AI command interface.
376
+
377
+ **CommandBar** — Unified input (hero/inline/floating variants):
378
+ ```tsx
379
+ <CommandBar
380
+ variant="hero"
381
+ onSubmit={(query) => sendToAI(query)} // AI submission
382
+ groups={commandGroups} // optional command palette filtering
383
+ state="idle" // idle | typing | processing | responded
384
+ greeting="Good morning, Mudit."
385
+ hints={['Add member...', 'Check status...']}
386
+ agentName="Devadoot"
387
+ agentIcon={<DevadootIcon state={iconState} />}
388
+ >
389
+ <AIConversation messages={messages} isProcessing={loading} />
390
+ </CommandBar>
391
+ ```
392
+
393
+ **BlockRenderer** — Renders AI response JSON as DS components:
394
+ ```tsx
395
+ <BlockRenderer blocks={response.blocks} onAction={handleAction} customBlocks={myBlocks} />
396
+ ```
397
+
398
+ Block types: `text`, `table`, `confirm`, `success`, `error`, `info`, `loading`, `divider`, `stat_row`.
399
+
400
+ **AICommandProvider** — Optional context wrapper:
401
+ ```tsx
402
+ <AICommandProvider customBlocks={karmBlocks} onAction={handle} agent={{ name: 'Devadoot' }}>
403
+ {/* CommandBar + AIConversation auto-wire from context */}
404
+ </AICommandProvider>
405
+ ```
406
+
407
+ **DevadootIcon** — Animated Devalok chakra with gradient state animations:
408
+ ```tsx
409
+ <DevadootIcon state="processing" size={20} /> // idle | processing | responded | error
410
+ ```
411
+
412
+ ## Install & Setup
413
+
414
+ pnpm add @devalok/shilp-sutra
415
+
416
+ ### Next.js Setup (Required for Next.js + pnpm)
417
+
418
+ Add to next.config.js:
419
+ ```js
420
+ transpilePackages: ["@devalok/shilp-sutra", "@devalok/shilp-sutra-brand"]
421
+ ```
422
+
423
+ // Import components (barrel):
424
+ import { Button, Card, Dialog } from '@devalok/shilp-sutra'
425
+
426
+ // Import per-component (recommended for Server Components):
427
+ import { Button } from '@devalok/shilp-sutra/ui/button'
428
+ import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
429
+ import { TopBar } from '@devalok/shilp-sutra/shell/top-bar'
430
+
431
+ // Chat primitives (v0.29.0+):
432
+ import { MessageList, Message, SystemMessage, MessageInput, DateSeparator, UnreadSeparator, TypingIndicator } from '@devalok/shilp-sutra/ui/chat'
433
+
434
+ // AI command system (v0.25.0+):
435
+ import { CommandBar, AIConversation, BlockRenderer, AICommandProvider, DevadootIcon } from '@devalok/shilp-sutra/ai'
436
+
437
+ // Toast (imperative, no hook needed):
438
+ import { toast } from '@devalok/shilp-sutra/ui/toast'
439
+
440
+ // Hooks:
441
+ import { useColorMode } from '@devalok/shilp-sutra/hooks/use-color-mode'
442
+
443
+ // CSS tokens (import once at app root — already included in /css):
444
+ import '@devalok/shilp-sutra/css'
445
+
446
+ ## CRITICAL: Differences from shadcn/ui
447
+
448
+ If you have shadcn/ui knowledge, these are the differences that WILL trip you up:
449
+
450
+ | shadcn/ui pattern | shilp-sutra equivalent | Notes |
451
+ |---|---|---|
452
+ | variant="destructive" | color="error" | Two-axis system: variant=shape, color=intent |
453
+ | size="default" | size="md" | All sizes: sm, md, lg (never "default") |
454
+ | <Select size="lg"> | <SelectTrigger size="lg"> | Size goes on trigger, NOT root |
455
+ | <Chip> | <Badge onClick={...}> | Chip is deprecated, use Badge with onClick |
456
+ | useToast() + toast({ variant }) | toast.success('msg') | Imperative API, no hook needed |
457
+ | Badge variant="destructive" | Badge variant="solid" color="error" | Two-axis: variant + color |
458
+ | Alert + AlertTitle + AlertDescription | <Alert title="..." color="error"> | Single component, not compound |
459
+ | Form + FormField + FormItem + FormLabel + FormControl + FormDescription + FormMessage | FormField + Label + Input + FormHelperText + useFormField() | Simpler API, hook-based a11y wiring |
460
+ | Pagination | PaginationRoot | Root component name differs |
461
+
462
+ ### The Two-Axis Variant System
463
+
464
+ Many components use TWO props where shadcn uses one:
465
+ - `variant` controls SHAPE/SURFACE: solid, outline, ghost, subtle, filled, etc.
466
+ - `color` controls INTENT/SEMANTICS: default, error, success, warning, info, etc.
467
+
468
+ Examples:
469
+ <Button variant="solid" color="error">Delete</Button> // red solid button
470
+ <Button variant="soft" color="warning">Pending</Button> // amber tinted button
471
+ <Button variant="soft" color="accent">Cancel</Button> // preferred for secondary actions
472
+ <Badge variant="solid" color="success">Active</Badge> // green solid badge
473
+ <Alert variant="solid" color="warning">Warning!</Alert> // amber filled alert
474
+
475
+ **Design preference (Devalok default):** for **secondary** Button actions, reach for `variant="soft"` before `variant="outline"`. Soft feels warmer, brand-consistent, and reads better in data-dense UIs. Use `outline` only when soft's tint would disappear (colored bg, surface-raised), in toolbar/icon-dense contexts, or when you need outline's stronger hierarchy next to a primary action.
476
+
477
+ Components with two-axis system: Button, Badge, Alert, Banner, Progress, StatusBadge
478
+
479
+ ## Component Quick Reference
480
+
481
+ ### Inputs & Controls
482
+ - Button: variant(solid|soft|outline|ghost|link) color(accent|error|success|warning|neutral) size(xs|sm|md|lg|compact-xs|compact-sm|compact-md|icon-xs|icon-sm|icon-md|icon-lg) shape(default|pill) weight(semibold|normal) + loading, startIcon, endIcon, asChild, processing?('ambient'|'working'|'urgent'|boolean — marching ants SVG border, forces soft variant), processingColor?('accent'|'error'|'success'|'warning'|'neutral'), processingDisabled?(boolean, default true — set false for cancel-by-click). onClickAsync auto-activates processing='working' during loading phase. Layout animation always on. Deprecated aliases still work: variant="default"→solid, variant="destructive"→solid+error, color="default"→accent
483
+ - IconButton: icon(ReactNode, required) shape(square|circle) size(sm|md|lg) + aria-label required
484
+ - SplitButton: [Action | ▼] button with dropdown. Props: variant(solid|soft|outline), color, size(xs|sm|md|icon-xs|icon-sm|icon-md), triggerSide(left|right, default right), triggerWidth?(number|string), placement?(Floating UI Placement, default top-end), dropdownContent(ReactNode), open?, onOpenChange?, dropdownLabel?, dropdownIcon?. ARIA: role="group", aria-haspopup="menu", aria-expanded.
485
+ - ButtonGroup: Visually merges adjacent Buttons. Props: variant, color, size, disabled (propagates), orientation(horizontal|vertical), attached(true|false, default true), fullWidth. Compound pattern: Button reads position from context, applies radius + border-removal inline. Tonal dividers for solid/soft/ghost. Focus z-index isolation.
486
+ - Icon: `<Icon icon={IconPlus} />` — context-aware wrapper for Tabler icons. Size tiers: xs(14px) sm(16px) md(18px) lg(20px) xl(24px) 2xl(32px). Default: md. Stroke: light(1.5) regular(2) bold(2.5). Default: regular. Scales per size tier. Reads size from parent Button/IconGroup via IconContext. Explicit props override. Accessibility: aria-hidden by default. Pass label="Add item" for accessible icons. Animation: animate="spin|pulse|bounce|draw". `draw` renders SVG path-draw animation (check/X icons draw progressively via pathLength; other icons fall back to static). State machine: state="idle|loading|success|error". Button integration: startIcon={<Icon icon={IconPlus} />} (NOT raw <IconPlus />). IconGroup: <IconGroup size="sm" gap="tight"> for toolbar patterns.
487
+ - Input: size(xs|sm|md|lg) state(InputState) + startSection(ReactNode), endSection(ReactNode), startSectionClickable(bool), endSectionClickable(bool), startSectionType('icon'|'label'), endSectionType('icon'|'label'), wrapperClassName(string). Container-level focus ring wraps input + sections as one unit. Sections are pointer-events-none by default; use *SectionClickable for interactive content (clear buttons, toggles). Section type auto-inferred: strings→'label' (tinted bg + border separator), React elements→'icon' (fixed-width centered). Override with *SectionType. Flexbox section layout. Icons auto-size via IconProvider per input size. className targets <input>, wrapperClassName targets wrapper div. Type: InputState = 'default' | 'error' | 'warning' | 'success'
488
+ - SearchInput: size(xs|sm|md|lg) + loading, onClear. Delegates to Input v2 sections internally.
489
+ - NumberInput: value + onValueChange, min, max, step (controlled only)
490
+ - Textarea: size(xs|sm|md|lg) state(default|error|warning|success)
491
+ - ColorInput: value(hex string) onChange(value) presets({hex,label}[]|string[]|false, default: 10 named colors) variant('default'|'inline') showPicker(boolean, default:true) defaultFormat('hex'|'rgb'|'hsl') align('start'|'center'|'end') disabled. Popover trigger opens interactive picker (react-colorful) + format switcher + preset swatches + undo/reset. Inline variant renders entire trigger as the color with contrast-aware text.
492
+ - Checkbox: checked, onCheckedChange, error(boolean), indeterminate(boolean)
493
+ - Switch: checked, onCheckedChange, error(boolean), size(sm|md|lg), color(accent|success|warning), thumbIcon(ReactNode)
494
+ - RadioGroup > RadioGroupItem(value)
495
+ - Select > SelectTrigger(size: xs|sm|md|lg) > SelectValue; SelectContent > SelectItem(value)
496
+ - Toggle: variant(default|outline) size(sm|md|lg)
497
+ - ToggleGroup > ToggleGroupItem (variant/size propagate from root)
498
+ - SegmentedControl: variant(default|solid) size(sm|md|lg) options selectedId onSelect. Types: SegmentedControlOption = { id, text, icon? }, SegmentedControlSize = 'sm' | 'md' | 'lg', SegmentedControlVariant = 'default' | 'solid'
499
+ - Slider: standard Radix slider
500
+
501
+ ### Feedback & Notifications
502
+ - Alert: variant(subtle|solid|outline) color(info|success|warning|error|neutral) size(sm|md|lg) + title, onDismiss
503
+ - Banner: color(info|success|warning|error|neutral) + actions?(ReactNode), onDismiss. Mobile flex-wrap for multiple buttons.
504
+ - Toast: imperative API via toast.success/error/warning/info/loading/message/undo/promise/upload/custom — REQUIRES <Toaster> at layout root
505
+ - Spinner: size(sm|md|lg) — renders with role="status"
506
+ - Progress: track size(sm|md|lg), indicator color(default|success|warning|error), autoColor(boolean, auto-shifts color by value: 0-59=default, 60-84=warning, 85-100=success, >100=error)
507
+
508
+ NOTIFICATION SELECTION GUIDE:
509
+ - Alert: inline contextual feedback within a form or page section
510
+ - Banner: persistent page-level notification above content
511
+ - Toast: transient notification triggered by user action (needs <Toaster>, then call toast.success() etc.)
512
+
513
+ ### Data Display
514
+ - Badge: variant(subtle|solid|outline|soft) color(default|accent|error|success|warning|info|neutral + 7 category colors + custom) size(xs|sm|md|lg) + onClick, onDismiss, selected, disabled, dot, startIcon, endIcon, maxWidth, circle, asChild. Compound: Badge.Indicator(count, max, dot, color, invisible, showZero, placement, children), Badge.Group(max, gap, size, onOverflowClick, children). Custom colors: color="custom" + style={{'--badge-color':'#hex'}}. Grain-ready (has relative/overflow-hidden/isolate).
515
+ - Chip: DEPRECATED — Use `<Badge onClick={...}>` instead. Chip wrapper maps label prop to children for backward compat.
516
+ - Avatar: size(xs|sm|md|lg|xl) shape(circle|square|rounded) status?(AvatarStatus) ring?('lead'|'admin'|'client') badge?(number|'dot'|ReactNode) loading?(boolean) > AvatarImage + AvatarFallback(colorSeed?). Types: AvatarStatus = 'online'|'offline'|'busy'|'away', AvatarRing = 'none'|'lead'|'admin'|'client'. Fallback colors are deterministic from name hash (8 categorical). Online dot pulses. Badge pops in with MotionPop.
517
+ - Card: variant(default|elevated|outline|flat) interactive(boolean) accent?(left|top|right|bottom) accentColor?(default|secondary|error|success|warning|info) > CardHeader > CardTitle, CardDescription; CardContent; CardFooter
518
+ - Table > TableHeader > TableRow > TableHead; TableBody > TableRow > TableCell; TableFooter; TableCaption
519
+ - Text: variant(TextVariant) as(element). Type: 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'
520
+ - Code: variant(inline|block)
521
+ - Skeleton: variant(rectangle|circle|text) animation(pulse|shimmer|none)
522
+ - StatCard: title/label, value, delta, icon, prefix, suffix, comparisonLabel, secondaryLabel, progress, sparkline, onClick, href, accent(default|success|warning|error|info), footer
523
+ - ColorSwatch: color(CSS string) size(sm|md|lg) shape(circle|square|rounded) ring(boolean) — for dynamic runtime colors
524
+ - StatusDot: status(healthy|warning|critical|neutral|inactive) size(sm|md|lg) pulse?(boolean, default true for healthy) label?(string)
525
+ - ProgressRing: value(number) max?(100) size(sm|md|lg) color(default|success|warning|error|info) showValue?(boolean) label?(string). Also: MultiProgressRing for concentric Activity Ring style
526
+ - DevalokGrain: Brand texture overlay — drop inside any element with `relative overflow-hidden isolate`. Props: intensity('subtle'|'medium'|'heavy'), surface('solid'|'soft'), sheen(boolean, inner highlight), animated(boolean, fade-in on mount), hoverIntensify(boolean, parent needs `group` class), tint(CSS color string for directional gradient). No gradient rendered without tint.
527
+
528
+ ### Chat Primitives (ui/chat/)
529
+ Import: `@devalok/shilp-sutra/ui/chat`
530
+ - MessageList: children, autoScroll?(true), newMessageCount?(number, shows floating "N new" pill), onScrollToBottom?(), onLoadMore?(), isLoadingMore?(boolean), emptySlot?(ReactNode), headerSlot?(ReactNode). role="log" aria-live="polite".
531
+ - Message: COMPOUND — variant('flat'|'bubble') placement('start'|'end') highlight?('mention'|'internal') grouped?(boolean) deleted?(boolean) deletedText?(string). Sub-parts: Message.Avatar(src?, fallback?, icon?, size?('sm'|'md')), Message.Content, Message.Author(name, badge?, timestamp?, formattedTimestamp?, timestampFormat?), Message.Body, Message.EditableBody(content, onSave, onCancel?, canEdit?, renderContent?), Message.Reactions(reactions[{emoji,count,reacted}], onReact), Message.Actions(children, delay?), Message.Action(icon, label, onClick, variant?('default'|'danger'))
532
+ - SystemMessage: variant('event'|'alert') icon?(ReactNode) timestamp?(string) children
533
+ - MessageInput: onSubmit(text=>void), placeholder?, disabled?, isStreaming?(boolean, shows stop button), onCancel?(), leadingSlot?, trailingSlot?, disclaimer?(string), sendIcon?(ReactNode). Enter to send, Shift+Enter for newline.
534
+ - DateSeparator: date(Date|string), format?((date)=>string). Shows "Today", "Yesterday", or "Mar 15".
535
+ - UnreadSeparator: label?('NEW'), count?(number). Accent-colored horizontal rule.
536
+ - TypingIndicator: users({name, image?}[]). Shows animated bouncing dots + "Alice is typing..." / "Alice and Bob are typing..." / "Several people are typing..."
537
+
538
+ ### Overlays
539
+ - Dialog > DialogTrigger; DialogContent > DialogHeader > DialogTitle, DialogDescription; [content]; DialogFooter
540
+ - AlertDialog > AlertDialogTrigger; AlertDialogContent > AlertDialogHeader > AlertDialogTitle; AlertDialogFooter > AlertDialogCancel, AlertDialogAction
541
+ - Sheet: side(top|bottom|left|right) > SheetTrigger; SheetContent > SheetHeader > SheetTitle; [content]; SheetFooter
542
+ - Popover > PopoverTrigger; PopoverContent
543
+ - Tooltip: auto-wraps with <TooltipProvider> (no manual provider needed) > Tooltip > TooltipTrigger; TooltipContent
544
+ - HoverCard > HoverCardTrigger; HoverCardContent
545
+ - Collapsible > CollapsibleTrigger; CollapsibleContent
546
+
547
+ ### Navigation
548
+ - Tabs > TabsList(variant: line|contained) > TabsTrigger(value); TabsContent(value) — variant propagates via context
549
+ - Accordion(type: single|multiple) > AccordionItem(value) > AccordionTrigger(chevronPosition?: 'left'|'right', default 'right'); AccordionContent
550
+ - Breadcrumb > BreadcrumbList > BreadcrumbItem > BreadcrumbLink | BreadcrumbPage; BreadcrumbSeparator
551
+ - PaginationRoot > PaginationContent > PaginationItem > PaginationLink(isActive) | PaginationPrevious | PaginationNext | PaginationEllipsis
552
+ - DropdownMenu > DropdownMenuTrigger; DropdownMenuContent > DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuCheckboxItem, DropdownMenuRadioGroup > DropdownMenuRadioItem
553
+ - ContextMenu > ContextMenuTrigger (right-click); ContextMenuContent > same sub-components as DropdownMenu
554
+ - Menubar > MenubarMenu > MenubarTrigger; MenubarContent > same sub-components
555
+ - NavigationMenu > NavigationMenuList > NavigationMenuItem > NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink
556
+
557
+ ### Layout
558
+ - Stack: direction(vertical|horizontal) gap(SpacingToken|number) align, justify, wrap
559
+ - Container: maxWidth(default|body|full)
560
+ - Separator: orientation(horizontal|vertical)
561
+ - Sidebar: complex — see llms-full.txt for complete tree
562
+
563
+ ### Form Pattern
564
+ - FormField: state(FormHelperState) > Label + Input + FormHelperText. Type: FormHelperState = 'helper' | 'error' | 'warning' | 'success'
565
+ - useFormField() hook returns { state, helperTextId, required } from FormField context
566
+ - Wire accessibility: const { state, helperTextId } = useFormField(); then aria-describedby={helperTextId}, aria-invalid={state === 'error'}
567
+ - Input/Textarea auto-wire from FormField context (no manual hookup needed). Explicit props override.
568
+
569
+ ### Composed Components
570
+ - ConfirmDialog: open, onOpenChange, title, description, onConfirm + confirmText, cancelText, color(default|error), loading
571
+ - PageHeader: title, subtitle, breadcrumbs[], actions(ReactNode)
572
+ - AvatarGroup: users(AvatarUser[]), max?(number), size?(xs|sm|md|lg|xl), showTooltip?, borderColor?('surface-base'|'surface-raised'), onOverflowClick?(), renderAvatar?((user,index)=>ReactNode), expandDirection?('left'|'right'), expandAmount?('compact'|'default'|'wide'). Type: AvatarUser = { name, image?, ring?, indicator?('lead'|'admin'|ReactNode) }. GPU-composited hover expand via translateX. Use expandDirection="left" for right-aligned groups. indicator renders a small dot on avatar: 'lead'=warning-9, 'admin'=accent-9, or custom ReactNode.
573
+ - StatusBadge: DISCRIMINATED UNION — pass status OR color, not both. status(active|pending|approved|rejected|completed|blocked|in-progress|review|cancelled|draft) color(success|warning|error|info|neutral) size(sm|md) onClick?(() => void, renders as button with auto chevron-down icon) icon?(ReactNode, custom trailing icon)
574
+ - ContentCard: variant(default|outline|ghost) padding(default|compact|spacious|none)
575
+ - EmptyState: icon(ReactNode or ComponentType), title(required), description, action(ReactNode), compact
576
+ - PriorityIndicator: priority(Priority) display(compact|full). Type: Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent'
577
+ - SimpleTooltip: wraps Tooltip compound into single component
578
+ - DatePicker, DateRangePicker, DateTimePicker
579
+ - TimePicker: standalone time selector — value(Date|null), onChange, format('12h'|'24h'), minuteStep, showSeconds, disabled
580
+ - CalendarGrid: low-level calendar widget — currentMonth, selected, rangeStart/End, onSelect, onMonthChange, events(CalendarEvent[])
581
+ - YearPicker: decade year grid — currentYear, selectedYear, onYearSelect, minDate, maxDate
582
+ - MonthPicker: month grid — currentYear, selectedMonth(0-11), onMonthSelect, minDate, maxDate
583
+ - Presets: date range quick-select buttons — presets(PresetKey[]), onSelect(start, end). Keys: today, yesterday, last7days, last30days, thisMonth, lastMonth, thisYear
584
+ - useCalendar: hook for calendar month state — returns currentMonth, goToPreviousMonth, goToNextMonth, goToMonth, goToYear
585
+ - (UploadProgress REMOVED — upload tracking is now built into toast.upload())
586
+ - RichTextEditor: Tiptap editor — bold/italic/underline/strike/highlight, headings, blockquote, lists (bullet/ordered/task), code, links, images (paste/drop/upload), file attachments, @mentions, emoji picker + :shortcode:, text alignment, HR. Props: onImageUpload?, onFileUpload?, mentions?, onMentionSearch?, onMentionSelect?(item: MentionItem), emojiSet?(native|apple|google|twitter|facebook)
587
+ - RichTextViewer: read-only renderer for RichTextEditor HTML content (renders all above content types)
588
+ - RichChatInput: compact rich text chat input for AI/messaging. Output: RichChatInputMessage { html, plainText, attachments?, voiceNote? }. Variants: compact(default), expanded, minimal, inline. Key props: onSubmit(msg), onSchedule?(msg,date), emojiSet?, mentions?, slashCommands?, onFileUpload?, onImageUpload?, onVoiceRecord?, replyTo?, toolbar?(bool|items[]|ReactNode), actionButton?(ReactNode|false), enterBehavior?(send|newline), maxLength?, isStreaming?, onCancel?, disclaimer?, sendOptions?, leadingSlot?, trailingSlot?. Composable toolbar primitives exported: ToolbarButton, ToolbarDivider, ToolbarGroup, BoldButton, ItalicButton, etc.
589
+ - ActivityFeed: items(ActivityItem[]), onLoadMore, loading, hasMore, emptyState, compact, maxInitialItems, groupBy?('time'|'none'), groupLabels?({ today, yesterday, thisWeek, older }), renderItem?((item, index) => ReactNode|undefined, custom renderer per item — return ReactNode for custom, undefined for default). Type: ActivityItem = { id, actor?, action, timestamp, icon?, color?, detail? }. Utility: groupItemsByTime(items, labels) exported.
590
+ - CommandPalette: open, defaultOpen, onOpenChange (controlled/uncontrolled), keybinding(string|string[]|false), maxHeight, emptyState(ReactNode), footerHints(FooterHint[]|false). CommandItem: label(string|ReactNode), description(string|ReactNode), renderLabel(query=>ReactNode), filterValue(string), shortcut(rendered as keycap badges). Keyboard shortcuts rendered per-key with platform-aware Cmd/Ctrl. Reduced-motion support via MotionProvider.
591
+ - MemberPicker: thin wrapper around MultiSelectPopover with Avatar rendering
592
+ - MultiSelectPopover: items/groups, value, onValueChange, searchPlaceholder, onSearch?(async), renderItem?, emptyMessage, maxSelections. Generic multi-select popover with search + checkmarks.
593
+ - FilterBar: searchValue, onSearchChange, onClearAll, size(xs|sm|md). Children: FilterSelect(label, value, onValueChange, options), FilterMultiSelect(label, value, onValueChange, options). Size propagates via context.
594
+ - InlineEdit: value, onSave(string=>void|Promise), placeholder, textClassName, inputSize(xs|sm|md), multiline, readOnly, maxLength, saving. Click-to-edit text → input transition.
595
+ - FormSection: title, description?, collapsible?, defaultOpen?. Titled form section with separator, optional collapse.
596
+ - BulkActionBar: show, count, onClearSelection, actions[{label,icon?,onClick,color?,disabled?}]. Fixed bottom floating bar for multi-select contexts.
597
+ - DeadlineIndicator: deadline(Date|string), warningThreshold?(1440min), criticalThreshold?(240min), format(relative|absolute), showIcon. Color transitions: green→yellow→red→overdue.
598
+ - MasterDetail: selected, onBack, masterWidth, breakpoint(sm|md|lg). Compound: MasterDetail.List, MasterDetail.Detail, MasterDetail.ListItem(active). Desktop=grid, mobile=stacked with back button.
599
+ - MarkdownViewer: content(string), compact?, allowHtml?(false), linkTarget?('_blank'). Renders markdown with design system tokens.
600
+ - EmojiPicker: onSelect(emoji), set?(native|apple|google|twitter|facebook), theme(auto|light|dark). EmojiPickerPopover wraps in Popover. Lazy-loads emoji-mart with set-specific data.
601
+ - EmojiNode: TipTap inline atom node for spritesheet emoji rendering. Attrs: id, native, set, x, y. Use createEmojiSuggestion(set) to wire :shortcode: autocomplete. Export: EmojiNode, EmojiNodeAttrs, createEmojiSuggestion.
602
+ - FilePreview: url, type?(image|pdf|video|audio|embed), mimeType?, alt?. Auto-detects type. Image zoom, PDF iframe, native video/audio, embed for Figma/YouTube/Loom.
603
+ - ErrorDisplay, GlobalLoading
604
+ - Loading skeletons: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
605
+ - Page skeletons: DashboardSkeleton, ProjectListSkeleton, TaskDetailSkeleton (no props, server-safe)
606
+
607
+ ### Shell Components (app-level layout)
608
+ - TopBar: Composition-based. Subcomponents: TopBar.Left, TopBar.Center (optional, triggers grid), TopBar.Right, TopBar.Section(gap: tight|default|loose), TopBar.IconButton(icon, tooltip), TopBar.Title, TopBar.UserMenu(user, onNavigate?, onLogout?, userMenuItems?). Types: TopBarUser = { name, email?, image? }, UserMenuItem = { label, icon?, href?, onClick?, separator?, color?, badge?, disabled? }
609
+ - AppSidebar: navigation tree with NavItem[], NavGroup[]. Types: NavItem = { title, href, icon, exact?, badge?, children?, defaultOpen? }, NavSubItem = { title, href, icon?, exact? }, NavGroup = { label, items, action? }, SidebarUser = { name, email?, image?, designation?, role? }
610
+
611
+ ### AppSidebar (v0.10.0 additions)
612
+ - NavItem.children?: NavSubItem[] — collapsible sub-list with chevron toggle
613
+ - NavItem.defaultOpen?: boolean — control initial collapsed state
614
+ - NavItem.badge?: string | number — badge on nav item (99+ cap for numbers)
615
+ - NavGroup.action?: ReactNode — action button next to group label
616
+ - footer?: SidebarFooterConfig — structured footer with links, version, slot, promo (replaces footerLinks)
617
+ - headerSlot?: ReactNode — content between user info and navigation
618
+ - preFooterSlot?: ReactNode — content between navigation and footer
619
+ - renderItem?: (item, defaultRender) => ReactNode | null — custom item rendering
620
+
621
+ - BottomNavbar: mobile navigation, user is optional. Types: BottomNavItem = { title, href, icon, exact?, badge? }, BottomNavbarUser = { name, role? }
622
+ - NotificationCenter: notifications[], onMarkRead, onMarkAllRead, onNavigate, getNotificationRoute?, footerSlot?, emptyState?, headerActions?, popoverClassName?, onDismiss?(id). Types: Notification = { id, title, body?, tier, isRead, createdAt, entityType?, entityId?, projectId?, project?, actions? }, NotificationAction = { label, variant?, onClick }
623
+ - NotificationPreferences: preferences[], projects[], onSave, onToggleMute, onUpdateTier, onDelete. Types: NotificationPreference = { id, userId?, projectId, channel, minTier, muted }, NotificationProject = { id, title }
624
+ - AppCommandPalette: user, isAdmin, onNavigate, onSearch, searchResults, searchResultGroups(SearchResultGroup[]), isSearching, onSearchResultSelect (when provided, consumer owns routing — no internal URL computation), searchResultsLabel(string|((count)=>string)), open, defaultOpen, onOpenChange, keybinding, maxHeight, emptyState, footerHints. Types: SearchResult = { id, title, snippet?, entityType, projectId?, metadata?, icon?(ReactNode), rank?(number), shortcut?(string) }, SearchResultGroup = { label, results: SearchResult[] }, AppCommandPaletteUser = { name, role? }
625
+ - LinkProvider: wraps app with router-agnostic Link component — component(ForwardRefComponent), children. useLink() hook returns the Link component.
626
+
627
+ ### Motion System (Framer Motion)
628
+ - Setup: Wrap app root with `<MotionProvider>` from `@devalok/shilp-sutra/motion`. Handles reduced-motion detection globally.
629
+ - Import presets: `import { springs, tweens, stagger } from '@devalok/shilp-sutra/motion'`
630
+ - Import primitives: `import { MotionFade, MotionScale, MotionPop, MotionSlide, MotionCollapse, MotionStagger, MotionStaggerItem } from '@devalok/shilp-sutra/motion/primitives'`
631
+ - Spring presets (spatial: position, scale, size): snappy (buttons/hover), smooth (dialogs/panels), bouncy (toasts/pop-ins), gentle (collapse/expand)
632
+ - Tween presets (non-spatial: opacity, color): fade (opacity enter/exit), colorShift (hover color/bg)
633
+ - All primitives take `show: boolean` to control mount/unmount via AnimatePresence
634
+ - MotionSlide: additional `direction` prop (up|down|left|right)
635
+ - MotionStagger + MotionStaggerItem: orchestrated stagger with configurable `delay` (default 0.04s)
636
+ - All primitives support `layout`, `layoutId`, `whileInView`, `viewportOnce`, `preset` props
637
+ - useMotion() hook returns { springs, tweens, reducedMotion: boolean }
638
+ - Old Fade/Collapse/Grow/Slide from @devalok/shilp-sutra/ui/transitions are REMOVED — use Motion* equivalents
639
+
640
+ ### Hooks
641
+ - toast: imperative API — import { toast } from '@devalok/shilp-sutra/ui/toast'. Methods: toast.success/error/warning/info/loading/message/undo/promise/upload/custom/dismiss. useToast() is deprecated.
642
+ - useColorMode(): returns { colorMode, setColorMode, toggleColorMode }
643
+ - useMobile(): returns boolean (true if viewport < 768px)
644
+ - useLink(): returns router-agnostic Link component from LinkProvider context (shell/link-context)
645
+
646
+ ## Server-Safe Components (no "use client")
647
+
648
+ These can be imported directly in Next.js Server Components:
649
+ - UI: Text, Skeleton, Stack, Container, Table (and sub-components), Code, VisuallyHidden
650
+ - Composed: ContentCard, PageHeader, LoadingSkeleton, PageSkeletons, PriorityIndicator
651
+
652
+ Use per-component imports for server components:
653
+ import { Text } from '@devalok/shilp-sutra/ui/text'
654
+ import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
655
+
656
+ DO NOT use barrel imports in Server Components — they include "use client" components.
657
+
658
+ ## Common Mistakes -- DO NOT
659
+
660
+ - DO NOT use variant="destructive" — use color="error"
661
+ - DO NOT use size="default" — use size="md" (or sm, lg)
662
+ - DO NOT put size on <Select> — put it on <SelectTrigger size="md">
663
+ - DO NOT use <Chip> — Chip is deprecated. Use <Badge onClick={...}> instead
664
+ - DO NOT use useToast() hook — use import { toast } from '@devalok/shilp-sutra/ui/toast' (imperative)
665
+ - DO NOT use toast({ title, color }) object syntax — use toast.success('message'), toast.error('message'), etc.
666
+ - DO NOT call toast() without <Toaster /> mounted at your layout root
667
+ - DO NOT use <Alert><AlertTitle>...</AlertTitle></Alert> — use <Alert title="..." />
668
+ - DO NOT import from barrel in Next.js Server Components — use per-component imports
669
+ - DO NOT use variant="secondary" on Button — use variant="outline" or variant="ghost"
670
+ - DO NOT use variant="default" on Button — use variant="solid" (deprecated alias, still works)
671
+ - DO NOT use variant="destructive" on Button — use variant="solid" color="error" (deprecated alias, still works)
672
+ - DO NOT use color="default" on Button — use color="accent" (deprecated alias, still works)
673
+ - DO NOT put variant on individual TabsTrigger — put it on TabsList (propagates via context)