@devalok/shilp-sutra 0.18.1 → 0.19.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 (101) hide show
  1. package/dist/shell/bottom-navbar.js +4 -4
  2. package/dist/shell/sidebar.js +2 -2
  3. package/dist/shell/top-bar.d.ts +45 -20
  4. package/dist/shell/top-bar.d.ts.map +1 -1
  5. package/dist/shell/top-bar.js +222 -159
  6. package/dist/tokens/semantic.css +5 -5
  7. package/dist/ui/sidebar.js +11 -11
  8. package/docs/components/_header.md +85 -0
  9. package/docs/components/composed/activity-feed.md +43 -0
  10. package/docs/components/composed/avatar-group.md +32 -0
  11. package/docs/components/composed/command-palette.md +40 -0
  12. package/docs/components/composed/confirm-dialog.md +46 -0
  13. package/docs/components/composed/content-card.md +36 -0
  14. package/docs/components/composed/date-picker.md +130 -0
  15. package/docs/components/composed/empty-state.md +53 -0
  16. package/docs/components/composed/error-boundary.md +29 -0
  17. package/docs/components/composed/global-loading.md +27 -0
  18. package/docs/components/composed/loading-skeleton.md +51 -0
  19. package/docs/components/composed/member-picker.md +35 -0
  20. package/docs/components/composed/page-header.md +41 -0
  21. package/docs/components/composed/page-skeletons.md +32 -0
  22. package/docs/components/composed/priority-indicator.md +32 -0
  23. package/docs/components/composed/rich-text-editor.md +71 -0
  24. package/docs/components/composed/schedule-view.md +39 -0
  25. package/docs/components/composed/simple-tooltip.md +33 -0
  26. package/docs/components/composed/status-badge.md +42 -0
  27. package/docs/components/shell/app-command-palette.md +44 -0
  28. package/docs/components/shell/bottom-navbar.md +52 -0
  29. package/docs/components/shell/command-registry.md +48 -0
  30. package/docs/components/shell/link-context.md +41 -0
  31. package/docs/components/shell/notification-center.md +63 -0
  32. package/docs/components/shell/notification-preferences.md +42 -0
  33. package/docs/components/shell/sidebar.md +92 -0
  34. package/docs/components/shell/top-bar.md +140 -0
  35. package/docs/components/ui/accordion.md +48 -0
  36. package/docs/components/ui/alert-dialog.md +58 -0
  37. package/docs/components/ui/alert.md +43 -0
  38. package/docs/components/ui/aspect-ratio.md +25 -0
  39. package/docs/components/ui/autocomplete.md +48 -0
  40. package/docs/components/ui/avatar.md +34 -0
  41. package/docs/components/ui/badge.md +48 -0
  42. package/docs/components/ui/banner.md +36 -0
  43. package/docs/components/ui/breadcrumb.md +37 -0
  44. package/docs/components/ui/button-group.md +32 -0
  45. package/docs/components/ui/button.md +55 -0
  46. package/docs/components/ui/card.md +48 -0
  47. package/docs/components/ui/charts.md +43 -0
  48. package/docs/components/ui/checkbox.md +31 -0
  49. package/docs/components/ui/chip.md +44 -0
  50. package/docs/components/ui/code.md +28 -0
  51. package/docs/components/ui/collapsible.md +40 -0
  52. package/docs/components/ui/color-input.md +37 -0
  53. package/docs/components/ui/combobox.md +54 -0
  54. package/docs/components/ui/container.md +26 -0
  55. package/docs/components/ui/context-menu.md +43 -0
  56. package/docs/components/ui/data-table-toolbar.md +44 -0
  57. package/docs/components/ui/data-table.md +91 -0
  58. package/docs/components/ui/dialog.md +51 -0
  59. package/docs/components/ui/dropdown-menu.md +45 -0
  60. package/docs/components/ui/file-upload.md +41 -0
  61. package/docs/components/ui/form.md +51 -0
  62. package/docs/components/ui/hover-card.md +32 -0
  63. package/docs/components/ui/icon-button.md +33 -0
  64. package/docs/components/ui/input-otp.md +44 -0
  65. package/docs/components/ui/input.md +48 -0
  66. package/docs/components/ui/label.md +25 -0
  67. package/docs/components/ui/link.md +29 -0
  68. package/docs/components/ui/menubar.md +44 -0
  69. package/docs/components/ui/navigation-menu.md +46 -0
  70. package/docs/components/ui/number-input.md +44 -0
  71. package/docs/components/ui/pagination.md +48 -0
  72. package/docs/components/ui/popover.md +30 -0
  73. package/docs/components/ui/progress.md +29 -0
  74. package/docs/components/ui/radio.md +34 -0
  75. package/docs/components/ui/search-input.md +43 -0
  76. package/docs/components/ui/segmented-control.md +50 -0
  77. package/docs/components/ui/select.md +49 -0
  78. package/docs/components/ui/separator.md +29 -0
  79. package/docs/components/ui/sheet.md +47 -0
  80. package/docs/components/ui/sidebar.md +72 -0
  81. package/docs/components/ui/skeleton.md +77 -0
  82. package/docs/components/ui/slider.md +29 -0
  83. package/docs/components/ui/spinner.md +51 -0
  84. package/docs/components/ui/stack.md +39 -0
  85. package/docs/components/ui/stat-card.md +61 -0
  86. package/docs/components/ui/stepper.md +49 -0
  87. package/docs/components/ui/switch.md +34 -0
  88. package/docs/components/ui/table.md +47 -0
  89. package/docs/components/ui/tabs.md +56 -0
  90. package/docs/components/ui/text.md +37 -0
  91. package/docs/components/ui/textarea.md +39 -0
  92. package/docs/components/ui/toast.md +65 -0
  93. package/docs/components/ui/toaster.md +47 -0
  94. package/docs/components/ui/toggle-group.md +43 -0
  95. package/docs/components/ui/toggle.md +37 -0
  96. package/docs/components/ui/tooltip.md +33 -0
  97. package/docs/components/ui/tree-view.md +65 -0
  98. package/docs/components/ui/visually-hidden.md +21 -0
  99. package/llms-full.txt +164 -73
  100. package/llms.txt +1 -1
  101. package/package.json +699 -697
