@devalok/shilp-sutra 0.38.0 → 0.40.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 (361) hide show
  1. package/AGENTS.md +151 -0
  2. package/MIGRATION.md +255 -0
  3. package/README.md +3 -0
  4. package/dist/_chunks/badge-group.js +76 -75
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chart-container.js +50 -0
  7. package/dist/_chunks/chart-container.js.map +1 -0
  8. package/dist/_chunks/chat.js +236 -228
  9. package/dist/_chunks/chat.js.map +1 -1
  10. package/dist/_chunks/colors.js +30 -0
  11. package/dist/_chunks/colors.js.map +1 -0
  12. package/dist/_chunks/document-preview.js +2 -2
  13. package/dist/_chunks/document-preview.js.map +1 -1
  14. package/dist/_chunks/emoji-data.js +45 -0
  15. package/dist/_chunks/emoji-data.js.map +1 -0
  16. package/dist/_chunks/grid-lines.js +72 -0
  17. package/dist/_chunks/grid-lines.js.map +1 -0
  18. package/dist/_chunks/image-preview.js +2 -2
  19. package/dist/_chunks/image-preview.js.map +1 -1
  20. package/dist/_chunks/mention-suggestion.js +35 -263
  21. package/dist/_chunks/mention-suggestion.js.map +1 -1
  22. package/dist/_chunks/normalize-icon.js +18 -0
  23. package/dist/_chunks/normalize-icon.js.map +1 -0
  24. package/dist/_chunks/oauth-button.js +227 -0
  25. package/dist/_chunks/oauth-button.js.map +1 -0
  26. package/dist/_chunks/popover.js +3 -3
  27. package/dist/_chunks/popover.js.map +1 -1
  28. package/dist/_chunks/primitives.js +107 -107
  29. package/dist/_chunks/primitives.js.map +1 -1
  30. package/dist/_chunks/shared.js +5 -5
  31. package/dist/_chunks/shared.js.map +1 -1
  32. package/dist/_chunks/{text.js → success.js} +26 -63
  33. package/dist/_chunks/success.js.map +1 -0
  34. package/dist/_chunks/tiptap.js +1952 -1949
  35. package/dist/_chunks/tiptap.js.map +1 -1
  36. package/dist/_chunks/tooltip.js +58 -0
  37. package/dist/_chunks/tooltip.js.map +1 -0
  38. package/dist/_chunks/tree-view.js +101 -96
  39. package/dist/_chunks/tree-view.js.map +1 -1
  40. package/dist/_chunks/use-calendar.js +5 -5
  41. package/dist/_chunks/use-calendar.js.map +1 -1
  42. package/dist/ai/ai-command-provider.d.ts +3 -2
  43. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  44. package/dist/ai/ai-command-provider.js.map +1 -1
  45. package/dist/ai/block-renderer.js +11 -9
  46. package/dist/ai/block-renderer.js.map +1 -1
  47. package/dist/ai/blocks/error.js +31 -0
  48. package/dist/ai/blocks/error.js.map +1 -0
  49. package/dist/ai/blocks/index.d.ts +0 -2
  50. package/dist/ai/blocks/index.d.ts.map +1 -1
  51. package/dist/ai/blocks/index.js +2 -2
  52. package/dist/ai/blocks/text.js +19 -0
  53. package/dist/ai/blocks/text.js.map +1 -0
  54. package/dist/ai/command-bar.d.ts.map +1 -1
  55. package/dist/ai/command-bar.js +198 -193
  56. package/dist/ai/command-bar.js.map +1 -1
  57. package/dist/ai/conversation.d.ts +2 -1
  58. package/dist/ai/conversation.d.ts.map +1 -1
  59. package/dist/ai/conversation.js +92 -87
  60. package/dist/ai/conversation.js.map +1 -1
  61. package/dist/ai/index.d.ts +0 -4
  62. package/dist/ai/index.d.ts.map +1 -1
  63. package/dist/ai/index.js +45 -46
  64. package/dist/ai/index.js.map +1 -1
  65. package/dist/composed/activity-feed.d.ts +2 -1
  66. package/dist/composed/activity-feed.d.ts.map +1 -1
  67. package/dist/composed/activity-feed.js +5 -5
  68. package/dist/composed/activity-feed.js.map +1 -1
  69. package/dist/composed/avatar-group.js +4 -4
  70. package/dist/composed/avatar-group.js.map +1 -1
  71. package/dist/composed/bulk-action-bar.d.ts +2 -2
  72. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  73. package/dist/composed/bulk-action-bar.js +12 -12
  74. package/dist/composed/bulk-action-bar.js.map +1 -1
  75. package/dist/composed/command-palette.d.ts +2 -1
  76. package/dist/composed/command-palette.d.ts.map +1 -1
  77. package/dist/composed/command-palette.js +106 -101
  78. package/dist/composed/command-palette.js.map +1 -1
  79. package/dist/composed/content-card.js +1 -1
  80. package/dist/composed/content-card.js.map +1 -1
  81. package/dist/composed/date-picker/index.js +747 -3
  82. package/dist/composed/date-picker/index.js.map +1 -0
  83. package/dist/composed/emoji-picker.js +4 -4
  84. package/dist/composed/emoji-picker.js.map +1 -1
  85. package/dist/composed/empty-state.d.ts +3 -3
  86. package/dist/composed/empty-state.d.ts.map +1 -1
  87. package/dist/composed/empty-state.js +40 -31
  88. package/dist/composed/empty-state.js.map +1 -1
  89. package/dist/composed/error-boundary.js +3 -3
  90. package/dist/composed/error-boundary.js.map +1 -1
  91. package/dist/composed/extensions/emoji-node.js +81 -0
  92. package/dist/composed/extensions/emoji-node.js.map +1 -0
  93. package/dist/composed/extensions/emoji-suggestion.js +117 -0
  94. package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
  95. package/dist/composed/file-preview.js +498 -2
  96. package/dist/composed/file-preview.js.map +1 -0
  97. package/dist/composed/filter-bar.js +1 -1
  98. package/dist/composed/filter-bar.js.map +1 -1
  99. package/dist/composed/index.d.ts +0 -15
  100. package/dist/composed/index.d.ts.map +1 -1
  101. package/dist/composed/index.js +16 -24
  102. package/dist/composed/inline-edit.js +1 -1
  103. package/dist/composed/inline-edit.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js +9 -9
  105. package/dist/composed/loading-skeleton.js.map +1 -1
  106. package/dist/composed/markdown-viewer.js +3 -3
  107. package/dist/composed/markdown-viewer.js.map +1 -1
  108. package/dist/composed/multi-select-popover.js +1 -1
  109. package/dist/composed/multi-select-popover.js.map +1 -1
  110. package/dist/composed/page-header.js +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js +15 -15
  113. package/dist/composed/page-skeletons.js.map +1 -1
  114. package/dist/composed/priority-indicator.js +3 -3
  115. package/dist/composed/priority-indicator.js.map +1 -1
  116. package/dist/composed/rich-chat-input.js +2073 -2
  117. package/dist/composed/rich-chat-input.js.map +1 -0
  118. package/dist/composed/rich-text-editor.js +75 -72
  119. package/dist/composed/rich-text-editor.js.map +1 -1
  120. package/dist/composed/schedule-view.js +3 -3
  121. package/dist/composed/schedule-view.js.map +1 -1
  122. package/dist/composed/status-badge.d.ts +3 -2
  123. package/dist/composed/status-badge.d.ts.map +1 -1
  124. package/dist/composed/status-badge.js +58 -53
  125. package/dist/composed/status-badge.js.map +1 -1
  126. package/dist/shell/app-command-palette.d.ts +2 -1
  127. package/dist/shell/app-command-palette.d.ts.map +1 -1
  128. package/dist/shell/app-command-palette.js.map +1 -1
  129. package/dist/shell/bottom-navbar.d.ts +3 -1
  130. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  131. package/dist/shell/bottom-navbar.js +94 -86
  132. package/dist/shell/bottom-navbar.js.map +1 -1
  133. package/dist/shell/command-registry.d.ts +2 -1
  134. package/dist/shell/command-registry.d.ts.map +1 -1
  135. package/dist/shell/command-registry.js.map +1 -1
  136. package/dist/shell/notification-center.js +8 -8
  137. package/dist/shell/notification-center.js.map +1 -1
  138. package/dist/shell/notification-preferences.js +1 -1
  139. package/dist/shell/notification-preferences.js.map +1 -1
  140. package/dist/shell/sidebar.d.ts +7 -4
  141. package/dist/shell/sidebar.d.ts.map +1 -1
  142. package/dist/shell/sidebar.js +148 -134
  143. package/dist/shell/sidebar.js.map +1 -1
  144. package/dist/shell/top-bar.d.ts +4 -3
  145. package/dist/shell/top-bar.d.ts.map +1 -1
  146. package/dist/shell/top-bar.js +116 -108
  147. package/dist/shell/top-bar.js.map +1 -1
  148. package/dist/tokens/semantic.css +82 -9
  149. package/dist/ui/accordion.js +1 -1
  150. package/dist/ui/accordion.js.map +1 -1
  151. package/dist/ui/alert-dialog.js +3 -3
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js +2 -2
  154. package/dist/ui/alert.js.map +1 -1
  155. package/dist/ui/autocomplete.js +2 -2
  156. package/dist/ui/autocomplete.js.map +1 -1
  157. package/dist/ui/avatar.js +11 -11
  158. package/dist/ui/avatar.js.map +1 -1
  159. package/dist/ui/badge-indicator.js +1 -1
  160. package/dist/ui/badge-indicator.js.map +1 -1
  161. package/dist/ui/badge.d.ts +3 -2
  162. package/dist/ui/badge.d.ts.map +1 -1
  163. package/dist/ui/banner.js +1 -1
  164. package/dist/ui/banner.js.map +1 -1
  165. package/dist/ui/breadcrumb.js +1 -1
  166. package/dist/ui/breadcrumb.js.map +1 -1
  167. package/dist/ui/button.d.ts +5 -4
  168. package/dist/ui/button.d.ts.map +1 -1
  169. package/dist/ui/button.js +66 -65
  170. package/dist/ui/button.js.map +1 -1
  171. package/dist/ui/card.js +5 -5
  172. package/dist/ui/card.js.map +1 -1
  173. package/dist/ui/charts/area-chart.js +177 -0
  174. package/dist/ui/charts/area-chart.js.map +1 -0
  175. package/dist/ui/charts/bar-chart.js +127 -0
  176. package/dist/ui/charts/bar-chart.js.map +1 -0
  177. package/dist/ui/charts/chart-container.js +3 -0
  178. package/dist/ui/charts/gauge-chart.js +72 -0
  179. package/dist/ui/charts/gauge-chart.js.map +1 -0
  180. package/dist/ui/charts/index.js +10 -1035
  181. package/dist/ui/charts/line-chart.js +135 -0
  182. package/dist/ui/charts/line-chart.js.map +1 -0
  183. package/dist/ui/charts/pie-chart.js +111 -0
  184. package/dist/ui/charts/pie-chart.js.map +1 -0
  185. package/dist/ui/charts/radar-chart.js +170 -0
  186. package/dist/ui/charts/radar-chart.js.map +1 -0
  187. package/dist/ui/charts/sparkline.js +119 -0
  188. package/dist/ui/charts/sparkline.js.map +1 -0
  189. package/dist/ui/chat/message.d.ts +3 -3
  190. package/dist/ui/chat/message.d.ts.map +1 -1
  191. package/dist/ui/chat/system-message.d.ts +2 -1
  192. package/dist/ui/chat/system-message.d.ts.map +1 -1
  193. package/dist/ui/checkbox.js +1 -1
  194. package/dist/ui/checkbox.js.map +1 -1
  195. package/dist/ui/code.js +2 -2
  196. package/dist/ui/code.js.map +1 -1
  197. package/dist/ui/color-input.js +10 -10
  198. package/dist/ui/color-input.js.map +1 -1
  199. package/dist/ui/color-swatch.js +3 -3
  200. package/dist/ui/color-swatch.js.map +1 -1
  201. package/dist/ui/combobox.d.ts +2 -1
  202. package/dist/ui/combobox.d.ts.map +1 -1
  203. package/dist/ui/combobox.js +100 -95
  204. package/dist/ui/combobox.js.map +1 -1
  205. package/dist/ui/container.d.ts +6 -1
  206. package/dist/ui/container.d.ts.map +1 -1
  207. package/dist/ui/container.js +2 -1
  208. package/dist/ui/container.js.map +1 -1
  209. package/dist/ui/context-menu.js +6 -6
  210. package/dist/ui/context-menu.js.map +1 -1
  211. package/dist/ui/data-table-body.js +1 -1
  212. package/dist/ui/data-table-body.js.map +1 -1
  213. package/dist/ui/data-table-bulk-actions.js +2 -2
  214. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  215. package/dist/ui/data-table-card.js +2 -2
  216. package/dist/ui/data-table-card.js.map +1 -1
  217. package/dist/ui/data-table-header.js +2 -2
  218. package/dist/ui/data-table-header.js.map +1 -1
  219. package/dist/ui/data-table-pagination.js +3 -3
  220. package/dist/ui/data-table-pagination.js.map +1 -1
  221. package/dist/ui/data-table-toolbar.js +1 -1
  222. package/dist/ui/data-table-toolbar.js.map +1 -1
  223. package/dist/ui/data-table.js +1 -1
  224. package/dist/ui/data-table.js.map +1 -1
  225. package/dist/ui/devalok-grain.d.ts +1 -1
  226. package/dist/ui/devalok-grain.js.map +1 -1
  227. package/dist/ui/dialog.js +2 -2
  228. package/dist/ui/dialog.js.map +1 -1
  229. package/dist/ui/dropdown-menu.js +6 -6
  230. package/dist/ui/dropdown-menu.js.map +1 -1
  231. package/dist/ui/file-upload.js +4 -4
  232. package/dist/ui/file-upload.js.map +1 -1
  233. package/dist/ui/hover-card.js +1 -1
  234. package/dist/ui/hover-card.js.map +1 -1
  235. package/dist/ui/icon-button.d.ts +9 -2
  236. package/dist/ui/icon-button.d.ts.map +1 -1
  237. package/dist/ui/icon-button.js +14 -13
  238. package/dist/ui/icon-button.js.map +1 -1
  239. package/dist/ui/index.d.ts +1 -3
  240. package/dist/ui/index.d.ts.map +1 -1
  241. package/dist/ui/index.js +31 -33
  242. package/dist/ui/index.js.map +1 -1
  243. package/dist/ui/input-otp.js +1 -1
  244. package/dist/ui/input-otp.js.map +1 -1
  245. package/dist/ui/input.js +2 -2
  246. package/dist/ui/input.js.map +1 -1
  247. package/dist/ui/lib/icon-input.d.ts +42 -0
  248. package/dist/ui/lib/icon-input.d.ts.map +1 -0
  249. package/dist/ui/lib/normalize-icon.d.ts +39 -0
  250. package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
  251. package/dist/ui/link.js +1 -1
  252. package/dist/ui/link.js.map +1 -1
  253. package/dist/ui/menubar.js +8 -8
  254. package/dist/ui/menubar.js.map +1 -1
  255. package/dist/ui/navigation-menu.js +3 -3
  256. package/dist/ui/navigation-menu.js.map +1 -1
  257. package/dist/ui/number-input.js +3 -3
  258. package/dist/ui/number-input.js.map +1 -1
  259. package/dist/ui/oauth-button/index.d.ts +3 -0
  260. package/dist/ui/oauth-button/index.d.ts.map +1 -0
  261. package/dist/ui/oauth-button/index.js +3 -0
  262. package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
  263. package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
  264. package/dist/ui/pagination.js +1 -1
  265. package/dist/ui/pagination.js.map +1 -1
  266. package/dist/ui/progress.js +2 -2
  267. package/dist/ui/progress.js.map +1 -1
  268. package/dist/ui/radio.js +1 -1
  269. package/dist/ui/radio.js.map +1 -1
  270. package/dist/ui/segmented-control.d.ts +3 -4
  271. package/dist/ui/segmented-control.d.ts.map +1 -1
  272. package/dist/ui/segmented-control.js +53 -45
  273. package/dist/ui/segmented-control.js.map +1 -1
  274. package/dist/ui/select.js +3 -3
  275. package/dist/ui/select.js.map +1 -1
  276. package/dist/ui/sheet.js +2 -2
  277. package/dist/ui/sheet.js.map +1 -1
  278. package/dist/ui/sidebar.js +11 -11
  279. package/dist/ui/sidebar.js.map +1 -1
  280. package/dist/ui/skeleton.js +9 -9
  281. package/dist/ui/skeleton.js.map +1 -1
  282. package/dist/ui/slider.js +2 -2
  283. package/dist/ui/slider.js.map +1 -1
  284. package/dist/ui/split-button.js +7 -7
  285. package/dist/ui/split-button.js.map +1 -1
  286. package/dist/ui/stack.d.ts +6 -1
  287. package/dist/ui/stack.d.ts.map +1 -1
  288. package/dist/ui/stack.js +2 -1
  289. package/dist/ui/stack.js.map +1 -1
  290. package/dist/ui/stat-card.d.ts +2 -3
  291. package/dist/ui/stat-card.d.ts.map +1 -1
  292. package/dist/ui/stat-card.js +118 -116
  293. package/dist/ui/stat-card.js.map +1 -1
  294. package/dist/ui/status-dot.js +2 -2
  295. package/dist/ui/status-dot.js.map +1 -1
  296. package/dist/ui/stepper.d.ts +2 -1
  297. package/dist/ui/stepper.d.ts.map +1 -1
  298. package/dist/ui/stepper.js +74 -69
  299. package/dist/ui/stepper.js.map +1 -1
  300. package/dist/ui/switch.js +2 -2
  301. package/dist/ui/switch.js.map +1 -1
  302. package/dist/ui/tabs.js +3 -3
  303. package/dist/ui/tabs.js.map +1 -1
  304. package/dist/ui/text.d.ts +7 -2
  305. package/dist/ui/text.d.ts.map +1 -1
  306. package/dist/ui/text.js +2 -1
  307. package/dist/ui/text.js.map +1 -1
  308. package/dist/ui/textarea.js +1 -1
  309. package/dist/ui/textarea.js.map +1 -1
  310. package/dist/ui/toast.js +8 -8
  311. package/dist/ui/toast.js.map +1 -1
  312. package/dist/ui/toaster.d.ts +11 -2
  313. package/dist/ui/toaster.d.ts.map +1 -1
  314. package/dist/ui/toaster.js.map +1 -1
  315. package/dist/ui/toggle.js +1 -1
  316. package/dist/ui/toggle.js.map +1 -1
  317. package/dist/ui/tooltip.js +12 -12
  318. package/dist/ui/tooltip.js.map +1 -1
  319. package/dist/ui/tree-view/tree-item.d.ts +3 -2
  320. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  321. package/dist/ui/tree-view/use-tree.d.ts +2 -1
  322. package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
  323. package/docs/components/_header.md +90 -1
  324. package/docs/components/ui/oauth-button.md +86 -0
  325. package/docs/recipes/customize-brand.md +100 -4
  326. package/docs/recipes/index.md +5 -1
  327. package/docs/recipes/install-astro.md +15 -0
  328. package/docs/recipes/install-next-app-router.md +21 -5
  329. package/docs/recipes/install-next-pages.md +2 -0
  330. package/docs/recipes/install-remix.md +15 -0
  331. package/docs/recipes/install-tanstack-start.md +15 -0
  332. package/docs/recipes/install-vite.md +15 -0
  333. package/docs/recipes/troubleshoot.md +22 -0
  334. package/llms-full.txt +177 -2
  335. package/llms-quick.txt +247 -0
  336. package/llms.txt +116 -3
  337. package/package.json +80 -2
  338. package/scripts/welcome.mjs +219 -0
  339. package/skill/README.md +99 -0
  340. package/skill/SKILL.md +163 -0
  341. package/skill/install.sh +59 -0
  342. package/skill/references/components-full.md +7083 -0
  343. package/skill/references/components.md +778 -0
  344. package/skill/references/customize-brand.md +314 -0
  345. package/skill/references/server-components.md +211 -0
  346. package/skill/references/setup-astro.md +195 -0
  347. package/skill/references/setup-next-app-router.md +248 -0
  348. package/skill/references/setup-next-pages.md +127 -0
  349. package/skill/references/setup-remix.md +188 -0
  350. package/skill/references/setup-tanstack-start.md +160 -0
  351. package/skill/references/setup-vite.md +187 -0
  352. package/skill/references/troubleshoot.md +241 -0
  353. package/dist/_chunks/date-picker.js +0 -748
  354. package/dist/_chunks/date-picker.js.map +0 -1
  355. package/dist/_chunks/file-preview.js +0 -499
  356. package/dist/_chunks/file-preview.js.map +0 -1
  357. package/dist/_chunks/rich-chat-input.js +0 -2071
  358. package/dist/_chunks/rich-chat-input.js.map +0 -1
  359. package/dist/_chunks/text.js.map +0 -1
  360. package/dist/ui/charts/index.js.map +0 -1
  361. /package/{LICENSE → skill/LICENSE} +0 -0
