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