@@ -98,7 +98,7 @@ const te = i(
98
98
  "div",
99
99
  {
100
100
  className: r(
101
- "flex h-full w-[--sidebar-width] flex-col bg-surface-1 text-surface-fg",
101
+ "flex h-full w-[--sidebar-width] flex-col bg-surface-2 text-surface-fg",
102
102
  d
103
103
  ),
104
104
  ref: u,
@@ -110,7 +110,7 @@ const te = i(
110
110
  {
111
111
  "data-sidebar": "sidebar",
112
112
  "data-mobile": "true",
113
- className: "w-[--sidebar-width] bg-surface-1 p-0 text-surface-fg [&>button]:hidden",
113
+ className: "w-[--sidebar-width] bg-surface-2 p-0 text-surface-fg [&>button]:hidden",
114
114
  style: {
115
115
  "--sidebar-width": Q
116
116
  },
@@ -152,7 +152,7 @@ const te = i(
152
152
  "div",
153
153
  {
154
154
  "data-sidebar": "sidebar",
155
- className: "flex h-full w-full flex-col bg-surface-1 group-data-[variant=floating]:rounded-ds-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-surface-border group-data-[variant=floating]:shadow",
155
+ className: "flex h-full w-full flex-col bg-surface-2 group-data-[variant=floating]:rounded-ds-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-surface-border group-data-[variant=floating]:shadow",
156
156
  children: o
157
157
  }
158
158
  )
@@ -202,7 +202,7 @@ const re = i(
202
202
  "hover:after:bg-surface-border-strong absolute inset-y-0 z-raised hidden w-4 -translate-x-1/2 transition-colors ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
203
203
  "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
204
204
  "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
205
- "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-surface-2",
205
+ "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-surface-3",
206
206
  "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
207
207
  "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
208
208
  a
@@ -234,7 +234,7 @@ const de = i(({ className: a, ...e }, t) => /* @__PURE__ */ s(
234
234
  ref: t,
235
235
  "data-sidebar": "input",
236
236
  className: r(
237
- "h-ds-sm w-full bg-surface-1 shadow-none focus-visible:ring-2 focus-visible:ring-accent-9",
237
+ "h-ds-sm w-full bg-surface-2 shadow-none focus-visible:ring-2 focus-visible:ring-accent-9",
238
238
  a
239
239
  ),
240
240
  ...e
@@ -325,7 +325,7 @@ const pe = i(({ className: a, asChild: e = !1, ...t }, d) => /* @__PURE__ */ s(
325
325
  ref: d,
326
326
  "data-sidebar": "group-action",
327
327
  className: r(
328
- "hover:bg-surface-2 absolute right-ds-04 top-ds-04 flex aspect-square w-5 items-center justify-center rounded-ds-md p-0 text-surface-fg outline-none ring-accent-9 transition-transform hover:text-surface-fg focus-visible:ring-2 [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
328
+ "hover:bg-surface-3 absolute right-ds-04 top-ds-04 flex aspect-square w-5 items-center justify-center rounded-ds-md p-0 text-surface-fg outline-none ring-accent-9 transition-transform hover:text-surface-fg focus-visible:ring-2 [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
329
329
  "after:absolute after:-inset-2 after:md:hidden",
330
330
  "group-data-[collapsible=icon]:hidden",
331
331
  a
@@ -371,12 +371,12 @@ const ge = i(
371
371
  );
372
372
  ge.displayName = "SidebarMenuItem";
373
373
  const he = T(
374
- "peer/menu-button hover:bg-surface-2 active:bg-accent-2 data-[active=true]:bg-accent-2 data-[state=open]:hover:bg-surface-2 flex w-full items-center gap-ds-03 overflow-hidden rounded-ds-md p-ds-03 text-left outline-none ring-accent-9 transition-[width,height,padding] hover:text-surface-fg focus-visible:ring-2 active:text-surface-fg disabled:pointer-events-none disabled:opacity-action-disabled group-has-[[data-sidebar=menu-action]]/menu-item:pr-ds-07 aria-disabled:pointer-events-none aria-disabled:opacity-action-disabled data-[active=true]:font-medium data-[active=true]:text-surface-fg data-[state=open]:hover:text-surface-fg group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-ds-03 [&>span:last-child]:truncate [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
374
+ "peer/menu-button hover:bg-surface-3 active:bg-accent-2 data-[active=true]:bg-accent-2 data-[state=open]:hover:bg-surface-3 flex w-full items-center gap-ds-03 overflow-hidden rounded-ds-md p-ds-03 text-left outline-none ring-accent-9 transition-[width,height,padding] hover:text-surface-fg focus-visible:ring-2 active:text-surface-fg disabled:pointer-events-none disabled:opacity-action-disabled group-has-[[data-sidebar=menu-action]]/menu-item:pr-ds-07 aria-disabled:pointer-events-none aria-disabled:opacity-action-disabled data-[active=true]:font-medium data-[active=true]:text-surface-fg data-[state=open]:hover:text-surface-fg group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-ds-03 [&>span:last-child]:truncate [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
375
375
  {
376
376
  variants: {
377
377
  variant: {
378
- default: "hover:bg-surface-2 hover:text-surface-fg",
379
- outline: "hover:bg-surface-2 bg-surface-1 shadow-[0_0_0_1px_var(--color-surface-border)] hover:text-surface-fg hover:shadow-[0_0_0_1px_var(--color-surface-border-strong)]"
378
+ default: "hover:bg-surface-3 hover:text-surface-fg",
379
+ outline: "hover:bg-surface-3 bg-surface-2 shadow-[0_0_0_1px_var(--color-surface-border)] hover:text-surface-fg hover:shadow-[0_0_0_1px_var(--color-surface-border-strong)]"
380
380
  },
381
381
  size: {
382
382
  md: "h-ds-sm text-ds-md",
@@ -445,7 +445,7 @@ const xe = i(({ className: a, asChild: e = !1, showOnHover: t = !1, ...d }, o) =
445
445
  ref: o,
446
446
  "data-sidebar": "menu-action",
447
447
  className: r(
448
- "hover:bg-surface-2 absolute right-ds-02 top-ds-02b flex aspect-square w-5 items-center justify-center rounded-ds-md p-0 text-surface-fg outline-none ring-accent-9 transition-transform hover:text-surface-fg focus-visible:ring-2 peer-hover/menu-button:text-surface-fg [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
448
+ "hover:bg-surface-3 absolute right-ds-02 top-ds-02b flex aspect-square w-5 items-center justify-center rounded-ds-md p-0 text-surface-fg outline-none ring-accent-9 transition-transform hover:text-surface-fg focus-visible:ring-2 peer-hover/menu-button:text-surface-fg [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0",
449
449
  "after:absolute after:-inset-2 after:md:hidden",
450
450
  "peer-data-[size=sm]/menu-button:top-1",
451
451
  "peer-data-[size=md]/menu-button:top-ds-02b",
@@ -538,7 +538,7 @@ const Me = i(({ asChild: a = !1, size: e = "md", isActive: t, className: d, ...o
538
538
  "data-size": e,
539
539
  "data-active": t,
540
540
  className: r(
541
- "hover:bg-surface-2 active:bg-accent-2 flex h-ds-xs-plus min-w-0 -translate-x-px items-center gap-ds-03 overflow-hidden rounded-ds-md px-ds-03 text-surface-fg outline-none ring-accent-9 hover:text-surface-fg focus-visible:ring-2 active:text-surface-fg disabled:pointer-events-none disabled:opacity-action-disabled aria-disabled:pointer-events-none aria-disabled:opacity-action-disabled [&>span:last-child]:truncate [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0 [&>svg]:text-surface-fg",
541
+ "hover:bg-surface-3 active:bg-accent-2 flex h-ds-xs-plus min-w-0 -translate-x-px items-center gap-ds-03 overflow-hidden rounded-ds-md px-ds-03 text-surface-fg outline-none ring-accent-9 hover:text-surface-fg focus-visible:ring-2 active:text-surface-fg disabled:pointer-events-none disabled:opacity-action-disabled aria-disabled:pointer-events-none aria-disabled:opacity-action-disabled [&>span:last-child]:truncate [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0 [&>svg]:text-surface-fg",
542
542
  "data-[active=true]:bg-accent-2 data-[active=true]:text-surface-fg",
543
543
  e === "sm" && "text-ds-sm",
544
544
  e === "md" && "text-ds-md",
@@ -0,0 +1,85 @@
1
+ # @devalok/shilp-sutra — Full Component Reference
2
+
3
+ > Exhaustive API reference for AI coding agents.
4
+ > For a concise cheatsheet, see llms.txt instead.
5
+ > All variant values and props verified from source CVA definitions.
6
+ >
7
+ > Package: @devalok/shilp-sutra
8
+ > Version: {{VERSION}}
9
+
10
+ ---
11
+
12
+ ## Architecture Notes
13
+
14
+ ### The Two-Axis Variant System
15
+
16
+ Many components use TWO props where shadcn/ui uses one:
17
+ - `variant` controls SHAPE/SURFACE: solid, outline, ghost, subtle, filled, etc.
18
+ - `color` controls INTENT/SEMANTICS: default, error, success, warning, info, etc.
19
+
20
+ Components with two-axis system: Button, Badge, Alert, Chip, Banner, Progress, StatusBadge
21
+
22
+ ### Server-Safe Components (no "use client")
23
+
24
+ These can be imported directly in Next.js Server Components:
25
+ - UI: Text, Skeleton, Stack, Container, Table (and sub-components), Code, VisuallyHidden
26
+ - Composed: ContentCard, PageHeader, LoadingSkeleton, PageSkeletons, PriorityIndicator
27
+ - NOTE (v0.18.0): Spinner, EmptyState, StatusBadge are NO LONGER server-safe (Framer Motion dependency)
28
+
29
+ Use per-component imports for server components:
30
+ import { Text } from '@devalok/shilp-sutra/ui/text'
31
+ import { PageHeader } from '@devalok/shilp-sutra/composed/page-header'
32
+
33
+ DO NOT use barrel imports in Server Components — they include "use client" components.
34
+
35
+ ### Token Architecture — OKLCH 12-Step System
36
+
37
+ Color tokens use OKLCH (perceptually uniform) with 12 functional steps per palette:
38
+
39
+ | Step | Purpose | Example usage |
40
+ |------|---------|---------------|
41
+ | 1 | App background | Page bg, body |
42
+ | 2 | Subtle background | Sidebar, card alt |
43
+ | 3 | Component bg | Input bg, badge bg |
44
+ | 4 | Component bg hover | Button hover state |
45
+ | 5 | Border subtle | Semantic `surface-border` in light mode |
46
+ | 6 | Border default | Semantic `surface-border-strong` in light mode |
47
+ | 7 | Border strong | Focus rings, emphasis borders |
48
+ | 8 | Border emphasis | High-contrast outlines |
49
+ | 9 | Solid / accent | Button bg, primary CTA |
50
+ | 10 | Solid hover | Button hover bg |
51
+ | 11 | Low-contrast text | Secondary accent text |
52
+ | 12 | High-contrast text | Headings on light bg |
53
+
54
+ Semantic layer:
55
+ - Accent (swappable): --color-accent-{1-12} + --color-accent-fg
56
+ - Secondary: --color-secondary-{1-12} + --color-secondary-fg
57
+ - Surface: --color-surface-{1-4} + --color-surface-fg / fg-muted / fg-subtle / border / border-strong
58
+ - Border mapping: light mode border=step5, border-strong=step6; dark mode border=step3, border-strong=step4
59
+ - Shell chrome (sidebar, topbar, bottom nav) uses surface-2 for elevation above surface-1 app background
60
+ - Status: --color-{error,success,warning,info}-{3,7,9,11}
61
+ - Category: --color-category-{teal,amber,slate,indigo,cyan,orange,emerald}
62
+
63
+ Consumer rebranding: Override accent scale CSS vars or use generateScale(options) utility.
64
+
65
+ Tailwind utilities: accent-1..12, secondary-1..12, surface-1..4, plus fg/border variants.
66
+
67
+ ### Toast Setup Pattern
68
+
69
+ 1. Mount <Toaster /> once at your root layout.
70
+ 2. Import { toast } from '@devalok/shilp-sutra/ui/toast' and call toast.success(), toast.error(), etc.
71
+ 3. Types: 'success' | 'error' | 'warning' | 'info' | 'loading' | 'message'
72
+
73
+ ### Form Accessibility Pattern
74
+
75
+ Use <FormField> + useFormField() hook:
76
+ <FormField state="error">
77
+ <Label htmlFor="email">Email</Label>
78
+ <Input id="email" state="error" />
79
+ <FormHelperText>Error message here.</FormHelperText>
80
+ </FormField>
81
+
82
+ useFormField() returns { state, helperTextId, required } from context.
83
+ Wire manually: <Input aria-describedby={helperTextId} aria-invalid={state === 'error'} />
84
+
85
+ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
@@ -0,0 +1,43 @@
1
+ # ActivityFeed
2
+
3
+ - Import: @devalok/shilp-sutra/composed/activity-feed
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ items: ActivityItem[] (REQUIRED) — { id, actor?: { name, image? }, action: string|ReactNode, timestamp: Date|string, icon?, color?: 'default'|'success'|'warning'|'error'|'info', detail?: ReactNode }
9
+ onLoadMore?: () => void — "Load more" button callback
10
+ loading: boolean — skeleton shimmer
11
+ hasMore?: boolean — shows "Load more" button
12
+ emptyState?: ReactNode — empty state content
13
+ compact: boolean — tighter spacing, no avatars, smaller text
14
+ maxInitialItems: number — truncate with "Show all (N)" toggle
15
+
16
+ ## Defaults
17
+ loading=false, compact=false, hasMore=false
18
+
19
+ ## Example
20
+ ```jsx
21
+ <ActivityFeed
22
+ items={[
23
+ { id: '1', actor: { name: 'Alice' }, action: 'completed task', timestamp: new Date(), color: 'success' },
24
+ { id: '2', action: 'System backup completed', timestamp: new Date(), detail: <pre>Details...</pre> },
25
+ ]}
26
+ hasMore
27
+ onLoadMore={() => fetchMore()}
28
+ compact
29
+ />
30
+ ```
31
+
32
+ ## Gotchas
33
+ - `items` is required — passing an empty array renders the `emptyState` content
34
+ - `color` on each item controls the timeline dot color
35
+ - `actor.image` is optional — falls back to initials from `actor.name`
36
+ - `maxInitialItems` truncates with a "Show all (N)" toggle button
37
+
38
+ ## Changes
39
+ ### v0.18.0
40
+ - **Fixed** `bg-accent-9` changed to `bg-info-9` (info color, not accent)
41
+
42
+ ### v0.16.0
43
+ - **Added** Initial release — vertical timeline with colored dots, actor avatars, expandable detail, compact mode, load more, maxInitialItems truncation
@@ -0,0 +1,32 @@
1
+ # AvatarGroup
2
+
3
+ - Import: @devalok/shilp-sutra/composed/avatar-group
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ users: AvatarUser[] (REQUIRED) — { name: string, image?: string | null }
9
+ max: number (default: 4, overflow shows "+N" badge)
10
+ size: "sm" | "md" | "lg"
11
+ showTooltip: boolean (default: true)
12
+
13
+ ## Defaults
14
+ size="md", max=4, showTooltip=true
15
+
16
+ ## Example
17
+ ```jsx
18
+ <AvatarGroup
19
+ users={[{ name: 'Alice', image: '/alice.jpg' }, { name: 'Bob' }]}
20
+ max={3}
21
+ size="md"
22
+ />
23
+ ```
24
+
25
+ ## Gotchas
26
+ - Wraps TooltipProvider internally — no need to add one yourself
27
+ - Users beyond `max` are collapsed into a "+N" overflow badge
28
+ - Missing `image` falls back to initials derived from `name`
29
+
30
+ ## Changes
31
+ ### v0.1.0
32
+ - **Added** Initial release
@@ -0,0 +1,40 @@
1
+ # CommandPalette
2
+
3
+ - Import: @devalok/shilp-sutra/composed/command-palette
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ groups?: CommandGroup[] (default: []) — { label: string, items: CommandItem[] }
9
+ placeholder: string (default: "Search or jump to...")
10
+ onSearch: (query: string) => void
11
+ emptyMessage: string (default: "No results found.")
12
+
13
+ CommandItem shape: { id, label, description?, icon?, shortcut?, onSelect: () => void }
14
+
15
+ ## Defaults
16
+ placeholder="Search or jump to...", emptyMessage="No results found.", groups=[]
17
+
18
+ ## Example
19
+ ```jsx
20
+ <CommandPalette
21
+ groups={[{
22
+ label: 'Navigation',
23
+ items: [{ id: 'dash', label: 'Dashboard', onSelect: () => navigate('/') }],
24
+ }]}
25
+ />
26
+ ```
27
+
28
+ ## Gotchas
29
+ - Opens with Ctrl+K / Cmd+K by default
30
+ - Items animate in with staggered slide-up (30ms delay cascade); groups fade in; active item icon/shortcut highlight in interactive color (v0.15.0)
31
+
32
+ ## Changes
33
+ ### v0.15.0
34
+ - **Added** Staggered slide-up entrance animations for items, fade-in for groups/empty state/footer, scale-in for search icon, active item icon/shortcut color transitions
35
+
36
+ ### v0.8.0
37
+ - **Added** Full ARIA combobox pattern (`role="combobox"`, `aria-expanded`, `aria-activedescendant`)
38
+
39
+ ### v0.1.0
40
+ - **Added** Initial release
@@ -0,0 +1,46 @@
1
+ # ConfirmDialog
2
+
3
+ - Import: @devalok/shilp-sutra/composed/confirm-dialog
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ open: boolean (REQUIRED, controlled)
9
+ onOpenChange: (open: boolean) => void (REQUIRED)
10
+ title: string (REQUIRED)
11
+ description: string (REQUIRED)
12
+ confirmText: string (default: "Confirm")
13
+ cancelText: string (default: "Cancel")
14
+ color: "default" | "error" (controls confirm button color)
15
+ loading: boolean (default: false, disables buttons and replaces confirm button text with 'Processing...')
16
+ onConfirm: () => void | Promise<void> (REQUIRED)
17
+
18
+ ## Defaults
19
+ confirmText="Confirm", cancelText="Cancel", color="default", loading=false
20
+
21
+ ## Example
22
+ ```jsx
23
+ const [open, setOpen] = useState(false)
24
+ <ConfirmDialog
25
+ open={open}
26
+ onOpenChange={setOpen}
27
+ title="Delete project?"
28
+ description="This action cannot be undone."
29
+ color="error"
30
+ confirmText="Delete"
31
+ loading={isDeleting}
32
+ onConfirm={async () => { await deleteProject(); setOpen(false) }}
33
+ />
34
+ ```
35
+
36
+ ## Gotchas
37
+ - Dialog stays open after confirm — consumer must close it via `onOpenChange`
38
+ - Built on AlertDialog internally
39
+ - Fully controlled — `open` and `onOpenChange` are required
40
+
41
+ ## Changes
42
+ ### v0.18.0
43
+ - **Fixed** Converted to `forwardRef` pattern
44
+
45
+ ### v0.1.0
46
+ - **Added** Initial release
@@ -0,0 +1,36 @@
1
+ # ContentCard
2
+
3
+ - Import: @devalok/shilp-sutra/composed/content-card
4
+ - Server-safe: Yes
5
+ - Category: composed
6
+
7
+ ## Props
8
+ variant: "default" | "outline" | "ghost"
9
+ padding: "default" | "compact" | "spacious" | "none"
10
+ header: ReactNode (custom header content)
11
+ headerTitle: string (simple text header)
12
+ headerActions: ReactNode (actions in header area)
13
+ footer: ReactNode
14
+ children: ReactNode (body)
15
+
16
+ ## Defaults
17
+ variant="default", padding="default"
18
+
19
+ ## Example
20
+ ```jsx
21
+ <ContentCard headerTitle="Team Members" headerActions={<Button size="sm">Add</Button>}>
22
+ <p>Member list here</p>
23
+ </ContentCard>
24
+ ```
25
+
26
+ ## Gotchas
27
+ - Server-safe: can be imported directly in Next.js Server Components
28
+ - Use `headerTitle` for simple text headers; use `header` for custom header content
29
+ - `header` takes precedence over `headerTitle` if both are provided
30
+
31
+ ## Changes
32
+ ### v0.2.0
33
+ - **Added** Identified as server-safe component
34
+
35
+ ### v0.1.0
36
+ - **Added** Initial release
@@ -0,0 +1,130 @@
1
+ # DatePicker
2
+
3
+ - Import: @devalok/shilp-sutra/composed/date-picker
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+
9
+ ### DatePicker
10
+ value?: Date | null
11
+ onChange?: (date: Date | null) => void
12
+ placeholder: string (default: "Pick a date")
13
+ formatStr: string (default: "MMM d, yyyy")
14
+ minDate: Date
15
+ maxDate: Date
16
+ disabledDates: (date: Date) => boolean
17
+ className: string
18
+
19
+ ### DateRangePicker
20
+ startDate?: Date | null
21
+ endDate?: Date | null
22
+ onChange?: (range: { start: Date | null, end: Date | null }) => void
23
+ placeholder: string (default: "Pick a date range")
24
+ formatStr: string (default: "MMM d, yyyy")
25
+ minDate: Date
26
+ maxDate: Date
27
+ disabledDates: (date: Date) => boolean
28
+ presets: PresetKey[] (shows quick-select sidebar)
29
+ numberOfMonths: number (default: 1)
30
+
31
+ ### DateTimePicker
32
+ value: Date | null
33
+ onChange: (date: Date | null) => void
34
+ minDate: Date
35
+ maxDate: Date
36
+ disabledDates: (date: Date) => boolean
37
+ timeFormat: "12h" | "24h"
38
+ minuteStep: number
39
+ placeholder: string
40
+ className: string
41
+
42
+ ### TimePicker
43
+ value?: Date | null (time stored as a Date object)
44
+ onChange?: (date: Date) => void
45
+ format: "12h" | "24h" (default: "12h")
46
+ minuteStep: number (default: 1)
47
+ secondStep: number (default: 1)
48
+ showSeconds: boolean (default: false)
49
+ placeholder: string (default: "Pick a time")
50
+ disabled: boolean (default: false)
51
+ className: string
52
+
53
+ ### CalendarGrid
54
+ currentMonth: Date (REQUIRED)
55
+ selected?: Date | null
56
+ rangeStart?: Date | null
57
+ rangeEnd?: Date | null
58
+ hoverDate?: Date | null
59
+ onSelect: (date: Date) => void (REQUIRED)
60
+ onHover?: (date: Date | null) => void
61
+ onMonthChange: (date: Date) => void (REQUIRED)
62
+ onHeaderClick?: () => void
63
+ disabledDates: (date: Date) => boolean
64
+ minDate: Date
65
+ maxDate: Date
66
+ hidePrevNav: boolean
67
+ hideNextNav: boolean
68
+ events: CalendarEvent[] — { date: Date, color?: string, label?: string }
69
+
70
+ ### YearPicker
71
+ currentYear: number (REQUIRED)
72
+ selectedYear: number
73
+ onYearSelect: (year: number) => void (REQUIRED)
74
+ minDate: Date
75
+ maxDate: Date
76
+
77
+ ### MonthPicker
78
+ currentYear: number (REQUIRED)
79
+ selectedMonth: number (0-11)
80
+ onMonthSelect: (month: number) => void (REQUIRED)
81
+ minDate: Date
82
+ maxDate: Date
83
+
84
+ ### Presets
85
+ presets: PresetKey[] (REQUIRED)
86
+ onSelect: (start: Date, end: Date) => void (REQUIRED)
87
+ className: string
88
+
89
+ PresetKey: 'today' | 'yesterday' | 'last7days' | 'last30days' | 'thisMonth' | 'lastMonth' | 'thisYear'
90
+
91
+ ### useCalendar hook
92
+ useCalendar(initialMonth?: Date) => { currentMonth, setCurrentMonth, goToPreviousMonth, goToNextMonth, goToMonth, goToYear }
93
+
94
+ ## Defaults
95
+ DatePicker: placeholder="Pick a date", formatStr="MMM d, yyyy"
96
+ DateRangePicker: placeholder="Pick a date range", formatStr="MMM d, yyyy", numberOfMonths=1
97
+ TimePicker: format="12h", minuteStep=1, secondStep=1, showSeconds=false
98
+
99
+ ## Example
100
+ ```jsx
101
+ <DatePicker value={date} onChange={setDate} placeholder="Select date" />
102
+
103
+ <DateRangePicker
104
+ startDate={start}
105
+ endDate={end}
106
+ onChange={({ start, end }) => { setStart(start); setEnd(end); }}
107
+ />
108
+
109
+ <DateTimePicker value={dateTime} onChange={setDateTime} timeFormat="12h" minuteStep={15} />
110
+
111
+ <TimePicker value={time} onChange={setTime} format="24h" minuteStep={15} />
112
+ ```
113
+
114
+ ## Gotchas
115
+ - TimePicker stores time inside a Date object — only hours/minutes/seconds are meaningful
116
+ - CalendarGrid is a low-level building block — prefer DatePicker/DateRangePicker for most use cases
117
+ - MonthPicker month values are 0-indexed (Jan=0, Dec=11) — same as JavaScript `Date.getMonth()`
118
+ - YearPicker displays a 12-year grid based on the decade of `currentYear`
119
+ - CalendarGrid supports up to 3 event dots per day cell
120
+ - useCalendar is a convenience hook for managing calendar month state
121
+
122
+ ## Changes
123
+ ### v0.18.0
124
+ - **Fixed** Added `aria-label` to DatePicker/DateRangePicker trigger buttons
125
+
126
+ ### v0.4.2
127
+ - **Changed** DateRangePicker default `formatStr` from `'MMM d'` to `'MMM d, yyyy'`
128
+
129
+ ### v0.1.0
130
+ - **Added** Initial release
@@ -0,0 +1,53 @@
1
+ # EmptyState
2
+
3
+ - Import: @devalok/shilp-sutra/composed/empty-state
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ Note: EmptyState was server-safe prior to v0.18.0 but is NO LONGER server-safe due to Framer Motion dependency.
8
+
9
+ ## Props
10
+ title: string (REQUIRED)
11
+ description: string
12
+ icon: ReactNode | ComponentType<{ className?: string }> (default: Devalok chakra icon)
13
+ action: ReactNode (e.g. a Button)
14
+ compact: boolean (smaller layout)
15
+ iconSize: 'sm' | 'md' | 'lg' (default 'md', compact defaults to 'sm') — sm=h-ico-sm, md=h-ico-lg, lg=h-ico-xl
16
+
17
+ ## Defaults
18
+ iconSize="md" (compact defaults to "sm")
19
+
20
+ ## Example
21
+ ```jsx
22
+ <EmptyState
23
+ title="No tasks found"
24
+ description="Create your first task to get started."
25
+ action={<Button>Create Task</Button>}
26
+ iconSize="lg"
27
+ />
28
+ ```
29
+
30
+ ## Gotchas
31
+ - `icon` accepts both JSX elements (`<IconFolder />`) and component references (`IconFolder`). Component references are auto-instantiated with correct sizing classes.
32
+ - `iconSize` controls icon dimensions regardless of icon type. When `compact=true` and no `iconSize`, defaults to `'sm'`.
33
+ - As of v0.18.0, EmptyState is NOT server-safe (Framer Motion dependency). Use per-component import in client components.
34
+
35
+ ## Changes
36
+ ### v0.18.0
37
+ - **Changed** No longer server-safe due to Framer Motion dependency
38
+
39
+ ### v0.16.0
40
+ - **Added** `iconSize?: 'sm' | 'md' | 'lg'` — control icon dimensions
41
+
42
+ ### v0.13.0
43
+ - **Changed** `icon` prop now accepts `React.ComponentType<{ className?: string }>` in addition to `ReactNode` — component references are auto-instantiated
44
+
45
+ ### v0.5.0
46
+ - **Changed** `icon` prop changed from `TablerIcon` (component ref) to `React.ReactNode` — use `icon={<MyIcon />}` instead of `icon={MyIcon}`
47
+ - **Changed** Default icon is now the Devalok swadhisthana chakra (inline SVG)
48
+
49
+ ### v0.2.0
50
+ - **Added** Identified as server-safe component (later reverted in v0.18.0)
51
+
52
+ ### v0.1.0
53
+ - **Added** Initial release
@@ -0,0 +1,29 @@
1
+ # ErrorDisplay
2
+
3
+ - Import: @devalok/shilp-sutra/composed/error-boundary
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ error: unknown (REQUIRED — Error object, status object, or string)
9
+ onReset: () => void (optional retry button)
10
+
11
+ ## Defaults
12
+ None
13
+
14
+ ## Example
15
+ ```jsx
16
+ <ErrorDisplay error={error} onReset={() => refetch()} />
17
+ ```
18
+
19
+ ## Gotchas
20
+ - Auto-detects HTTP status codes (404, 403, 500) and shows appropriate icon/message
21
+ - Shows stack trace in development mode only
22
+ - The import path is `error-boundary` but the component is named `ErrorDisplay`
23
+
24
+ ## Changes
25
+ ### v0.18.0
26
+ - **Added** ErrorBoundary tests (13 new tests)
27
+
28
+ ### v0.1.0
29
+ - **Added** Initial release
@@ -0,0 +1,27 @@
1
+ # GlobalLoading
2
+
3
+ - Import: @devalok/shilp-sutra/composed/global-loading
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+ isLoading: boolean (REQUIRED)
9
+
10
+ ## Defaults
11
+ None
12
+
13
+ ## Example
14
+ ```jsx
15
+ <GlobalLoading isLoading={isNavigating} />
16
+ ```
17
+
18
+ ## Gotchas
19
+ - Fixed-position bar at top of viewport (z-toast layer)
20
+ - Renders nothing when `isLoading` is false
21
+
22
+ ## Changes
23
+ ### v0.18.0
24
+ - **Fixed** Track `setTimeout` with ref, add cleanup on unmount
25
+
26
+ ### v0.1.0
27
+ - **Added** Initial release
@@ -0,0 +1,51 @@
1
+ # LoadingSkeleton
2
+
3
+ - Import: @devalok/shilp-sutra/composed/loading-skeleton
4
+ - Server-safe: Yes
5
+ - Category: composed
6
+
7
+ Exports: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton
8
+
9
+ ## Props
10
+
11
+ ### CardSkeleton
12
+ className: string
13
+
14
+ ### TableSkeleton
15
+ rows: number (default: 5)
16
+ columns: number (default: 4)
17
+ className: string
18
+
19
+ ### BoardSkeleton
20
+ columns: number (default: 4)
21
+ cardsPerColumn: number (default: 3)
22
+ className: string
23
+
24
+ ### ListSkeleton
25
+ rows: number (default: 6)
26
+ showAvatar: boolean (default: true)
27
+ className: string
28
+
29
+ ## Defaults
30
+ TableSkeleton: rows=5, columns=4
31
+ BoardSkeleton: columns=4, cardsPerColumn=3
32
+ ListSkeleton: rows=6, showAvatar=true
33
+
34
+ ## Example
35
+ ```jsx
36
+ <CardSkeleton />
37
+ <TableSkeleton rows={8} columns={5} />
38
+ <BoardSkeleton columns={3} cardsPerColumn={4} />
39
+ <ListSkeleton rows={10} showAvatar={false} />
40
+ ```
41
+
42
+ ## Gotchas
43
+ - Server-safe: can be imported directly in Next.js Server Components
44
+ - These are pre-composed skeleton layouts — for individual skeleton shapes, use the `Skeleton` UI component
45
+
46
+ ## Changes
47
+ ### v0.2.0
48
+ - **Added** Identified as server-safe component
49
+
50
+ ### v0.1.0
51
+ - **Added** Initial release