@@ -0,0 +1,778 @@
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 Themer (fast path for branding)
32
+
33
+ Before hand-writing CSS variables, point the user at **https://shilp-sutra.devalok.in/themer** — one funnel, four doors. Each door drops the user at a result page with install commands + a copy-pasteable CSS block (role tokens + 12-step OKLCH accent ramp) + a shareable URL.
34
+
35
+ | User context | URL |
36
+ |---|---|
37
+ | "Make it look like Linear / Stripe / Apple / Material / Notion / Vercel / Devalok" | `/themer/archetypes` |
38
+ | "Here's our brand color: `#…`" | `/themer/brand` |
39
+ | "Not sure" | `/themer/wizard` |
40
+ | "Show me a sample result" | `/themer/result?archetype=devalok` |
41
+
42
+ Paste the snippet *after* `@import "@devalok/shilp-sutra/css";` in the global stylesheet. No `tailwind.config.ts`, no theme provider, no JS bundle. Fall through to `customize-brand.md` only for tokens the Themer doesn't expose yet (font stack, spacing scale, focus ring).
43
+
44
+ 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.
45
+
46
+ ## NEW (v0.40.0)
47
+
48
+ - **OAuthButton.** Brand-aware social/login buttons. Subpath: `@devalok/shilp-sutra/ui/oauth-button`. 13 providers (`google` `apple` `github` `microsoft` `x` `linkedin` `facebook` `discord` `slack` `gitlab` `sso` `email` `passkey`). Props: `provider`, `intent` (`continue|signin|signup`), `appearance` (`brand|outline|dark`), `icon` (override default glyph), `iconOnly`, `compact` (renders just "Google" instead of "Continue with Google"; aria-label keeps long form), `lastUsed` (inline right-edge pill inside button), `helperText`. Inherits Button async/loading/sizes. Siblings: `OAuthGroup` (with `reorderLastUsedFirst` for Stripe-style ordering), `OAuthDivider`, `OAuthConnectionRow` (settings-page linked state). Default glyphs from Tabler peer dep; pass `icon` to drop in a brand's official multicolour SVG. In dark mode every brand appearance lands on the same DS surface — brand identity comes from the glyph, not the bg, so rows stay visually coherent.
49
+ - **Icon API unification.** Every icon-accepting prop (`startIcon`, `endIcon`, `icon`, `leftIcon`, `rightIcon`) across 22 components now takes one type: **`IconInput`**. Pass a rendered element (`<Icon icon={IconPlus} />` or `<IconPlus />`), a component ref (`IconPlus`), or any custom node — all four shapes work interchangeably. Type widening only; every call that compiled before still compiles. Helpers exported for your own wrappers: `import type { IconInput } from '@devalok/shilp-sutra/ui/lib/icon-input'` + `import { normalizeIcon } from '@devalok/shilp-sutra/ui/lib/normalize-icon'`. `IconProvider` now sizes icons via context — delete `className="h-4 w-4"` overrides.
50
+ - **Polymorphic `Text` / `Stack` / `Container`.** The `as` prop now widens accepted attributes to the rendered element: `<Text as="label" htmlFor="email">`, `<Text as="a" href="/x">`, `<Stack as="ul" role="list">`, `<Container as="main" aria-label>` all typecheck. Default element behavior unchanged.
51
+ - **Agent-friendly install experience.** `AGENTS.md` now ships in the tarball (`node_modules/@devalok/shilp-sutra/AGENTS.md`), discoverable by 25+ agent tools. `package.json` declares an `agents` field (npm-agentskills convention) so `pnpm dlx @codemcp/agentskills export` auto-installs the bundled skill. New postinstall welcome banner (silent in CI / non-TTY / `SHILP_SUTRA_NO_WELCOME=1`). `troubleshoot.md` gained peer-cliff symptom entries.
52
+ - **`llms-quick.txt`.** New ≤15K-token fast-path summary in the tarball — fits in one Read on any agent. Read order is now `llms-quick.txt` → `llms.txt` → `llms-full.txt`.
53
+ - **Companion package `@devalok/eslint-plugin-shilp-sutra`** (first release). 12 rules — deprecated-API catches, peer-cliff barrel-import detection, TW3→TW4 classname autofixes. `pnpm add -D @devalok/eslint-plugin-shilp-sutra`, then `shilpSutra.configs['flat/recommended']`. Three presets: `recommended`, `strict`, `migration` (one-shot codemod).
54
+
55
+ ## BREAKING CHANGES (v0.40.0)
56
+
57
+ - **Barrel peer-cliff cleanup.** 12 symbols that statically import optional peers were removed from their parent barrels (`/ui`, `/composed`, `/ai`, `/ai/blocks`) — they now import ONLY via per-component subpath. Affected: `Toaster`/`toast` (→ `/ui/toaster`, `/ui/toast`), `InputOTP*` (→ `/ui/input-otp`), `DatePicker*` (→ `/composed/date-picker`), `EmojiPicker*` (→ `/composed/emoji-picker`), `FilePreview` (→ `/composed/file-preview`), `MarkdownViewer` (→ `/composed/markdown-viewer`), `RichTextEditor*`/`RichChatInput*` (→ their subpaths), `BlockRenderer`/`ErrorBlock`/`TextBlock` (→ `/ai/*`). Fixes `Module not found: Can't resolve 'sonner'`/etc. at consumer build time. Full before/after table in `MIGRATION.md → v0.40.0`. Per-chart subpaths (`/ui/charts/bar-chart`, etc.) added non-breaking alongside.
58
+
59
+ ## NEW (v0.39.0)
60
+
61
+ - **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.
62
+ - **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; }`.
63
+ - **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.
64
+ - **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).
65
+ - See `customize-brand.md` recipe for the full role token list and how to define your own preset.
66
+
67
+ ## BREAKING CHANGES (v0.37.0 — Tailwind 4 CSS-first)
68
+
69
+ **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.
70
+
71
+ - **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:
72
+ ```css
73
+ @import "tailwindcss";
74
+ @import "@devalok/shilp-sutra/css";
75
+ ```
76
+ 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.
77
+ - **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.
78
+ - **sonner is now an optional peer dep.** Install only if you render `<Toaster />`: `pnpm add sonner`.
79
+ - **tailwindcss peer tightened to `^4.0.0`.** No more `^3.4.0 || ^4.0.0`.
80
+ - **use-sync-external-store moved to our `dependencies`** (from optional peer). Auto-installed transitively.
81
+ - **Node engines floor dropped.** No `engines.node` declared — use any Node 18+.
82
+ - **New export `@devalok/shilp-sutra/css`** — primary consumer entry for TW4 setup.
83
+ - **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/`.
84
+ - **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.).
85
+ - **Dark mode variant:** `@custom-variant dark (&:where(.dark *))` — identical semantics to old `darkMode: 'class'`. `.dark` on `<html>` or `<body>` activates everything below.
86
+
87
+ ## NEW (v0.36.0)
88
+
89
+ - **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.
90
+ - **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.
91
+ - **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.
92
+ - **Dev-mode missing-`<Toaster />` warning.** `toast()` called without a mounted `Toaster` logs a one-time console warning in dev. Production-silent.
93
+ - **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.
94
+
95
+ ## FIXES (v0.36.0)
96
+
97
+ - **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.
98
+ - **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.
99
+ - **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.
100
+ - **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.
101
+
102
+ ## BREAKING CHANGES (v0.35.0 — World-Class Audit)
103
+
104
+ - **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.
105
+ - **Responsive typography:** Heading sizes 3xl–6xl use `clamp()` for fluid scaling. Headings shrink on mobile.
106
+ - **Body letter spacing:** body-lg (-0.01em), body-md (0em), body-sm (+0.01em), body-xs (+0.02em). Was all -0.02em.
107
+ - **surface-fg-subtle:** Darkened from neutral-8 to neutral-9 in light mode. Tertiary text is more visible.
108
+ - **MessageList:** `isLoadingMore` renamed to `loadingMore`.
109
+ - **AppCommandPalette:** Default Karm routes removed. Use `CommandRegistryProvider` for page registration. `SearchResult` type adds optional `href` field.
110
+ - **NumberInput:** Shape changed from pill to rounded rectangle.
111
+ - **Dependencies:** `@floating-ui/dom`, `@tiptap/*`, `prosemirror-state` moved to devDeps (bundled; consumers no longer install them).
112
+
113
+ ## NEW (v0.35.0)
114
+
115
+ - **Size props:** Combobox (xs/sm/md/lg), NumberInput (xs/sm/md/lg + state), Slider (sm/md/lg + color), InputOTP (sm/md/lg + state).
116
+ - **Toggle color:** `color` prop on Toggle/ToggleGroup (accent/error/success/neutral).
117
+ - **Tabs vertical:** `orientation="vertical"` for side-nav layout.
118
+ - **Stepper clickable:** `onStepClick` callback for navigating to completed steps.
119
+ - **AlertDialog responsive:** `responsive` prop for mobile bottom-sheet.
120
+ - **Typography:** `code`, `label-plain-lg/md/sm` variants. Tailwind composite utilities: `text-heading-xl`, `text-body-md`, `text-code`, etc.
121
+ - **Layout spacing:** `--spacing-page-x` (responsive 16→24→40px), `--spacing-section-gap`, `--spacing-card-gap`.
122
+ - **Link colors:** `--color-link`, `--color-link-hover`, `--color-link-visited` tokens.
123
+ - **useFormField:** Now wired into Select, Combobox, Autocomplete, Checkbox, Radio, Switch, Slider, InputOTP.
124
+ - **Chart a11y:** Keyboard tooltip access on BarChart/LineChart. `ariaDescription` on ChartContainer.
125
+ - **Dev warnings:** Token-missing CSS detection + MotionProvider hint (dev mode only).
126
+
127
+ ## HISTORICAL: BREAKING CHANGES (v0.33.x — Tailwind 4 + Toolchain)
128
+
129
+ > **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.
130
+
131
+ - **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`.
132
+ - **tailwind-merge 3.0 → 3.5:** Required for TW4 class recognition.
133
+ - **TypeScript 5.7 → 6.0.2:** `types` defaults to `[]` in TS6. Add explicit `"types": ["node"]` to tsconfig if needed.
134
+ - **ESLint 9 → 10:** Config file lookup starts from linted file directory (not CWD). Verify monorepo configs.
135
+ - **react-zoom-pan-pinch 3 → 4:** `onTransformed` renamed to `onTransform`. Peer dep `^3.0.0 || ^4.0.0`.
136
+
137
+ ## CHANGES (v0.33.1 / v0.33.2)
138
+
139
+ - 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.
140
+
141
+ ## BREAKING CHANGES (v0.33.0)
142
+
143
+ - **EmojiSuggestion:** Named export removed. Use `createEmojiSuggestion(set?)` factory. Default: `createEmojiSuggestion()` (native set).
144
+ - **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.
145
+
146
+ ## CHANGES (v0.33.0)
147
+
148
+ - **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?`.
149
+ - **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`.
150
+ - **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`.
151
+ - **Schedule Send** — `onSchedule?(msg, date)` on RichChatInput. Smart presets (time-of-day aware) + DateTimePicker. Banner shows scheduled time. Send button morphs to SplitButton.
152
+ - **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.
153
+ - **TipTap v2 → v3** — `useEditorState`, `immediatelyRender: false` (SSR-safe), `ListKit`. Fixes React 19 `removeChild` crash.
154
+ - **Composable toolbar** — Exported: `ToolbarButton`, `ToolbarDivider`, `ToolbarGroup`, `BoldButton`, `ItalicButton`, `UnderlineButton`, `StrikeButton`, `HighlightButton`, `CodeButton`, `BulletListButton`, `OrderedListButton`, `BlockquoteButton`, `LinkButton`, `EmojiButton`.
155
+ - **Button `disabled`** — Now inherited from ButtonGroup context.
156
+
157
+ ## BREAKING CHANGES (v0.32.0)
158
+
159
+ - **Button:** `variant="default"` removed (use `"solid"`), `variant="destructive"` removed (use `variant="solid" color="error"`), `color="default"` removed (use `"accent"`).
160
+ - **Chip:** Removed. Use `Badge` instead.
161
+ - **SegmentedControl:** Rewritten. Variants are `"default"` (white pill) and `"solid"` (brand pill). `SegmentedControlItem` no longer exported.
162
+ - **TopBar:** Now renders as `<header>` (was `<div>`).
163
+ - **Sidebar:** Now renders as `<aside>` (was `<div>`).
164
+ - **InfoBlock:** `role="status"` (was `role="alert"`).
165
+ - **Border tokens:** One step darker system-wide.
166
+ - **Dark mode button text:** Pure white `neutral-0` (#fff) on brand-colored buttons.
167
+ - **BottomNavbar:** Bottom padding is now `pb-safe` (safe-area-inset).
168
+ - **iOS inputs:** Forced to `font-size: max(16px, 1em)` on mobile via preset.
169
+
170
+ ## CHANGES (v0.32.0)
171
+
172
+ - **Mobile Responsiveness:**
173
+ - Dialog auto-fullScreens on mobile (<768px). Opt out: `<DialogContent responsive={false}>`.
174
+ - Sheet auto-bottom with swipe-to-dismiss on mobile. Drag handle, 30% threshold. Opt out: `<SheetContent responsive={false}>`.
175
+ - Popover renders as bottom drawer on mobile automatically.
176
+ - `.touch-target` utility — 44px invisible hit area for Apple HIG compliance.
177
+ - `.pt-safe`, `.pb-safe`, `.pl-safe`, `.pr-safe`, `.p-safe` — safe area inset utilities.
178
+ - `useTouchDevice()` — detects touch capability (vs viewport width).
179
+ - `useViewportHeight()` — dynamic viewport height via Visual Viewport API.
180
+ - Sidebar has swipe-to-close on mobile.
181
+ - **DataTable `mobileView="card"`** — Rows render as stacked cards below 640px. First column = card title, rest = label-value pairs.
182
+ - **DataTable `aria-sort`** — Sortable column headers include `aria-sort`.
183
+ - **Charts `ariaLabel` prop** — Configurable screen reader label on all chart components.
184
+ - **SegmentedControl** — Redesigned: `variant="default"` (white pill + shadow-raised) | `variant="solid"` (brand pill). Inset radius, snappy spring animation.
185
+ - **`--shadow-kbd` token** — Keyboard shortcut badge shadow. Use `shadow-kbd` utility.
186
+ - **Checkbox/Radio `size` prop** — `sm | md (default) | lg`.
187
+
188
+ ## CHANGES (v0.31.0)
189
+ - **Alert `size` prop** — `sm | md (default) | lg`. Scales padding, gap, icon, text.
190
+ - **Card `color` prop** — `default | accent | error | success | warning | info | neutral`. Semantic border color.
191
+ - **Card `size` prop** — `sm | md (default) | lg`. Propagated to sub-components via context.
192
+ - **Select `variant` prop** — `default | outline | ghost` on SelectTrigger.
193
+ - **Select `color` prop** — `default | error | success | warning` on SelectTrigger. Sets `aria-invalid` when error.
194
+ - **Tabs `color` prop** — `accent (default) | neutral`. Affects line variant indicator.
195
+ - **Tabs `size` prop** — `sm | md (default) | lg`. Scales height and padding.
196
+ - **Badge `truncate` prop** — Enables ellipsis truncation. Combine with fixed width or `maxWidth`.
197
+ - **New subpath exports** — `./ui/icon`, `./ui/icon-context`, `./ui/icon-group`, `./ui/badge-group`, `./ui/badge-indicator`, `./ui/devalok-grain`, `./ai/types`.
198
+ - **Server-safe fix** — `empty-state`, `priority-indicator`, `status-badge` now correctly get `"use client"` (were incorrectly omitted).
199
+ - **Server-safe detection** — Hardcoded allowlist replaced with `// @server-safe` source annotations.
200
+
201
+ ## CHANGES (v0.30.0)
202
+ - **RichTextEditor `toolbar` prop** — `toolbar?: ToolbarItem[]` whitelist of toolbar items to display. Omit to show all (default). `ToolbarItem` type exported.
203
+ - **`@devalok/shilp-sutra-karm` removed** — Domain components moved to Karm app repo. npm package deprecated.
204
+ - **Warning dark mode fixed** — `warning-*` tokens now have proper dark mode values (higher chroma than category amber).
205
+ - **tailwind-merge fix** — All `text-ds-*` sizes now correctly registered. `cn('text-ds-lg', 'text-accent-11')` no longer strips the color.
206
+ - **AvatarGroup fixes** — Overflow badge text matches avatar size, indicator dots scale with size, aria-labels added.
207
+
208
+ ## BREAKING CHANGES (v0.27.0 — Externalized Dependencies)
209
+
210
+ FilePreview and MarkdownViewer dependencies are now **external** (not bundled).
211
+ Install them if you use these components:
212
+
213
+ ```bash
214
+ pnpm add react-pdf react-zoom-pan-pinch react-syntax-highlighter
215
+ ```
216
+
217
+ These are optional peerDependencies — consumers who don't use FilePreview or MarkdownViewer are unaffected.
218
+
219
+ **Next.js optimization:** Add to your `next.config.js`:
220
+ ```js
221
+ optimizePackageImports: ['@devalok/shilp-sutra']
222
+ ```
223
+
224
+ ## BREAKING CHANGES (v0.23.0 — Semantic Surface & Shadow Tokens)
225
+
226
+ **Surface tokens renamed:** Numeric `surface-1..4` replaced with semantic names.
227
+ | Old | New | Usage |
228
+ |-----|-----|-------|
229
+ | `bg-surface-1` | `bg-surface-base` | Page background |
230
+ | `bg-surface-1` | `bg-surface-sunken` | Shell chrome (sidebar, topbar), board columns |
231
+ | `bg-surface-1` | `bg-surface-overlay` | Dialogs, popovers, dropdowns, inputs |
232
+ | `bg-surface-2` | `bg-surface-raised` | Cards, widgets, panels |
233
+ | `bg-surface-3` | `bg-surface-raised-hover` | Hover states on raised elements |
234
+ | `bg-surface-4` | `bg-surface-raised-active` | Active/pressed states |
235
+
236
+ Same pattern for `border-surface-*`, `text-surface-*`, `ring-surface-*`.
237
+
238
+ **Shadow tokens renamed:** Numeric `shadow-01..05` replaced with semantic names.
239
+ | Old | New |
240
+ |-----|-----|
241
+ | `shadow-01` | `shadow-raised` |
242
+ | `shadow-02` | `shadow-raised-hover` |
243
+ | `shadow-03` | `shadow-floating` |
244
+ | `shadow-04` | `shadow-overlay` |
245
+ | `shadow-05` | (removed — was unused) |
246
+
247
+ **New surface tokens:**
248
+ - `bg-surface-sunken` — recessed areas (sidebar, board columns, segmented track)
249
+ - `bg-surface-overlay` — floating elements (dialogs, popovers, inputs). Diverges from base in dark mode.
250
+ - `bg-surface-inverted` / `text-surface-inverted-fg` — tooltips, inverted badges
251
+ - `bg-surface-disabled` / `text-surface-fg-disabled` — disabled elements
252
+ - `border-surface-border-subtle` — hairline dividers
253
+ - `bg-backdrop` — dialog/sheet backdrop overlay
254
+
255
+ **New shadow tokens:**
256
+ - `shadow-glow` — selection/focus accent glow
257
+ - `shadow-inset` — toggle/segmented track deboss
258
+ - `shadow-ring` / `shadow-ring-sm` — focus ring / subtle separator
259
+
260
+ **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.
261
+
262
+ **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.
263
+
264
+ **Component Decision Matrix:**
265
+ | Building... | Surface | Shadow |
266
+ |-------------|---------|--------|
267
+ | Page/layout | `surface-base` | none |
268
+ | Shell (sidebar/topbar) | `surface-sunken` | `shadow-raised` |
269
+ | Card/widget/panel | `surface-raised` | `shadow-raised` |
270
+ | Card hover | `surface-raised` | `shadow-raised-hover` |
271
+ | Board column/well | `surface-sunken` | none |
272
+ | Popover/menu/dropdown | `surface-overlay` | `shadow-floating` |
273
+ | Dialog/modal/sheet | `surface-overlay` | `shadow-overlay` |
274
+ | Tooltip | `surface-inverted` | `shadow-floating` |
275
+ | Toast | `surface-overlay` | `shadow-floating` |
276
+ | Input (rest) | `surface-overlay` | none |
277
+ | Input (focus) | `surface-overlay` | `shadow-ring` |
278
+ | Button (solid) | accent colors | `shadow-raised` |
279
+ | Button (disabled) | `surface-disabled` | none |
280
+ | Segmented track | `surface-sunken` | `shadow-inset` |
281
+ | Selected item | current surface | `shadow-glow` |
282
+
283
+ ## BREAKING CHANGES (v0.18.0 — Framer Motion + OKLCH)
284
+
285
+ **New runtime dependency:** `framer-motion@^12.36.0` (bundled). Karm consumers must install `framer-motion@^12.0.0` as peer dep.
286
+
287
+ **Transitions removed:** `Fade`, `Collapse`, `Grow`, `Slide` from `./ui/transitions` no longer exist. Use `MotionFade`, `MotionCollapse`, `MotionSlide` from `@devalok/shilp-sutra/motion/primitives`.
288
+
289
+ **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.
290
+
291
+ **`useReducedMotion()` removed:** Use `<MotionProvider reducedMotion="user">` at app root.
292
+
293
+ **New motion system:**
294
+ - `import { MotionProvider, springs, tweens } from '@devalok/shilp-sutra/motion'`
295
+ - `import { MotionFade, MotionCollapse, MotionSlide, MotionPop, MotionScale, MotionStagger } from '@devalok/shilp-sutra/motion/primitives'`
296
+ - Springs: `springs.snappy`, `springs.smooth`, `springs.bouncy`, `springs.gentle`
297
+ - Tweens: `tweens.fade`, `tweens.colorShift`
298
+
299
+ **Spinner v2:** New props `state?: 'spinning' | 'success' | 'error'`, `variant?: 'filled' | 'bare'`, `delay?: number`, `onComplete?: () => void`
300
+
301
+ **Button `onClickAsync`:** New prop `onClickAsync?: (e) => Promise<void>` — auto-manages loading → success/error → idle states. `asyncFeedbackDuration?: number` (default 1500ms).
302
+
303
+ **Server safety changes:** EmptyState, StatusBadge, PriorityIndicator, Spinner are NOT server-safe (they use Framer Motion). Do NOT import from RSC.
304
+
305
+ **Build:** `framer-motion` and `sonner` moved from `dependencies` to `devDependencies` (bundled at build time — no consumer install needed for core).
306
+
307
+ **New APIs in v0.18.0:**
308
+ - Combobox: `accessibleLabel?: string` — custom aria-label for trigger (falls back to placeholder)
309
+ - Slider: multi-thumb support — pass array `defaultValue={[25, 75]}` for range sliders
310
+
311
+ ## CHANGES (v0.16.0)
312
+ - **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
313
+ - **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).
314
+ - **ActivityFeed**: New composed component — `@devalok/shilp-sutra/composed/activity-feed` — vertical timeline with colored dots, actor avatars, expandable detail, compact mode, load more
315
+ - EmptyState: `iconSize?: 'sm' | 'md' | 'lg'` prop for icon dimension control
316
+ - BottomNavbar: `badge?: number` on BottomNavItem for notification counts (99+ cap)
317
+ - AppSidebar: `preFooterClassName?: string` for scrollable preFooterSlot
318
+
319
+ ## CHANGES (v0.15.0)
320
+ - **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.
321
+ - CommandPalette: Staggered slide-up animations for items, fade-in for groups, scale-in search icon, active item color transitions
322
+
323
+ ## CHANGES (v0.14.0)
324
+ - **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.
325
+ - TabsTrigger: Added gap-ds-02 (4px) between icon and label
326
+ - AppSidebar: footer.version now accepts string | { label, href } for clickable version links
327
+
328
+ ## CHANGES (v0.13.0)
329
+ - EmptyState: icon prop now accepts ComponentType (e.g. Tabler icon references) in addition to ReactNode
330
+ - NotificationCenter: Notification.actions?: NotificationAction[] — inline action buttons (Approve/Deny) per notification
331
+ - NotificationCenter: Tier dot now doubles as read/unread marker; separate unread dot removed
332
+ - AppSidebar: footer.promo?: SidebarPromo — dismissable promo banner with icon, text, action button
333
+ - AppSidebar: Footer links + version render on same line with · dividers
334
+ - Collapsible: Now uses height-based expand/collapse animation (animate-collapsible-down/up)
335
+ - Tailwind preset: 4 new keyframes + utilities — accordion-down, accordion-up, collapsible-down, collapsible-up
336
+
337
+ ## CHANGES (v0.12.0)
338
+ - Input: Softer resting border (border-subtle instead of border), subtler focus ring (ring-1 ring-focus/50 instead of ring-2 ring-focus)
339
+ - Tailwind preset: 9 animation keyframes + utilities (fade-in, fade-out, slide-up, slide-right, scale-in, scale-out, glow-pulse, scale-bounce, lift)
340
+ - Tailwind preset: Stagger plugins — .delay-stagger (30ms × --stagger-index), .delay-stagger-50 (50ms × --stagger-index)
341
+
342
+ ## BREAKING CHANGES (v0.11.0 — dark mode)
343
+ - 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
344
+ - 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
345
+ - New primitive token: --pink-1000 (#150208) near-black
346
+
347
+ ## BREAKING CHANGES (v0.8.0)
348
+ - 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.
349
+ - StatusBadge: Pass either `status` OR `color`, not both (discriminated union).
350
+ - Input/Textarea: Now auto-inherit state, aria-describedby, aria-required from FormField context. Explicit props override.
351
+
352
+ ## BREAKING CHANGES (v0.18.0 — OKLCH token migration, continued)
353
+ - All color primitives migrated from hex (50-950 shades) to OKLCH (12 functional steps)
354
+ - Old shade numbers: --pink-50..950. New step numbers: --pink-1..12 (OKLCH values)
355
+ - 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
356
+ - 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
357
+ - 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}
358
+ - New Tailwind utilities: accent-1..12, secondary-1..12, surface-base/raised/sunken/overlay/inverted/disabled, status/category step utilities
359
+ - Backward compat: ALL old semantic token names preserved as aliases. --color-interactive still works → maps to --color-accent-9
360
+ - Consumer rebranding: override --color-accent-1..12 CSS vars OR use generateScale() utility with a seed color
361
+ - Dark mode: algorithmically derived (OKLCH curves), NOT hex overrides. Surfaces lighten with elevation.
362
+ - 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
363
+
364
+ ## v0.22.0 — UI Polish & Micro-Refinement
365
+
366
+ **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).
367
+
368
+ **Transitions**: All CSS transitions use `ease-productive-standard` easing. Tween presets aligned: `tweens.fade` = 0.11s, `tweens.colorShift` = 0.07s.
369
+
370
+ **New Tailwind utilities**:
371
+ - `.focus-ring` — double-ring (2px surface + 2px accent), use on custom interactive elements (buttons, cards)
372
+ - `.focus-ring-inset` — inset ring, use on buttons over solid backgrounds
373
+ - `.focus-ring-sm` — 1px subtle ring, use on inputs and small controls
374
+ - `.tabular-nums` — aligned numbers via `font-variant-numeric: tabular-nums`
375
+
376
+ **Category color utilities** (standalone, not tied to Badge/Chip):
377
+ - 7 colors: teal, amber, slate, indigo, cyan, orange, emerald
378
+ - 4 steps each: bg-category-{color}-{3|7|9|11}, text-category-{color}-{3|7|9|11}, border-category-{color}-{3|7|9|11}
379
+ - Use for: board column accents, status indicators, tag colors, category chips
380
+
381
+ **Dense size variant (xs)** added to Input, Select, SearchInput, Button, Textarea:
382
+ - xs = 28px height (h-ds-xs-plus), 12px text (text-ds-sm), compact padding
383
+ - Designed for filter bars, toolbar controls, and dense UI contexts
384
+ - Button also gets icon-xs (28×28) for compact icon buttons
385
+ - Size matrix: xs=28px | sm=32px | md=40px (default) | lg=48px
386
+
387
+ **Separator**: New `variant` prop — `"gradient" | "gradient-left" | "gradient-right"`. Default unchanged.
388
+
389
+ **Checkbox**: Path-draw animation (stroke draws progressively). Uncontrolled usage now works.
390
+
391
+ **Tooltip**: Auto-wraps with `<TooltipProvider>` — no manual provider needed. Text color fixed for dark mode.
392
+
393
+ **Avatar fallback**: Now respects `shape` prop (was always circle). Font size auto-scales with avatar size (v0.22.3).
394
+
395
+ **AvatarGroup renderAvatar**: Wrapper is positioning-only — pass `size` directly to your Avatar, do NOT use `className="h-full w-full"` (v0.22.3).
396
+
397
+ **New hover states**: Checkbox, Radio, Switch track, Select items, DropdownMenu items, Combobox trigger.
398
+
399
+ ## AI Command System (v0.25.0+)
400
+
401
+ New `@devalok/shilp-sutra/ai` module — composable AI command interface.
402
+
403
+ **CommandBar** — Unified input (hero/inline/floating variants):
404
+ ```tsx
405
+ <CommandBar
406
+ variant="hero"
407
+ onSubmit={(query) => sendToAI(query)} // AI submission
408
+ groups={commandGroups} // optional command palette filtering
409
+ state="idle" // idle | typing | processing | responded
410
+ greeting="Good morning, Mudit."
411
+ hints={['Add member...', 'Check status...']}
412
+ agentName="Devadoot"
413
+ agentIcon={<DevadootIcon state={iconState} />}
414
+ >
415
+ <AIConversation messages={messages} isProcessing={loading} />
416
+ </CommandBar>
417
+ ```
418
+
419
+ **BlockRenderer** — Renders AI response JSON as DS components:
420
+ ```tsx
421
+ <BlockRenderer blocks={response.blocks} onAction={handleAction} customBlocks={myBlocks} />
422
+ ```
423
+
424
+ Block types: `text`, `table`, `confirm`, `success`, `error`, `info`, `loading`, `divider`, `stat_row`.
425
+
426
+ **AICommandProvider** — Optional context wrapper:
427
+ ```tsx
428
+ <AICommandProvider customBlocks={karmBlocks} onAction={handle} agent={{ name: 'Devadoot' }}>
429
+ {/* CommandBar + AIConversation auto-wire from context */}
430
+ </AICommandProvider>
431
+ ```
432
+
433
+ **DevadootIcon** — Animated Devalok chakra with gradient state animations:
434
+ ```tsx
435
+ <DevadootIcon state="processing" size={20} /> // idle | processing | responded | error
436
+ ```
437
+
438
+ ## Install & Setup
439
+
440
+ pnpm add @devalok/shilp-sutra
441
+
442
+ ### Next.js Setup (Required for Next.js + pnpm)
443
+
444
+ Add to next.config.js:
445
+ ```js
446
+ transpilePackages: ["@devalok/shilp-sutra", "@devalok/shilp-sutra-brand"]
447
+ ```
448
+
449
+ // Import components (barrel):
450
+ import { Button, Card, Dialog } from '@devalok/shilp-sutra'
451
+
452
+ // Import per-component (recommended for Server Components):
453
+ import { Button } from '@devalok/shilp-sutra/ui/button'
454
+ import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
455
+ import { TopBar } from '@devalok/shilp-sutra/shell/top-bar'
456
+
457
+ // Chat primitives (v0.29.0+):
458
+ import { MessageList, Message, SystemMessage, MessageInput, DateSeparator, UnreadSeparator, TypingIndicator } from '@devalok/shilp-sutra/ui/chat'
459
+
460
+ // AI command system (v0.25.0+):
461
+ import { CommandBar, AIConversation, BlockRenderer, AICommandProvider, DevadootIcon } from '@devalok/shilp-sutra/ai'
462
+
463
+ // Toast (imperative, no hook needed):
464
+ import { toast } from '@devalok/shilp-sutra/ui/toast'
465
+
466
+ // Hooks:
467
+ import { useColorMode } from '@devalok/shilp-sutra/hooks/use-color-mode'
468
+
469
+ // CSS tokens (import once at app root — already included in /css):
470
+ import '@devalok/shilp-sutra/css'
471
+
472
+ ## IMPORT PATH CHEATSHEET (don't guess — these subpaths are NOT always the kebab-case of the component name)
473
+
474
+ > **0.40.0 — barrel peer-cliff cleanup.** Components below marked `MANDATORY per-component` were removed from their parent barrel (`/ui`, `/composed`, `/ai`, `/ai/blocks`) because they statically import optional peers (`input-otp`, `sonner`, `date-fns`, `@emoji-mart/*`, `react-pdf`, `react-zoom-pan-pinch`, `react-markdown`, `remark-gfm`, `react-syntax-highlighter`, `@tiptap/*`). Fresh consumers using the barrel were getting `Module not found` at build time. The per-component subpath is now the ONLY way to import them. See MIGRATION.md → "v0.40.0 — barrel peer-cliff cleanup" for the full before/after.
475
+
476
+ Common confusions to memorize:
477
+
478
+ | Component / API | Exact import path |
479
+ |------------------------------------------------|----------------------------------------------------------------|
480
+ | `FormField`, `FormHelperText`, `useFormField` | `@devalok/shilp-sutra/ui/form` (NOT `ui/form-field`)|
481
+ | `Label` | `@devalok/shilp-sutra/ui/label` |
482
+ | `AppSidebar` | `@devalok/shilp-sutra/shell/sidebar` (NOT `shell/app-sidebar`)|
483
+ | `TopBar`, `TopBar.*` | `@devalok/shilp-sutra/shell/top-bar` |
484
+ | `BottomNavbar` | `@devalok/shilp-sutra/shell/bottom-navbar` |
485
+ | `AppCommandPalette` | `@devalok/shilp-sutra/shell/app-command-palette` |
486
+ | `CommandRegistryProvider`, `useCommandRegistry`| `@devalok/shilp-sutra/shell/command-registry` |
487
+ | `NotificationCenter` | `@devalok/shilp-sutra/shell/notification-center` |
488
+ | `NotificationPreferences` | `@devalok/shilp-sutra/shell/notification-preferences` |
489
+ | `LinkProvider`, `useLink` | `@devalok/shilp-sutra/shell/link-context` |
490
+ | `CommandPalette` (lower-level palette) | `@devalok/shilp-sutra/composed/command-palette` |
491
+ | `BarChart`, `LineChart`, `AreaChart`, `PieChart`, `RadarChart`, `GaugeChart`, `Sparkline`, `ChartContainer`, `Legend` | `@devalok/shilp-sutra/ui/charts` (full barrel, pulls all 9 d3-\* peers) — **prefer per-chart subpath when possible: `/ui/charts/bar-chart`, `/ui/charts/line-chart`, `/ui/charts/area-chart`, `/ui/charts/pie-chart`, `/ui/charts/radar-chart`, `/ui/charts/gauge-chart`, `/ui/charts/sparkline`, `/ui/charts/chart-container`** (each pulls only the d3-\* peers it needs — BarChart needs `d3-scale` + `d3-axis` + `d3-selection`; PieChart/RadarChart need only `d3-shape`) |
492
+ | `DataTable` | `@devalok/shilp-sutra/ui/data-table` |
493
+ | `DataTableToolbar` | `@devalok/shilp-sutra/ui/data-table-toolbar` |
494
+ | `DatePicker`, `DateRangePicker`, `DateTimePicker`, `TimePicker`, `CalendarGrid`, `YearPicker`, `MonthPicker`, `Presets`, `useCalendar` | `@devalok/shilp-sutra/composed/date-picker` **MANDATORY per-component (0.40.0+)** — pulls `date-fns` |
495
+ | `Toaster` | `@devalok/shilp-sutra/ui/toaster` **MANDATORY per-component (0.40.0+)** — pulls `sonner` |
496
+ | `toast` | `@devalok/shilp-sutra/ui/toast` **MANDATORY per-component (0.40.0+)** — pulls `sonner` |
497
+ | `InputOTP`, `InputOTPGroup`, `InputOTPSeparator`, `InputOTPSlot` | `@devalok/shilp-sutra/ui/input-otp` **MANDATORY per-component (0.40.0+)** — pulls `input-otp` |
498
+ | `EmojiPicker`, `EmojiPickerPopover`, `EmojiData`, `EmojiSet` | `@devalok/shilp-sutra/composed/emoji-picker` **MANDATORY per-component (0.40.0+)** — pulls `@emoji-mart/data` + `@emoji-mart/react` |
499
+ | `EmojiNode`, `EmojiNodeAttrs` | `@devalok/shilp-sutra/composed/extensions/emoji-node` **MANDATORY per-component (0.40.0+)** — pulls `@tiptap/*` |
500
+ | `createEmojiSuggestion` | `@devalok/shilp-sutra/composed/extensions/emoji-suggestion` **MANDATORY per-component (0.40.0+)** — pulls `@tiptap/*` |
501
+ | `FilePreview`, `FilePreviewProps` | `@devalok/shilp-sutra/composed/file-preview` **MANDATORY per-component (0.40.0+)** — pulls `react-pdf` + `react-zoom-pan-pinch` |
502
+ | `MarkdownViewer` | `@devalok/shilp-sutra/composed/markdown-viewer` **MANDATORY per-component (0.40.0+)** — pulls `react-markdown` + `react-syntax-highlighter` + `remark-gfm` |
503
+ | `RichChatInput`, `AudioPlayer`, `AudioWaveform`, `useVoiceRecorder` | `@devalok/shilp-sutra/composed/rich-chat-input` **MANDATORY per-component (0.40.0+)** — pulls `@tiptap/*` |
504
+ | `RichTextEditor`, `RichTextViewer`, `MentionItem`, `ToolbarItem` | `@devalok/shilp-sutra/composed/rich-text-editor` **MANDATORY per-component (0.40.0+)** — pulls `@tiptap/*` |
505
+ | `MessageList`, `Message`, `SystemMessage`, `MessageInput`, `DateSeparator`, `UnreadSeparator`, `TypingIndicator` | `@devalok/shilp-sutra/ui/chat` |
506
+ | `CommandBar` | `@devalok/shilp-sutra/ai/command-bar` (also re-exported from `/ai`) |
507
+ | `AIConversation` | `@devalok/shilp-sutra/ai/conversation` |
508
+ | `BlockRenderer` | `@devalok/shilp-sutra/ai/block-renderer` **MANDATORY per-component (0.40.0+)** — transitively pulls `react-markdown` + `remark-gfm` via ErrorBlock/TextBlock |
509
+ | `AICommandProvider` | `@devalok/shilp-sutra/ai/ai-command-provider` |
510
+ | `DevadootIcon` | `@devalok/shilp-sutra/ai` |
511
+ | `ErrorBlock` | `@devalok/shilp-sutra/ai/blocks/error` **MANDATORY per-component (0.40.0+)** — pulls `react-markdown` + `remark-gfm` |
512
+ | `TextBlock` | `@devalok/shilp-sutra/ai/blocks/text` **MANDATORY per-component (0.40.0+)** — pulls `react-markdown` + `remark-gfm` |
513
+ | `BlockTable`, `ConfirmBlock`, `DividerBlock`, `InfoBlock`, `LoadingBlock`, `StatRowBlock`, `SuccessBlock` | `@devalok/shilp-sutra/ai/blocks` (barrel — these 7 are peer-cliff-free) |
514
+ | `useColorMode` | `@devalok/shilp-sutra/hooks/use-color-mode` |
515
+ | `useMobile` | `@devalok/shilp-sutra/hooks/use-mobile` |
516
+ | `MotionProvider`, `springs`, `tweens`, `stagger`, `useMotion` | `@devalok/shilp-sutra/motion` |
517
+ | `MotionFade`, `MotionScale`, `MotionPop`, `MotionSlide`, `MotionCollapse`, `MotionStagger`, `MotionStaggerItem` | `@devalok/shilp-sutra/motion/primitives` |
518
+
519
+ Components named directly after their file (`Button` → `ui/button`, `Card` → `ui/card`, `Avatar` → `ui/avatar`, `Stack` → `ui/stack`, `Text` → `ui/text`, etc.) follow the kebab-case-of-name rule. The table above is for the ones that DON'T.
520
+
521
+ **When in doubt:** `cat node_modules/@devalok/shilp-sutra/package.json | jq '.exports | keys'` lists every available subpath in the installed version.
522
+
523
+ ## ICON API — one shape across every component (v0.40.0+)
524
+
525
+ Every icon-accepting prop in the design system (`startIcon`, `endIcon`, `icon`, etc. — see list below) takes the **`IconInput`** type. Pass any of these four shapes interchangeably:
526
+
527
+ ```tsx
528
+ import { IconPlus } from '@tabler/icons-react'
529
+ import { Icon } from '@devalok/shilp-sutra/ui/icon'
530
+
531
+ <Button startIcon={<Icon icon={IconPlus} />}>Add</Button> // canonical
532
+ <Button startIcon={<IconPlus />}>Add</Button> // raw Tabler element
533
+ <Button startIcon={IconPlus}>Add</Button> // component ref
534
+ <Button startIcon={<span>+</span>}>Add</Button> // custom node
535
+ ```
536
+
537
+ All four work identically at the call site. The component wraps its icon slot in `<IconProvider size={...}>` so size + stroke flow via React context — no `className="h-4 w-4"` overrides needed.
538
+
539
+ **Components on the unified API:** Button, IconButton, Badge, Combobox, SegmentedControl, Stepper, StatCard, TreeItem (TreeNode.icon), OAuthButton (icon + linkedIcon), Chat.Message.Avatar, Chat.Message.Action, Chat.SystemMessage, AIConversation (agent.icon), AICommandProvider (agent.icon), CommandBar (item.icon), EmptyState (kills the dual ReactNode|ComponentType signature), BulkActionBar (action.icon), ActivityFeed (item.icon), CommandPalette (item.icon), TopBar (UserMenuItem.icon, TopBar.IconButton.icon), Sidebar (NavItem.icon, NavSubItem.icon, footer.promo.icon), BottomNavbar (item.icon), AppCommandPalette (SearchResult.icon), CommandRegistry (CommandPageItem.icon).
540
+
541
+ **Internals** (`<Toaster>`, `<Toast>`'s success/error icons) use Sonner's own type contract and don't accept consumer-passed icons — that's by design.
542
+
543
+ **When to use which shape:**
544
+ - `<Icon icon={IconX} />` when you want explicit size/stroke control (size flows from context if not set)
545
+ - `<IconX />` when you trust the surrounding `IconProvider` and don't need stroke control
546
+ - `IconX` (raw ref) when you want the helper to do the wrapping for you (auto-wraps to `<Icon icon={IconX} />`)
547
+ - Custom node when the "icon" is actually `<span>$</span>` or an emoji
548
+
549
+ **Migration:** zero consumer changes needed if you were already passing valid React content. Components that previously took strict `IconProps['icon']` (BulkActionBar, Message.Action) or `ComponentType<{className}>` (SegmentedControl) now also accept the other three shapes. Strict-to-loose type widening — no breaking calls.
550
+
551
+ ## CRITICAL: Differences from shadcn/ui
552
+
553
+ If you have shadcn/ui knowledge, these are the differences that WILL trip you up:
554
+
555
+ | shadcn/ui pattern | shilp-sutra equivalent | Notes |
556
+ |---|---|---|
557
+ | variant="destructive" | color="error" | Two-axis system: variant=shape, color=intent |
558
+ | size="default" | size="md" | All sizes: sm, md, lg (never "default") |
559
+ | <Select size="lg"> | <SelectTrigger size="lg"> | Size goes on trigger, NOT root |
560
+ | <Chip> | <Badge onClick={...}> | Chip is deprecated, use Badge with onClick |
561
+ | useToast() + toast({ variant }) | toast.success('msg') | Imperative API, no hook needed |
562
+ | Badge variant="destructive" | Badge variant="solid" color="error" | Two-axis: variant + color |
563
+ | Alert + AlertTitle + AlertDescription | <Alert title="..." color="error"> | Single component, not compound |
564
+ | Form + FormField + FormItem + FormLabel + FormControl + FormDescription + FormMessage | FormField + Label + Input + FormHelperText + useFormField() | Simpler API, hook-based a11y wiring |
565
+ | Pagination | PaginationRoot | Root component name differs |
566
+
567
+ ### The Two-Axis Variant System
568
+
569
+ Many components use TWO props where shadcn uses one:
570
+ - `variant` controls SHAPE/SURFACE: solid, outline, ghost, subtle, filled, etc.
571
+ - `color` controls INTENT/SEMANTICS: default, error, success, warning, info, etc.
572
+
573
+ Examples:
574
+ <Button variant="solid" color="error">Delete</Button> // red solid button
575
+ <Button variant="soft" color="warning">Pending</Button> // amber tinted button
576
+ <Button variant="soft" color="accent">Cancel</Button> // preferred for secondary actions
577
+ <Badge variant="solid" color="success">Active</Badge> // green solid badge
578
+ <Alert variant="solid" color="warning">Warning!</Alert> // amber filled alert
579
+
580
+ **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.
581
+
582
+ Components with two-axis system: Button, Badge, Alert, Banner, Progress, StatusBadge
583
+
584
+ ## Component Quick Reference
585
+
586
+ ### Inputs & Controls
587
+ - 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
588
+ - IconButton: icon(ReactNode, required as PROP — NOT children) shape(square|circle) size(sm|md|lg) + aria-label required. **Children rejected by type** (`Omit<ButtonProps, 'children'>`); pass the icon via `icon=` prop. Correct: `<IconButton icon={<Icon icon={IconArrowRight} />} aria-label="Submit" />`. Wrong: `<IconButton><Icon icon={IconArrowRight} /></IconButton>` (TS error). Wrap with `<Icon icon={…} />` (not raw Tabler `<IconX />`) so the size context cascades.
589
+ - 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.
590
+ - 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.
591
+ - 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.
592
+ - 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'
593
+ - SearchInput: size(xs|sm|md|lg) + loading, onClear. Delegates to Input v2 sections internally.
594
+ - NumberInput: value + onValueChange, min, max, step (controlled only)
595
+ - Textarea: size(xs|sm|md|lg) state(default|error|warning|success)
596
+ - 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.
597
+ - Checkbox: checked, onCheckedChange, error(boolean), indeterminate(boolean)
598
+ - Switch: checked, onCheckedChange, error(boolean), size(sm|md|lg), color(accent|success|warning), thumbIcon(ReactNode)
599
+ - RadioGroup > RadioGroupItem(value)
600
+ - Select > SelectTrigger(size: xs|sm|md|lg) > SelectValue; SelectContent > SelectItem(value)
601
+ - Toggle: variant(default|outline) size(sm|md|lg)
602
+ - ToggleGroup > ToggleGroupItem (variant/size propagate from root)
603
+ - SegmentedControl: variant(default|solid) size(sm|md|lg) options selectedId onSelect. Types: SegmentedControlOption = { id, text, icon? }, SegmentedControlSize = 'sm' | 'md' | 'lg', SegmentedControlVariant = 'default' | 'solid'
604
+ - Slider: standard Radix slider
605
+
606
+ ### Feedback & Notifications
607
+ - Alert: variant(subtle|solid|outline) color(info|success|warning|error|neutral) size(sm|md|lg) + title, onDismiss
608
+ - Banner: color(info|success|warning|error|neutral) + actions?(ReactNode), onDismiss. Mobile flex-wrap for multiple buttons.
609
+ - Toast: imperative API via toast.success/error/warning/info/loading/message/undo/promise/upload/custom — REQUIRES <Toaster> at layout root
610
+ - Spinner: size(sm|md|lg) — renders with role="status"
611
+ - 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)
612
+
613
+ NOTIFICATION SELECTION GUIDE:
614
+ - Alert: inline contextual feedback within a form or page section
615
+ - Banner: persistent page-level notification above content
616
+ - Toast: transient notification triggered by user action (needs <Toaster>, then call toast.success() etc.)
617
+
618
+ ### Data Display
619
+ - 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).
620
+ - Chip: DEPRECATED — Use `<Badge onClick={...}>` instead. Chip wrapper maps label prop to children for backward compat.
621
+ - 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.
622
+ - 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
623
+ - Table > TableHeader > TableRow > TableHead; TableBody > TableRow > TableCell; TableFooter; TableCaption
624
+ - 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'
625
+ - Code: variant(inline|block)
626
+ - Skeleton: variant(rectangle|circle|text) animation(pulse|shimmer|none)
627
+ - StatCard: title/label, value, delta, icon, prefix, suffix, comparisonLabel, secondaryLabel, progress, sparkline, onClick, href, accent(default|success|warning|error|info), footer
628
+ - ColorSwatch: color(CSS string) size(sm|md|lg) shape(circle|square|rounded) ring(boolean) — for dynamic runtime colors
629
+ - StatusDot: status(healthy|warning|critical|neutral|inactive) size(sm|md|lg) pulse?(boolean, default true for healthy) label?(string)
630
+ - 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
631
+ - 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.
632
+
633
+ ### Chat Primitives (ui/chat/)
634
+ Import: `@devalok/shilp-sutra/ui/chat`
635
+ - MessageList: children, autoScroll?(true), newMessageCount?(number, shows floating "N new" pill), onScrollToBottom?(), onLoadMore?(), isLoadingMore?(boolean), emptySlot?(ReactNode), headerSlot?(ReactNode). role="log" aria-live="polite".
636
+ - 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'))
637
+ - SystemMessage: variant('event'|'alert') icon?(ReactNode) timestamp?(string) children
638
+ - 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.
639
+ - DateSeparator: date(Date|string), format?((date)=>string). Shows "Today", "Yesterday", or "Mar 15".
640
+ - UnreadSeparator: label?('NEW'), count?(number). Accent-colored horizontal rule.
641
+ - TypingIndicator: users({name, image?}[]). Shows animated bouncing dots + "Alice is typing..." / "Alice and Bob are typing..." / "Several people are typing..."
642
+
643
+ ### Overlays
644
+ - Dialog > DialogTrigger; DialogContent > DialogHeader > DialogTitle, DialogDescription; [content]; DialogFooter
645
+ - AlertDialog > AlertDialogTrigger; AlertDialogContent > AlertDialogHeader > AlertDialogTitle; AlertDialogFooter > AlertDialogCancel, AlertDialogAction
646
+ - Sheet: side(top|bottom|left|right) > SheetTrigger; SheetContent > SheetHeader > SheetTitle; [content]; SheetFooter
647
+ - Popover > PopoverTrigger; PopoverContent
648
+ - Tooltip: auto-wraps with <TooltipProvider> (no manual provider needed) > Tooltip > TooltipTrigger; TooltipContent
649
+ - HoverCard > HoverCardTrigger; HoverCardContent
650
+ - Collapsible > CollapsibleTrigger; CollapsibleContent
651
+
652
+ ### Navigation
653
+ - Tabs > TabsList(variant: line|contained) > TabsTrigger(value); TabsContent(value) — variant propagates via context
654
+ - Accordion(type: single|multiple) > AccordionItem(value) > AccordionTrigger(chevronPosition?: 'left'|'right', default 'right'); AccordionContent
655
+ - Breadcrumb > BreadcrumbList > BreadcrumbItem > BreadcrumbLink | BreadcrumbPage; BreadcrumbSeparator
656
+ - PaginationRoot > PaginationContent > PaginationItem > PaginationLink(isActive) | PaginationPrevious | PaginationNext | PaginationEllipsis
657
+ - DropdownMenu > DropdownMenuTrigger; DropdownMenuContent > DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuCheckboxItem, DropdownMenuRadioGroup > DropdownMenuRadioItem
658
+ - ContextMenu > ContextMenuTrigger (right-click); ContextMenuContent > same sub-components as DropdownMenu
659
+ - Menubar > MenubarMenu > MenubarTrigger; MenubarContent > same sub-components
660
+ - NavigationMenu > NavigationMenuList > NavigationMenuItem > NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink
661
+
662
+ ### Layout
663
+ - Stack: direction(vertical|horizontal) gap(SpacingToken|number) align, justify, wrap
664
+ - Container: maxWidth(default|body|full)
665
+ - Separator: orientation(horizontal|vertical)
666
+ - Sidebar: complex — see llms-full.txt for complete tree
667
+
668
+ ### Form Pattern
669
+ - FormField: state(FormHelperState) > Label + Input + FormHelperText. Type: FormHelperState = 'helper' | 'error' | 'warning' | 'success'
670
+ - useFormField() hook returns { state, helperTextId, required } from FormField context
671
+ - Wire accessibility: const { state, helperTextId } = useFormField(); then aria-describedby={helperTextId}, aria-invalid={state === 'error'}
672
+ - Input/Textarea auto-wire from FormField context (no manual hookup needed). Explicit props override.
673
+
674
+ ### Composed Components
675
+ - ConfirmDialog: open, onOpenChange, title, description, onConfirm + confirmText, cancelText, color(default|error), loading
676
+ - PageHeader: title, subtitle, breadcrumbs[], actions(ReactNode)
677
+ - 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.
678
+ - 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)
679
+ - ContentCard: variant(default|outline|ghost) padding(default|compact|spacious|none)
680
+ - EmptyState: icon(ReactNode or ComponentType), title(required), description, action(ReactNode), compact
681
+ - PriorityIndicator: priority(Priority) display(compact|full). Type: Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent'
682
+ - SimpleTooltip: wraps Tooltip compound into single component
683
+ - DatePicker, DateRangePicker, DateTimePicker
684
+ - TimePicker: standalone time selector — value(Date|null), onChange, format('12h'|'24h'), minuteStep, showSeconds, disabled
685
+ - CalendarGrid: low-level calendar widget — currentMonth, selected, rangeStart/End, onSelect, onMonthChange, events(CalendarEvent[])
686
+ - YearPicker: decade year grid — currentYear, selectedYear, onYearSelect, minDate, maxDate
687
+ - MonthPicker: month grid — currentYear, selectedMonth(0-11), onMonthSelect, minDate, maxDate
688
+ - Presets: date range quick-select buttons — presets(PresetKey[]), onSelect(start, end). Keys: today, yesterday, last7days, last30days, thisMonth, lastMonth, thisYear
689
+ - useCalendar: hook for calendar month state — returns currentMonth, goToPreviousMonth, goToNextMonth, goToMonth, goToYear
690
+ - (UploadProgress REMOVED — upload tracking is now built into toast.upload())
691
+ - 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)
692
+ - RichTextViewer: read-only renderer for RichTextEditor HTML content (renders all above content types)
693
+ - 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.
694
+ - 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.
695
+ - 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.
696
+ - MemberPicker: thin wrapper around MultiSelectPopover with Avatar rendering
697
+ - MultiSelectPopover: items/groups, value, onValueChange, searchPlaceholder, onSearch?(async), renderItem?, emptyMessage, maxSelections. Generic multi-select popover with search + checkmarks.
698
+ - FilterBar: searchValue, onSearchChange, onClearAll, size(xs|sm|md). Children: FilterSelect(label, value, onValueChange, options), FilterMultiSelect(label, value, onValueChange, options). Size propagates via context.
699
+ - InlineEdit: value, onSave(string=>void|Promise), placeholder, textClassName, inputSize(xs|sm|md), multiline, readOnly, maxLength, saving. Click-to-edit text → input transition.
700
+ - FormSection: title, description?, collapsible?, defaultOpen?. Titled form section with separator, optional collapse.
701
+ - BulkActionBar: show, count, onClearSelection, actions[{label,icon?,onClick,color?,disabled?}]. Fixed bottom floating bar for multi-select contexts.
702
+ - DeadlineIndicator: deadline(Date|string), warningThreshold?(1440min), criticalThreshold?(240min), format(relative|absolute), showIcon. Color transitions: green→yellow→red→overdue.
703
+ - MasterDetail: selected, onBack, masterWidth, breakpoint(sm|md|lg). Compound: MasterDetail.List, MasterDetail.Detail, MasterDetail.ListItem(active). Desktop=grid, mobile=stacked with back button.
704
+ - MarkdownViewer: content(string), compact?, allowHtml?(false), linkTarget?('_blank'). Renders markdown with design system tokens.
705
+ - 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.
706
+ - 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.
707
+ - 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.
708
+ - ErrorDisplay, GlobalLoading
709
+ - Loading skeletons: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
710
+ - Page skeletons: DashboardSkeleton, ProjectListSkeleton, TaskDetailSkeleton (no props, server-safe)
711
+
712
+ ### Shell Components (app-level layout)
713
+ - 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? }
714
+ - 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? }
715
+
716
+ ### AppSidebar (v0.10.0 additions)
717
+ - NavItem.children?: NavSubItem[] — collapsible sub-list with chevron toggle
718
+ - NavItem.defaultOpen?: boolean — control initial collapsed state
719
+ - NavItem.badge?: string | number — badge on nav item (99+ cap for numbers)
720
+ - NavGroup.action?: ReactNode — action button next to group label
721
+ - footer?: SidebarFooterConfig — structured footer with links, version, slot, promo (replaces footerLinks)
722
+ - headerSlot?: ReactNode — content between user info and navigation
723
+ - preFooterSlot?: ReactNode — content between navigation and footer
724
+ - renderItem?: (item, defaultRender) => ReactNode | null — custom item rendering
725
+
726
+ - BottomNavbar: mobile navigation, user is optional. Types: BottomNavItem = { title, href, icon, exact?, badge? }, BottomNavbarUser = { name, role? }
727
+ - 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 }
728
+ - NotificationPreferences: preferences[], projects[], onSave, onToggleMute, onUpdateTier, onDelete. Types: NotificationPreference = { id, userId?, projectId, channel, minTier, muted }, NotificationProject = { id, title }
729
+ - 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? }
730
+ - LinkProvider: wraps app with router-agnostic Link component — component(ForwardRefComponent), children. useLink() hook returns the Link component.
731
+
732
+ ### Motion System (Framer Motion)
733
+ - Setup: Wrap app root with `<MotionProvider>` from `@devalok/shilp-sutra/motion`. Handles reduced-motion detection globally.
734
+ - Import presets: `import { springs, tweens, stagger } from '@devalok/shilp-sutra/motion'`
735
+ - Import primitives: `import { MotionFade, MotionScale, MotionPop, MotionSlide, MotionCollapse, MotionStagger, MotionStaggerItem } from '@devalok/shilp-sutra/motion/primitives'`
736
+ - Spring presets (spatial: position, scale, size): snappy (buttons/hover), smooth (dialogs/panels), bouncy (toasts/pop-ins), gentle (collapse/expand)
737
+ - Tween presets (non-spatial: opacity, color): fade (opacity enter/exit), colorShift (hover color/bg)
738
+ - All primitives take `show: boolean` to control mount/unmount via AnimatePresence
739
+ - MotionSlide: additional `direction` prop (up|down|left|right)
740
+ - MotionStagger + MotionStaggerItem: orchestrated stagger with configurable `delay` (default 0.04s)
741
+ - All primitives support `layout`, `layoutId`, `whileInView`, `viewportOnce`, `preset` props
742
+ - useMotion() hook returns { springs, tweens, reducedMotion: boolean }
743
+ - Old Fade/Collapse/Grow/Slide from @devalok/shilp-sutra/ui/transitions are REMOVED — use Motion* equivalents
744
+
745
+ ### Hooks
746
+ - toast: imperative API — import { toast } from '@devalok/shilp-sutra/ui/toast'. **Signature is `(message: string, options?: { description?, duration?, action?, … })`** (sonner-style positional, NOT object-first). Examples: `toast.success('Saved')`, `toast.error('Failed to fetch', { description: 'Check your network', duration: 7000 })`, `toast.promise(fn, { loading: '…', success: '…', error: '…' })`, `toast.upload(file, { onProgress, onComplete })`. Methods: toast.success/error/warning/info/loading/message/undo/promise/upload/custom/dismiss. useToast() is deprecated. Mount `<Toaster />` at layout root or `toast()` calls are no-ops + log a dev warning.
747
+ - useColorMode(): returns { colorMode, setColorMode, toggleColorMode }
748
+ - useMobile(): returns boolean (true if viewport < 768px)
749
+ - useLink(): returns router-agnostic Link component from LinkProvider context (shell/link-context)
750
+
751
+ ## Server-Safe Components (no "use client")
752
+
753
+ These can be imported directly in Next.js Server Components:
754
+ - UI: Text, Skeleton, Stack, Container, Table (and sub-components), Code, VisuallyHidden
755
+ - Composed: ContentCard, PageHeader, LoadingSkeleton, PageSkeletons, PriorityIndicator
756
+
757
+ Use per-component imports for server components:
758
+ import { Text } from '@devalok/shilp-sutra/ui/text'
759
+ import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
760
+
761
+ DO NOT use barrel imports in Server Components — they include "use client" components.
762
+
763
+ ## Common Mistakes -- DO NOT
764
+
765
+ - DO NOT use variant="destructive" — use color="error"
766
+ - DO NOT use size="default" — use size="md" (or sm, lg)
767
+ - DO NOT put size on <Select> — put it on <SelectTrigger size="md">
768
+ - DO NOT use <Chip> — Chip is deprecated. Use <Badge onClick={...}> instead
769
+ - DO NOT use useToast() hook — use import { toast } from '@devalok/shilp-sutra/ui/toast' (imperative)
770
+ - DO NOT use toast({ title, color }) object syntax — use toast.success('message'), toast.error('message'), etc.
771
+ - DO NOT call toast() without <Toaster /> mounted at your layout root
772
+ - DO NOT use <Alert><AlertTitle>...</AlertTitle></Alert> — use <Alert title="..." />
773
+ - DO NOT import from barrel in Next.js Server Components — use per-component imports
774
+ - DO NOT use variant="secondary" on Button — use variant="outline" or variant="ghost"
775
+ - DO NOT use variant="default" on Button — use variant="solid" (deprecated alias, still works)
776
+ - DO NOT use variant="destructive" on Button — use variant="solid" color="error" (deprecated alias, still works)
777
+ - DO NOT use color="default" on Button — use color="accent" (deprecated alias, still works)
778
+ - DO NOT put variant on individual TabsTrigger — put it on TabsList (propagates via context)