@devalok/shilp-sutra 0.37.0 → 0.38.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.
- package/MIGRATION.md +67 -0
- package/dist/_chunks/tiptap.js +977 -968
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/composed/index.d.ts +0 -2
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/index.js +5 -6
- package/dist/composed/inline-edit.d.ts.map +1 -1
- package/dist/composed/inline-edit.js +42 -40
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/test-utils/conformance.d.ts +37 -0
- package/dist/test-utils/conformance.d.ts.map +1 -0
- package/dist/ui/alert.d.ts +1 -2
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +1 -27
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/banner.d.ts +3 -5
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +13 -13
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.d.ts +1 -9
- package/dist/ui/input.d.ts.map +1 -1
- package/dist/ui/input.js +26 -27
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/segmented-control.d.ts +1 -1
- package/dist/ui/segmented-control.d.ts.map +1 -1
- package/dist/ui/segmented-control.js +2 -4
- package/dist/ui/segmented-control.js.map +1 -1
- package/docs/components/_header.md +1 -1
- package/docs/components/composed/activity-feed.md +6 -0
- package/docs/components/composed/avatar-group.md +8 -0
- package/docs/components/composed/bulk-action-bar.md +6 -0
- package/docs/components/composed/command-palette.md +7 -0
- package/docs/components/composed/confirm-dialog.md +6 -0
- package/docs/components/composed/content-card.md +6 -0
- package/docs/components/composed/date-picker.md +10 -0
- package/docs/components/composed/deadline-indicator.md +7 -0
- package/docs/components/composed/emoji-picker.md +8 -0
- package/docs/components/composed/empty-state.md +8 -0
- package/docs/components/composed/error-boundary.md +7 -0
- package/docs/components/composed/file-preview.md +8 -0
- package/docs/components/composed/filter-bar.md +8 -0
- package/docs/components/composed/form-section.md +6 -0
- package/docs/components/composed/global-loading.md +6 -0
- package/docs/components/composed/inline-edit.md +8 -0
- package/docs/components/composed/loading-skeleton.md +7 -0
- package/docs/components/composed/markdown-viewer.md +9 -0
- package/docs/components/composed/master-detail.md +7 -0
- package/docs/components/composed/member-picker.md +7 -0
- package/docs/components/composed/multi-select-popover.md +11 -0
- package/docs/components/composed/page-header.md +7 -0
- package/docs/components/composed/page-skeletons.md +10 -0
- package/docs/components/composed/priority-indicator.md +7 -0
- package/docs/components/composed/rich-chat-input.md +12 -0
- package/docs/components/composed/rich-text-editor.md +9 -0
- package/docs/components/composed/schedule-view.md +8 -0
- package/docs/components/composed/simple-tooltip.md +7 -0
- package/docs/components/composed/status-badge.md +10 -0
- package/docs/components/shell/app-command-palette.md +8 -0
- package/docs/components/shell/bottom-navbar.md +12 -0
- package/docs/components/shell/command-registry.md +7 -0
- package/docs/components/shell/link-context.md +15 -0
- package/docs/components/shell/notification-center.md +10 -0
- package/docs/components/shell/notification-preferences.md +7 -0
- package/docs/components/shell/sidebar.md +11 -0
- package/docs/components/shell/top-bar.md +11 -0
- package/docs/components/ui/accordion.md +10 -0
- package/docs/components/ui/alert-dialog.md +10 -1
- package/docs/components/ui/alert.md +13 -2
- package/docs/components/ui/aspect-ratio.md +7 -0
- package/docs/components/ui/autocomplete.md +7 -0
- package/docs/components/ui/avatar.md +10 -0
- package/docs/components/ui/badge-group.md +7 -0
- package/docs/components/ui/badge-indicator.md +7 -0
- package/docs/components/ui/badge.md +12 -0
- package/docs/components/ui/banner.md +10 -1
- package/docs/components/ui/breadcrumb.md +8 -0
- package/docs/components/ui/button-group.md +24 -4
- package/docs/components/ui/button-processing.md +5 -0
- package/docs/components/ui/button.md +9 -0
- package/docs/components/ui/card.md +16 -4
- package/docs/components/ui/charts.md +9 -0
- package/docs/components/ui/chat.md +9 -0
- package/docs/components/ui/checkbox.md +15 -1
- package/docs/components/ui/chip.md +9 -0
- package/docs/components/ui/code.md +7 -0
- package/docs/components/ui/collapsible.md +9 -0
- package/docs/components/ui/color-input.md +8 -0
- package/docs/components/ui/color-swatch.md +7 -0
- package/docs/components/ui/combobox.md +16 -3
- package/docs/components/ui/container.md +11 -0
- package/docs/components/ui/context-menu.md +8 -0
- package/docs/components/ui/data-table-body.md +4 -0
- package/docs/components/ui/data-table-bulk-actions.md +4 -0
- package/docs/components/ui/data-table-card.md +4 -0
- package/docs/components/ui/data-table-context.md +4 -0
- package/docs/components/ui/data-table-header.md +4 -0
- package/docs/components/ui/data-table-pagination.md +4 -0
- package/docs/components/ui/data-table-toolbar.md +7 -0
- package/docs/components/ui/data-table.md +25 -0
- package/docs/components/ui/devalok-grain.md +8 -0
- package/docs/components/ui/dialog.md +10 -0
- package/docs/components/ui/dropdown-menu.md +10 -0
- package/docs/components/ui/file-upload.md +8 -0
- package/docs/components/ui/form.md +21 -0
- package/docs/components/ui/hover-card.md +9 -0
- package/docs/components/ui/icon-button.md +7 -0
- package/docs/components/ui/icon-context.md +7 -0
- package/docs/components/ui/icon-group.md +9 -0
- package/docs/components/ui/icon.md +7 -0
- package/docs/components/ui/input-otp.md +29 -7
- package/docs/components/ui/input.md +11 -2
- package/docs/components/ui/label.md +7 -1
- package/docs/components/ui/link.md +7 -0
- package/docs/components/ui/menubar.md +9 -0
- package/docs/components/ui/navigation-menu.md +9 -0
- package/docs/components/ui/number-input.md +10 -0
- package/docs/components/ui/pagination.md +10 -0
- package/docs/components/ui/popover.md +9 -0
- package/docs/components/ui/progress-ring.md +7 -0
- package/docs/components/ui/progress.md +7 -0
- package/docs/components/ui/radio.md +27 -2
- package/docs/components/ui/search-input.md +8 -0
- package/docs/components/ui/segmented-control.md +21 -6
- package/docs/components/ui/select.md +14 -3
- package/docs/components/ui/separator.md +7 -0
- package/docs/components/ui/sheet.md +10 -0
- package/docs/components/ui/sidebar.md +30 -0
- package/docs/components/ui/skeleton.md +7 -0
- package/docs/components/ui/slider.md +15 -1
- package/docs/components/ui/spinner.md +7 -0
- package/docs/components/ui/split-button.md +11 -0
- package/docs/components/ui/stack.md +8 -0
- package/docs/components/ui/stat-card.md +9 -0
- package/docs/components/ui/status-dot.md +9 -0
- package/docs/components/ui/stepper.md +8 -0
- package/docs/components/ui/switch.md +8 -0
- package/docs/components/ui/table.md +8 -0
- package/docs/components/ui/tabs.md +10 -2
- package/docs/components/ui/text.md +9 -4
- package/docs/components/ui/textarea.md +7 -1
- package/docs/components/ui/toast.md +9 -0
- package/docs/components/ui/toaster.md +8 -0
- package/docs/components/ui/toggle-group.md +13 -4
- package/docs/components/ui/toggle.md +10 -2
- package/docs/components/ui/tooltip.md +11 -1
- package/docs/components/ui/tree-view.md +12 -0
- package/docs/components/ui/visually-hidden.md +7 -0
- package/docs/recipes/customize-brand.md +216 -0
- package/docs/recipes/index.md +51 -0
- package/docs/recipes/install-astro.md +178 -0
- package/docs/recipes/install-next-app-router.md +230 -0
- package/docs/recipes/install-next-pages.md +123 -0
- package/docs/recipes/install-remix.md +171 -0
- package/docs/recipes/install-tanstack-start.md +143 -0
- package/docs/recipes/install-vite.md +170 -0
- package/docs/recipes/server-components.md +209 -0
- package/docs/recipes/troubleshoot.md +217 -0
- package/llms-full.txt +1133 -88
- package/llms.txt +33 -16
- package/package.json +45 -35
- package/dist/composed/responsive-overlay.d.ts +0 -23
- package/dist/composed/responsive-overlay.d.ts.map +0 -1
- package/dist/composed/responsive-overlay.js +0 -40
- package/dist/composed/responsive-overlay.js.map +0 -1
- package/dist/hooks/use-toast.d.ts +0 -17
- package/dist/hooks/use-toast.d.ts.map +0 -1
- package/dist/hooks/use-toast.js +0 -3
- package/dist/tailwind/index.cjs +0 -41
- package/dist/tailwind/index.d.ts +0 -2
- package/dist/tailwind/index.d.ts.map +0 -1
- package/dist/tailwind/index.js +0 -2
- package/dist/tailwind/preset.d.ts +0 -25
- package/dist/tailwind/preset.d.ts.map +0 -1
- package/dist/tailwind/preset.js +0 -17
- package/dist/tailwind/preset.js.map +0 -1
- package/docs/components/composed/responsive-overlay.md +0 -34
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
## Props
|
|
8
8
|
color: "info" | "success" | "warning" | "error" | "neutral"
|
|
9
9
|
actions: ReactNode (optional action slot for one or more buttons; wraps on narrow viewports)
|
|
10
|
-
action: ReactNode (DEPRECATED — use `actions` instead)
|
|
11
10
|
onDismiss: () => void (optional, shows X button)
|
|
12
11
|
children: ReactNode (message text)
|
|
13
12
|
|
|
@@ -21,12 +20,22 @@
|
|
|
21
20
|
</Banner>
|
|
22
21
|
```
|
|
23
22
|
|
|
23
|
+
## Composability
|
|
24
|
+
- **Banner vs Alert vs Toast:** Banner is full-width, top-of-page / top-of-region announcements (maintenance, quota, trial-expiring). Alert is inline in-flow. Toast is transient floating notifications. Pick by where the message lives in the visual hierarchy.
|
|
25
|
+
- **actions slot:** Pass one or more `<Button>` elements — the container flex-wraps on narrow viewports so actions drop below the message rather than squeezing horizontally.
|
|
26
|
+
- **Role=alert** announces assertively. Same constraint as Alert — don't stack multiple Banners.
|
|
27
|
+
- **Dismissal timing:** `onDismiss` fires AFTER the exit animation completes, not on click. Use it to remove the banner from state only after it's visually gone.
|
|
28
|
+
- Works inside Shell layouts (TopBar / Sidebar / main content) — usually sits above main content, below the TopBar.
|
|
29
|
+
|
|
24
30
|
## Gotchas
|
|
25
31
|
- Banner is full-width (spans container). Alert is inline.
|
|
26
32
|
- Renders role="alert" automatically
|
|
27
33
|
- `onDismiss` fires after the exit animation completes, not immediately on dismiss button click
|
|
28
34
|
|
|
29
35
|
## Changes
|
|
36
|
+
### v0.38.0
|
|
37
|
+
- **Removed** (BREAKING) deprecated singular `action` prop. Use `actions={[...]}` (plural).
|
|
38
|
+
|
|
30
39
|
### v0.20.0
|
|
31
40
|
- **Added** `actions` prop (plural) for multiple action buttons with mobile-friendly flex-wrap
|
|
32
41
|
- **Deprecated** `action` prop — use `actions` instead (both still work; `actions` takes priority)
|
|
@@ -26,8 +26,16 @@
|
|
|
26
26
|
</Breadcrumb>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## Composability
|
|
30
|
+
- **Compound structure only** — no context cascade, each part is standalone. The semantic shape (`<nav>` → `<ol>` → `<li>`) is what matters for a11y, not any internal state.
|
|
31
|
+
- **BreadcrumbLink vs BreadcrumbPage:** Use BreadcrumbLink for everything except the current page; BreadcrumbPage for the current page (not clickable, renders without href, announced as "current page" via aria-current).
|
|
32
|
+
- **Router integration:** Use `<BreadcrumbLink asChild><NextLink href="/x">...</NextLink></BreadcrumbLink>` (Radix Slot pattern).
|
|
33
|
+
- **Truncation:** For long paths, use BreadcrumbEllipsis between the first and last items instead of showing all. Pair with a DropdownMenu (open the ellipsis to show hidden intermediate items) if you need to expose them.
|
|
34
|
+
- **PageHeader (composed) auto-builds Breadcrumb** from its `breadcrumbs` prop — use that higher-level component for page-top breadcrumbs and save this component for inline or custom positioning.
|
|
35
|
+
|
|
29
36
|
## Gotchas
|
|
30
37
|
- Use BreadcrumbPage for the current (non-clickable) page, BreadcrumbLink for navigable items
|
|
38
|
+
- Don't wrap BreadcrumbPage in a link — it's the current location by definition
|
|
31
39
|
|
|
32
40
|
## Changes
|
|
33
41
|
### v0.18.0
|
|
@@ -5,24 +5,44 @@
|
|
|
5
5
|
- Category: ui
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
|
-
variant: ButtonProps['variant'] (propagated to children)
|
|
8
|
+
variant: ButtonProps['variant'] (propagated to children via context)
|
|
9
9
|
color: ButtonProps['color'] (propagated to children)
|
|
10
10
|
size: ButtonProps['size'] (propagated to children)
|
|
11
|
-
|
|
11
|
+
weight: ButtonProps['weight'] (propagated to children)
|
|
12
|
+
shape: ButtonProps['shape'] (propagated to children)
|
|
13
|
+
disabled: boolean (propagates to all children)
|
|
14
|
+
orientation: "horizontal" | "vertical"
|
|
15
|
+
attached: boolean (true = buttons visually merge with shared borders; false = spaced apart via gap)
|
|
16
|
+
fullWidth: boolean (group stretches to parent width; children stretch equally)
|
|
12
17
|
|
|
13
18
|
## Defaults
|
|
14
|
-
orientation="horizontal"
|
|
19
|
+
orientation="horizontal", attached=true
|
|
15
20
|
|
|
16
21
|
## Example
|
|
17
22
|
```jsx
|
|
18
23
|
<ButtonGroup variant="outline" size="sm">
|
|
19
24
|
<Button>Bold</Button>
|
|
20
25
|
<Button>Italic</Button>
|
|
26
|
+
<Button>Underline</Button>
|
|
27
|
+
</ButtonGroup>
|
|
28
|
+
|
|
29
|
+
{/* Spaced, not attached */}
|
|
30
|
+
<ButtonGroup attached={false} variant="soft">
|
|
31
|
+
<Button>Save</Button>
|
|
32
|
+
<Button>Cancel</Button>
|
|
21
33
|
</ButtonGroup>
|
|
22
34
|
```
|
|
23
35
|
|
|
36
|
+
## Composability
|
|
37
|
+
- Every Button child reads variant/color/size/weight/shape/disabled from ButtonGroup context. Explicit props on individual children override context.
|
|
38
|
+
- **Position-aware border radius:** Child Buttons read their position in the group (first / middle / last) and apply appropriate corner radii inline. Works for both horizontal and vertical orientations.
|
|
39
|
+
- **Focus z-index isolation:** The focused button rises above its siblings so the focus ring isn't clipped by adjacent borders.
|
|
40
|
+
- **Tonal dividers:** For solid/soft/ghost variants without visible borders, ButtonGroup injects subtle divider elements between children.
|
|
41
|
+
- **Works with SplitButton:** `<SplitButton>` inside a `<ButtonGroup>` inherits the same context and position rules.
|
|
42
|
+
|
|
24
43
|
## Gotchas
|
|
25
|
-
- Children can override variant/size individually
|
|
44
|
+
- Children can override variant/size individually — context is a default, not a lock
|
|
45
|
+
- `attached={false}` disables the position-aware border radius (children use their default corners)
|
|
26
46
|
|
|
27
47
|
## Changes
|
|
28
48
|
### v0.33.0
|
|
@@ -10,6 +10,11 @@ Internal component that renders the processing animation overlay for Button. Con
|
|
|
10
10
|
|
|
11
11
|
See `Button` docs for the public API.
|
|
12
12
|
|
|
13
|
+
## Composability
|
|
14
|
+
- **Internal only — do NOT import or use directly.** The Button component owns the lifecycle of this overlay.
|
|
15
|
+
- Drives Button's `processing` prop rendering. If you're building a custom button and want similar marching-ants feedback, copy the SVG/animation pattern — don't reach into this component.
|
|
16
|
+
- Listed here for reference so consumers grep'ing for "processing" find the behavior origin.
|
|
17
|
+
|
|
13
18
|
## Changes
|
|
14
19
|
### v0.29.0
|
|
15
20
|
- **Added** Initial release — marching ants processing overlay (SVG dashed rect with animated stroke-dashoffset). Speed tiers: ambient (3s), working (2s), urgent (1s). Color maps to step-11 tokens for visibility on all variants.
|
|
@@ -34,6 +34,15 @@
|
|
|
34
34
|
<Button variant="soft" color="warning" size="compact-sm" shape="pill">Overdue</Button>
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## Composability
|
|
38
|
+
- **ButtonGroup context consumption:** When nested inside `<ButtonGroup>`, Button auto-inherits variant/color/size/weight/shape/disabled. Explicit props on the individual Button override. The context also drives position-aware border-radius (first/middle/last within an attached group).
|
|
39
|
+
- **IconProvider cascade:** Icons in `startIcon`/`endIcon` auto-size via IconProvider per the button size (xs→sm, sm→sm, md→md, lg→md, icon-xs→xs, icon-lg→lg). Don't pass explicit `size` to `<Icon>` inside Button.
|
|
40
|
+
- **asChild for router links:** `<Button asChild><Link href="/foo">...</Link></Button>` transfers Button's styling to the Link while preserving navigation semantics. Required for Next.js `<Link>` / react-router `<Link>`.
|
|
41
|
+
- **onClickAsync state machine:** Overrides onClick. Auto-cycles `idle → loading (aria-busy, spinner) → success (checkmark) → idle` on resolve; `loading → error (X mark) → idle` on reject. Duration controlled by `asyncFeedbackDuration` (1500ms default). Auto-activates `processing='working'` during loading — marching-ants border keeps users visually aware.
|
|
42
|
+
- **Processing vs loading:** `loading` is a short async state (shows spinner, blocks clicks). `processing` is a longer-running state (marching ants border, may or may not block clicks based on `processingDisabled`). Use onClickAsync for simple request cases; use processing explicitly for long-running background operations.
|
|
43
|
+
- **DevalokGrain children:** Grain elements are auto-extracted and rendered as direct button children for absolute positioning — lets you layer grain texture on solid-variant buttons without breaking layout.
|
|
44
|
+
- **Prefer `variant="soft"` over `variant="outline"` for secondary actions** (see Gotchas for details). This is a design-system-wide convention.
|
|
45
|
+
|
|
37
46
|
## Gotchas
|
|
38
47
|
- **Prefer `variant="soft"` over `variant="outline"` for secondary actions.** Soft (tinted step-3 bg, step-11 text) is the Devalok-recommended default — it feels warmer and brand-consistent. Use `outline` only when soft's tint would disappear (on colored/surface-raised bg), in toolbar/icon-dense contexts, or when you need outline's stronger hierarchy next to a primary action.
|
|
39
48
|
- DO NOT use variant="destructive" — use variant="solid" color="error"
|
|
@@ -6,18 +6,22 @@
|
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
8
|
variant: "default" | "elevated" | "outline" | "flat"
|
|
9
|
+
color: "default" | "accent" | "error" | "success" | "warning" | "info" | "neutral" (border accent color)
|
|
10
|
+
size: "sm" | "md" | "lg" (padding — propagated to CardHeader/CardContent/CardFooter via context)
|
|
9
11
|
interactive: boolean (enables hover shadow lift + pointer cursor)
|
|
12
|
+
accent: "left" | "top" | "right" | "bottom" (render a colored accent bar on the specified edge)
|
|
13
|
+
accentColor: "default" | "accent" | "error" | "success" | "warning" | "info" (color of the accent bar; default maps to accent-9)
|
|
10
14
|
|
|
11
15
|
## Compound Components
|
|
12
16
|
Card (root)
|
|
13
|
-
CardHeader
|
|
17
|
+
CardHeader ← inherits size from Card context
|
|
14
18
|
CardTitle
|
|
15
19
|
CardDescription
|
|
16
|
-
CardContent
|
|
17
|
-
CardFooter
|
|
20
|
+
CardContent ← inherits size from Card context
|
|
21
|
+
CardFooter ← inherits size from Card context
|
|
18
22
|
|
|
19
23
|
## Defaults
|
|
20
|
-
variant="default"
|
|
24
|
+
variant="default", color="default", size="md"
|
|
21
25
|
|
|
22
26
|
## Example
|
|
23
27
|
```jsx
|
|
@@ -30,8 +34,16 @@
|
|
|
30
34
|
</Card>
|
|
31
35
|
```
|
|
32
36
|
|
|
37
|
+
## Composability
|
|
38
|
+
- **Size cascades through context** — Card's `size` prop sets padding on CardHeader, CardContent, and CardFooter via `CardSizeContext`. Don't set padding classes on sub-components directly; override via `className` if needed.
|
|
39
|
+
- **Not a compound state machine** — Card, CardHeader, CardTitle, etc. are purely structural. No open/close state.
|
|
40
|
+
- **Accent bar is independent:** The `accent` / `accentColor` props render a decorative colored edge bar (absolutely positioned, `aria-hidden`). Works alongside `color` (which tints the border) — the two can stack for layered emphasis.
|
|
41
|
+
- **Interactive cards:** Set `interactive={true}` + `onClick` for clickable cards (entire surface becomes the button). Add `aria-label` on the Card root when there's no visible heading. For complex multi-action cards, prefer standard Card with explicit buttons inside.
|
|
42
|
+
- **ContentCard (composed)** is a higher-level wrapper with built-in header/footer slots and title/actions — use it for list-row-style cards; use Card directly for custom layouts.
|
|
43
|
+
|
|
33
44
|
## Gotchas
|
|
34
45
|
- Use `interactive` prop for clickable cards — adds hover lift and pointer cursor
|
|
46
|
+
- Don't override CardHeader/CardContent/CardFooter padding via className if you want the size cascade to work — set size on Card instead
|
|
35
47
|
|
|
36
48
|
## Changes
|
|
37
49
|
### v0.31.0
|
|
@@ -28,9 +28,18 @@ import { BarChart } from '@devalok/shilp-sutra/ui/charts'
|
|
|
28
28
|
<BarChart data={salesData} />
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
## Composability
|
|
32
|
+
- **ChartContainer wraps all chart primitives** — provides responsive sizing (fills parent width, configurable aspect ratio) and a consistent background/padding. Always render charts inside a ChartContainer unless you're building a custom container.
|
|
33
|
+
- **Legend is a sibling, not a child** — render `<Legend items={...} />` next to your chart (above/below), not nested. Use `onHover` / `onClick` handlers in Legend + chart to sync hover highlights.
|
|
34
|
+
- **Data shape is chart-specific** — BarChart wants `[{ label, value }]`, LineChart wants `[{ x, y, series }]`, etc. Each chart's props doc spells out the shape; don't assume cross-chart compatibility.
|
|
35
|
+
- **Sparkline is the only chart safe to use inline** — it's a minimal 1-line SVG, no axes, no legend. Use it inside StatCard, tables, tight cells. For anything larger, reach for the full chart types.
|
|
36
|
+
- **Entrance animations** — all charts use Framer Motion spring-based entry. Animations respect `prefers-reduced-motion`.
|
|
37
|
+
- **Accessibility:** Charts render role="img" with aria-label from the chart title. For dense data, provide a hidden accessible table fallback manually (WCAG requirement for complex charts).
|
|
38
|
+
|
|
31
39
|
## Gotchas
|
|
32
40
|
- Barrel-isolated since v0.5.0 — must use `@devalok/shilp-sutra/ui/charts`, NOT the `ui` barrel
|
|
33
41
|
- Requires D3 as an optional peer dependency
|
|
42
|
+
- Chart components do NOT auto-generate accessible data tables — add one manually for WCAG compliance on complex charts
|
|
34
43
|
|
|
35
44
|
## Changes
|
|
36
45
|
### v0.18.0
|
|
@@ -199,6 +199,15 @@ Animated bouncing dots with a text description of who is typing.
|
|
|
199
199
|
|
|
200
200
|
---
|
|
201
201
|
|
|
202
|
+
## Composability
|
|
203
|
+
- **Chat is a kit of 7 primitives, not a monolithic ChatWindow.** Compose MessageList (scroll container) + Message/SystemMessage (row variants) + DateSeparator/UnreadSeparator (visual dividers) + MessageInput (composer) + TypingIndicator (presence).
|
|
204
|
+
- **Message is a compound component** — `Message.Avatar`, `Message.Content`, `Message.Author`, `Message.Body`, `Message.Reactions`, `Message.Actions`, `Message.Action`. Arrange them to match your design; most layouts only need Avatar + Content (with Author + Body inside).
|
|
205
|
+
- **Message.Actions reveal on hover** via `group-hover/message` — ONLY works when Actions is nested inside a Message root. If you want a custom action bar, do it differently.
|
|
206
|
+
- **MessageList ARIA:** `role="log" + aria-live="polite"` — screen readers announce new messages automatically. Don't manually add aria-live to children.
|
|
207
|
+
- **grouped mode:** For consecutive messages from the same user, set `grouped={true}` to hide the avatar and author (typical chat UI pattern). Logic for "same user as previous" is consumer-side.
|
|
208
|
+
- **MessageInput is specifically for chat** — auto-resizing textarea (up to 160px), Enter-to-send, Shift+Enter-for-newline, streaming support. For richer composition (formatting, attachments), use RichChatInput from composed (built on top of this + TipTap).
|
|
209
|
+
- **TypingIndicator** accepts multiple users — handles pluralization of the "is/are typing" label automatically.
|
|
210
|
+
|
|
202
211
|
## Gotchas
|
|
203
212
|
- MessageList uses `role="log"` with `aria-live="polite"` — screen readers announce new messages
|
|
204
213
|
- Message entrance animations use Framer Motion springs — AnimatePresence wraps children in MessageList
|
|
@@ -7,20 +7,34 @@
|
|
|
7
7
|
## Props
|
|
8
8
|
checked: boolean | "indeterminate"
|
|
9
9
|
onCheckedChange: (checked: boolean | "indeterminate") => void
|
|
10
|
+
size: "sm" | "md" | "lg"
|
|
10
11
|
error: boolean (shows red border)
|
|
11
12
|
indeterminate: boolean (overrides checked, shows dash icon)
|
|
12
13
|
disabled: boolean
|
|
13
14
|
|
|
14
15
|
## Defaults
|
|
15
|
-
|
|
16
|
+
size="md"
|
|
16
17
|
|
|
17
18
|
## Example
|
|
18
19
|
```jsx
|
|
19
20
|
<Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />
|
|
21
|
+
|
|
22
|
+
{/* With label */}
|
|
23
|
+
<label htmlFor="terms" className="flex items-center gap-ds-02">
|
|
24
|
+
<Checkbox id="terms" checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />
|
|
25
|
+
I agree to the terms
|
|
26
|
+
</label>
|
|
20
27
|
```
|
|
21
28
|
|
|
29
|
+
## Composability
|
|
30
|
+
- **FormField integration:** Unlike Input/Textarea, Checkbox does NOT auto-consume FormField state — the `error` prop must be set explicitly. (Form-library convention differs for checkboxes since they often don't share the same visual grouping.)
|
|
31
|
+
- **Labels:** Checkbox doesn't carry its own label — pair it with `<Label htmlFor="x" />` + `<Checkbox id="x" />`, or wrap both in a `<label>` element. Screen readers rely on that association.
|
|
32
|
+
- **Controlled vs uncontrolled:** Pass `checked` + `onCheckedChange` for controlled, `defaultChecked` for uncontrolled. Don't mix.
|
|
33
|
+
|
|
22
34
|
## Gotchas
|
|
23
35
|
- indeterminate overrides checked visually
|
|
36
|
+
- Checkbox does NOT auto-consume FormField error state — pass `error` explicitly if using inside a FormField
|
|
37
|
+
- WCAG 2.5.8 minimum target size met at md (24px); sm (20px) may fail if not paired with enough label hit area
|
|
24
38
|
|
|
25
39
|
## Changes
|
|
26
40
|
### v0.22.0
|
|
@@ -26,11 +26,20 @@
|
|
|
26
26
|
## Additional Exports
|
|
27
27
|
ChipGroup — re-exported AnimatePresence from framer-motion; wrap a list of Chips for coordinated exit animations
|
|
28
28
|
|
|
29
|
+
## Composability
|
|
30
|
+
- **DEPRECATED — use Badge instead.** Chip v0.29.0+ superset capability merged into Badge. Chip remains in the library for backward compatibility; new code should use:
|
|
31
|
+
- `<Badge>...</Badge>` for static tags (replaces `<Chip label="..." />`)
|
|
32
|
+
- `<Badge onClick={...} selected={isSelected}>...</Badge>` for interactive filter chips
|
|
33
|
+
- `<Badge onDismiss={...}>...</Badge>` for dismissible chips
|
|
34
|
+
- **Why deprecated:** Chip used `label` prop (not children) and had a separate CVA; Badge now supports everything Chip did via children + onClick/onDismiss/selected, with more colors and variants.
|
|
35
|
+
- **Migration:** `<Chip label="React" color="info" />` → `<Badge variant="subtle" color="info">React</Badge>`. ChipGroup → BadgeGroup or just AnimatePresence wrapper.
|
|
36
|
+
|
|
29
37
|
## Gotchas
|
|
30
38
|
- MUST use label prop — children are NOT rendered
|
|
31
39
|
- `<Chip>text</Chip>` is WRONG — use `<Chip label="text" />`
|
|
32
40
|
- Wrap dynamic chip lists in `<ChipGroup>` for exit animations
|
|
33
41
|
- `color="primary"` will be renamed to `color="brand"` in v1.0 — use `color="primary"` for now
|
|
42
|
+
- **Deprecated — migrate to Badge for all new code**
|
|
34
43
|
|
|
35
44
|
## Changes
|
|
36
45
|
### v0.19.1
|
|
@@ -17,8 +17,15 @@
|
|
|
17
17
|
<Code variant="block">{`const x = 1;\nconsole.log(x);`}</Code>
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## Composability
|
|
21
|
+
- **Server-safe.** No context, no cascade.
|
|
22
|
+
- Inline variant composes inside Text, paragraphs, list items, table cells — wherever body text goes.
|
|
23
|
+
- Block variant is a `<pre><code>` pair with overflow-x scroll; pair with a dark background Card or MarkdownViewer for long snippets.
|
|
24
|
+
- Not a syntax-highlighted code viewer — for that, use RichTextEditor's code block or a dedicated library. Code here is typographic emphasis, not lexer-aware rendering.
|
|
25
|
+
|
|
20
26
|
## Gotchas
|
|
21
27
|
- "block" renders as `<pre><code>`, "inline" renders as `<code>`
|
|
28
|
+
- Block variant doesn't syntax-highlight — it's a styled pre tag, nothing more
|
|
22
29
|
|
|
23
30
|
## Changes
|
|
24
31
|
### v0.1.1
|
|
@@ -25,8 +25,17 @@
|
|
|
25
25
|
</Collapsible>
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Composability
|
|
29
|
+
- Radix Collapsible primitive — smaller than Accordion (no grouping/value matching, just open/close).
|
|
30
|
+
- **When to use:** A single show/hide section where the state is local (e.g. "Advanced options" inside a form, expandable row detail, show-more). For multi-section with mutual exclusion, use Accordion.
|
|
31
|
+
- **Inline rendering:** CollapsibleContent is NOT portalled — it expands inline and pushes sibling content down. Respects `overflow` rules of the parent.
|
|
32
|
+
- **No built-in chevron** — unlike AccordionTrigger, CollapsibleTrigger is bare. Add your own icon + rotate via `data-state` attribute Radix sets (`[data-state=open]:rotate-180`).
|
|
33
|
+
- **Animation:** Height transition via `animate-collapsible-down/up` keyframes + Radix `--radix-collapsible-content-height` CSS custom property.
|
|
34
|
+
|
|
28
35
|
## Gotchas
|
|
29
36
|
- Standard Radix Collapsible API
|
|
37
|
+
- No auto-chevron — add one manually if you want the affordance
|
|
38
|
+
- Not portalled — clipped by parent `overflow: hidden`
|
|
30
39
|
|
|
31
40
|
## Changes
|
|
32
41
|
### v0.13.0
|
|
@@ -61,6 +61,14 @@
|
|
|
61
61
|
<ColorInput value={color} onChange={setColor} showPicker={false} />
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
## Composability
|
|
65
|
+
- **Built on Popover internally** — trigger opens a portal-rendered picker panel. z-popover (1400) stacking.
|
|
66
|
+
- **variant="default" vs "inline":** Default variant is an input-style trigger with gradient swatch + hex label (fits in forms). Inline variant IS the selected color — the entire trigger takes the color as its background with contrast-aware text. Use inline for color-tags in chat, lists, or tight toolbar UIs.
|
|
67
|
+
- **Controlled or uncontrolled:** Works both ways — pass `value` + `onChange` for controlled, or omit and let internal state track.
|
|
68
|
+
- **Presets are compositional:** Pass `{ hex, label }[]` for named brand colors (accessible, keyboard-navigable). Pass `false` to hide the preset strip entirely (picker-only mode).
|
|
69
|
+
- **react-colorful** is bundled (2.8KB gzipped) — zero additional setup. Picker itself is pointer-based; keyboard users edit via the HEX/RGB/HSL format inputs below.
|
|
70
|
+
- **FormField:** Not auto-consumed (no `state` prop). Wrap in FormField for label + helper text; style error visuals via className.
|
|
71
|
+
|
|
64
72
|
## Gotchas
|
|
65
73
|
- Value must be a 6-character hex string (e.g. "#d33163")
|
|
66
74
|
- Presets accept both `string[]` (backward-compatible) and `{ hex, label }[]` (recommended for accessibility)
|
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
<ColorSwatch color="oklch(0.7 0.15 200)" shape="rounded" />
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## Composability
|
|
24
|
+
- **Server-safe, decorative-only primitive.** Accepts any valid CSS color string — hex, rgb, oklch, hsl, named. Pure presentation, no context.
|
|
25
|
+
- **Usage patterns:** Inline color marker next to a label, preview dot in lists, color-indicator in a category chip, legend swatch for charts.
|
|
26
|
+
- **`ring={true}`** adds a subtle outline — essential for white/very-light colors that would otherwise disappear on surface-raised backgrounds.
|
|
27
|
+
- **Interactive color picking:** Use ColorInput (which opens a full picker). ColorSwatch is display-only.
|
|
28
|
+
- No IconProvider cascade, no FormField consumption — composes freely with anything.
|
|
29
|
+
|
|
23
30
|
## Gotchas
|
|
24
31
|
- Color is applied via inline `backgroundColor` style, not a token class — accepts any runtime CSS color string
|
|
25
32
|
- Renders `role="presentation"` — purely decorative, not interactive
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
8
|
options: ComboboxOption[] (REQUIRED) — { value: string, label: string, description?: string, icon?: ReactNode, disabled?: boolean }
|
|
9
|
+
size: "xs" | "sm" | "md" | "lg" (trigger height)
|
|
9
10
|
DISCRIMINATED UNION — type depends on `multiple` flag:
|
|
10
11
|
Single (default): multiple?: false, value?: string, onValueChange: (value: string) => void
|
|
11
12
|
Multiple: multiple: true, value?: string[], onValueChange: (value: string[]) => void
|
|
@@ -13,13 +14,14 @@
|
|
|
13
14
|
searchPlaceholder: string (default: "Search...")
|
|
14
15
|
emptyMessage: string (default: "No results found")
|
|
15
16
|
disabled: boolean
|
|
16
|
-
|
|
17
|
+
className: string (wrapper div — the positioning container, NOT the trigger)
|
|
18
|
+
triggerClassName: string (the actual Popover trigger button)
|
|
17
19
|
accessibleLabel: string (custom aria-label for trigger, falls back to placeholder)
|
|
18
20
|
maxVisible: number (default: 6, max dropdown items before scroll)
|
|
19
21
|
renderOption: (option, selected) => ReactNode
|
|
20
22
|
|
|
21
23
|
## Defaults
|
|
22
|
-
placeholder="Select...", searchPlaceholder="Search...", emptyMessage="No results found", maxVisible=6
|
|
24
|
+
size="md", placeholder="Select...", searchPlaceholder="Search...", emptyMessage="No results found", maxVisible=6
|
|
23
25
|
|
|
24
26
|
## Example
|
|
25
27
|
```jsx
|
|
@@ -32,9 +34,20 @@
|
|
|
32
34
|
/>
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
## Composability
|
|
38
|
+
- **Combobox vs Autocomplete vs Select:** Combobox = typeahead search + forced selection (the user picks from filtered options). Autocomplete = typeahead + free text allowed. Select = no typeahead, click-to-open with fixed options. Pick by user behavior, not visual style.
|
|
39
|
+
- **Single vs multi mode** is a discriminated union — `multiple: true` changes the shape of value (`string[]`) and onValueChange. TypeScript enforces the pairing.
|
|
40
|
+
- **Multi-select pills:** Capped at 2 visible + "+N more" overflow regardless of `maxVisible`. Clicking the +N opens a popover list of all selected items (handled by the component).
|
|
41
|
+
- **className vs triggerClassName:** className lands on the wrapper (positioning); triggerClassName lands on the trigger button (styling the control). Know which you need.
|
|
42
|
+
- **Portal + z-popover (1400):** content stacks above Dialog/Sheet; works inside scrolling containers without clipping.
|
|
43
|
+
- **renderOption:** For complex option rendering (avatar + label + description), pass `renderOption: (option, selected) => <YourCustom />`. The selected state is a boolean flag.
|
|
44
|
+
- **FormField:** Does NOT auto-consume FormField state. Wrap in FormField for label + helper text, but style error manually.
|
|
45
|
+
|
|
35
46
|
## Gotchas
|
|
36
47
|
- Enforces selection from list (unlike Autocomplete which allows free text)
|
|
37
|
-
- In multi mode, selected items appear as pills with "+N more" overflow
|
|
48
|
+
- In multi mode, selected items appear as pills with "+N more" overflow (capped at 2 visible pills regardless of `maxVisible`)
|
|
49
|
+
- `className` vs `triggerClassName`: `className` lands on the wrapper div (useful for width/positioning); `triggerClassName` lands on the actual Popover trigger button (useful for styling the control itself)
|
|
50
|
+
- Dropdown content is portalled to document.body — parent styles like `overflow: hidden` don't clip it, and container-scoped test queries won't find it
|
|
38
51
|
|
|
39
52
|
## Changes
|
|
40
53
|
### v0.18.0
|
|
@@ -18,8 +18,19 @@
|
|
|
18
18
|
</Container>
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## Composability
|
|
22
|
+
- **Server-safe layout primitive.** Safe in RSC trees — no hooks, no context.
|
|
23
|
+
- **maxWidth choices:**
|
|
24
|
+
- `"default"` (standard page container — matches the design system's layout grid)
|
|
25
|
+
- `"body"` (narrower reading width — use for article/blog content)
|
|
26
|
+
- `"full"` (no max — edge-to-edge, useful for full-bleed marketing sections)
|
|
27
|
+
- **Polymorphic via `as`:** Change the rendered element for semantics (`as="main"` for page content, `as="section"` for major subdivisions, `as="article"` for standalone content).
|
|
28
|
+
- **mx-auto centering is automatic** — Container handles horizontal centering; it does NOT add vertical spacing. Pair with `py-*` utility classes on the Container itself or inside it.
|
|
29
|
+
- Nothing cascades — nesting Containers is fine but rarely useful (max-width constraints compound).
|
|
30
|
+
|
|
21
31
|
## Gotchas
|
|
22
32
|
- Server-safe component — can be imported directly in Next.js Server Components
|
|
33
|
+
- Container does NOT add vertical padding — add it explicitly via className if needed
|
|
23
34
|
|
|
24
35
|
## Changes
|
|
25
36
|
### v0.1.0
|
|
@@ -29,8 +29,16 @@
|
|
|
29
29
|
</ContextMenu>
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
## Composability
|
|
33
|
+
- Radix ContextMenu — same item-variant surface as DropdownMenu (checkbox, radio group, sub-menus, label, separator) with the same keyboard model. Swap `Dropdown` → `Context` in imports and everything behaves the same.
|
|
34
|
+
- **Trigger is not a button** — ContextMenuTrigger is a wrapper element (defaults to `<div>`) that listens for `contextmenu` events on itself and children. Use `asChild` to pass styling to your own element.
|
|
35
|
+
- **Touch support:** Radix maps long-press to right-click. On mobile, hold-to-open just works without extra code.
|
|
36
|
+
- **No visible trigger affordance** — unlike DropdownMenu/Popover, the user has to *know* the element is right-clickable. Pair with a visible hint (keyboard shortcut label, menu icon elsewhere) for discoverability.
|
|
37
|
+
- **Portal + z-index:** z-popover (1400).
|
|
38
|
+
|
|
32
39
|
## Gotchas
|
|
33
40
|
- Triggered by right-click (or long-press on touch devices)
|
|
41
|
+
- ContextMenuTrigger doesn't auto-indicate it's interactive — add visual affordance elsewhere on the page
|
|
34
42
|
|
|
35
43
|
## Changes
|
|
36
44
|
### v0.18.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal only.** Renders the tbody + rows for DataTable. Consumes DataTableContext for row data, selection state, expandable state, loading skeletons.
|
|
12
|
+
- Customization routes through DataTable props: `renderExpanded`, `onRowClick`, `getRowId`, `loading`, `emptyState`.
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal only.** Renders the floating bulk-action bar that appears when rows are selected. Reads selection state + bulkActions config from DataTableContext.
|
|
12
|
+
- Customization goes through DataTable's `bulkActions` prop — `{ label, onClick, color?, disabled? }[]`.
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal only.** Renders the card wrapper around DataTable (border, shadow, rounded corners matching the Card primitive's surface treatment).
|
|
12
|
+
- DataTable uses this automatically — no consumer-facing prop toggles it.
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal React context** — binds DataTable's sub-components (header, body, pagination, toolbar, bulk-actions) to shared state: TanStack table instance, density, selection, loading.
|
|
12
|
+
- Consumer code never reads this context — all interaction goes through DataTable's props.
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal only.** Renders the thead + column headers for DataTable. Reads sort state + column definitions from DataTableContext.
|
|
12
|
+
- Customization goes through DataTable's `columns` prop (column definitions are TanStack ColumnDef<TData> — header, sortable, filter, etc. all declared there).
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
This component is used internally by `<DataTable>` and should not be imported directly.
|
|
8
8
|
See [DataTable](./data-table.md) for the public API.
|
|
9
9
|
|
|
10
|
+
## Composability
|
|
11
|
+
- **Internal only.** Renders the pagination footer for DataTable. Reads pagination state from DataTableContext.
|
|
12
|
+
- Customization goes through DataTable's `pagination` prop (server-side: pass `{ page, pageSize, total, onPageChange }`) or `pageSize` + `paginated` (client-side).
|
|
13
|
+
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
16
|
### v0.32.0
|
|
@@ -31,10 +31,17 @@ import { DataTableToolbar } from '@devalok/shilp-sutra/ui/data-table-toolbar'
|
|
|
31
31
|
/>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Composability
|
|
35
|
+
- **Companion to DataTable** — typically enabled via DataTable's `toolbar={true}` prop (which auto-renders this internally). Use DataTableToolbar directly only if you're building a custom DataTable integration that needs the toolbar positioned/styled differently.
|
|
36
|
+
- **Reads table state via the `table` instance** (TanStack react-table) — you must pass it. For the auto-rendered version inside DataTable, this wiring is automatic.
|
|
37
|
+
- **Feature toggles:** `globalFilter` (search across all columns), density switcher (compact/standard/comfortable row heights), CSV export. Turn each on/off independently.
|
|
38
|
+
- **Density changes are runtime** — the switcher writes to the same `defaultDensity` that DataTable's prop seeds. State lives in DataTable context.
|
|
39
|
+
|
|
34
40
|
## Gotchas
|
|
35
41
|
- Barrel-isolated since v0.5.0 — must use `@devalok/shilp-sutra/ui/data-table-toolbar`, NOT the `ui` barrel
|
|
36
42
|
- Companion to DataTable — provides column visibility, density toggle, and CSV export controls
|
|
37
43
|
- Requires @tanstack/react-table as a peer dependency
|
|
44
|
+
- Prefer DataTable's `toolbar={true}` prop over rendering this directly
|
|
38
45
|
|
|
39
46
|
## Changes
|
|
40
47
|
### v0.5.0
|
|
@@ -55,6 +55,30 @@ import { DataTable } from '@devalok/shilp-sutra/ui/data-table'
|
|
|
55
55
|
/>
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
## Composability
|
|
59
|
+
**Server vs client mode is prop-driven, not explicit.**
|
|
60
|
+
- Pass `onSort` → server-side sort (manual, rows stay in data order — you're responsible for re-fetching).
|
|
61
|
+
- Pass `pagination` object → server-side pagination (manual, pass total count).
|
|
62
|
+
- Omit both → client-side sort/pagination via TanStack react-table.
|
|
63
|
+
- Mix-and-match: `onSort` + no pagination = server sort + client pagination.
|
|
64
|
+
|
|
65
|
+
**Companion components:**
|
|
66
|
+
- `DataTableToolbar` — enabled via `toolbar={true}`. Provides column visibility, density switcher, CSV export. Reads table state via `DataTableContext` (internal). Rendered ABOVE the table automatically.
|
|
67
|
+
- `BulkActionBar` (floating) — appears when rows are selected AND `bulkActions` array is non-empty. Synced with `selectedIds`; shows count + action buttons.
|
|
68
|
+
- `EmptyState` from `@devalok/shilp-sutra/composed` — pass to `emptyState` prop. Takes precedence over `noResultsText` string.
|
|
69
|
+
|
|
70
|
+
**Controlled selection:**
|
|
71
|
+
- Pass `selectedIds` (Set<string>) + `onSelectionChange` for controlled row selection.
|
|
72
|
+
- Provide `getRowId: (row) => row.id` so selection survives data refetches (otherwise TanStack uses array index, which breaks on sort/filter).
|
|
73
|
+
- `selectableFilter: (row) => boolean` disables selection on specific rows (e.g. archived items).
|
|
74
|
+
|
|
75
|
+
**Row click model:**
|
|
76
|
+
- `onRowClick` fires on row-level click BUT excludes clicks on checkboxes, buttons, links, and inputs automatically. No manual `stopPropagation` needed for standard interactive elements.
|
|
77
|
+
|
|
78
|
+
**Virtualization:** `virtualRows={true}` enables row virtualization via `@tanstack/react-virtual`. Turn it on for 1000+ row datasets; the scroll container must have a bounded height.
|
|
79
|
+
|
|
80
|
+
**Density integration:** `defaultDensity="compact"` is the Karm-style dense mode (h-9 rows). DataTableToolbar's density switcher updates this at runtime; the prop sets the initial state only.
|
|
81
|
+
|
|
58
82
|
## Gotchas
|
|
59
83
|
- Barrel-isolated since v0.5.0 — must use `@devalok/shilp-sutra/ui/data-table`, NOT the `ui` barrel
|
|
60
84
|
- Requires @tanstack/react-table and @tanstack/react-virtual as peer dependencies
|
|
@@ -63,6 +87,7 @@ import { DataTable } from '@devalok/shilp-sutra/ui/data-table'
|
|
|
63
87
|
- selectedIds syncs via useEffect — provide getRowId for custom row IDs
|
|
64
88
|
- onRowClick does NOT fire when clicking checkboxes, buttons, links, or inputs
|
|
65
89
|
- Use defaultDensity="compact" for Karm-style h-9 rows
|
|
90
|
+
- `virtualRows={true}` requires a bounded scroll container — unbounded height silently disables virtualization
|
|
66
91
|
|
|
67
92
|
## Changes
|
|
68
93
|
### v0.29.0
|
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
</div>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
## Composability
|
|
45
|
+
- **Brand texture overlay** — drops into any parent with `relative overflow-hidden isolate`. Auto-inherits the parent's border radius.
|
|
46
|
+
- **Button auto-extracts Grain children** — if you nest `<DevalokGrain>` inside a `<Button>`, Button auto-separates it from the label slot and positions it correctly. No extra wrapping needed.
|
|
47
|
+
- **Card, custom hero sections, landing-page tiles** — wrap in a positioned container (or add the `relative overflow-hidden isolate` classes to Card explicitly) and drop Grain in as a sibling to your content.
|
|
48
|
+
- **z-layer contract:** Grain renders at `z-[1]`. Content on top needs `z-[2]+`. The component doesn't boost child z-index — that's consumer responsibility.
|
|
49
|
+
- **`hoverIntensify` depends on parent** — the parent must have the Tailwind `group` class so `group-hover:` selectors apply. Forgetting this silently disables the effect.
|
|
50
|
+
- **Tint composes with surface:** Pass an OKLCH color (or CSS variable reference like `var(--color-accent-9)`) to `tint` for a directional gradient on top of the noise. Without tint, just noise.
|
|
51
|
+
|
|
44
52
|
## Gotchas
|
|
45
53
|
- Parent element MUST have `relative overflow-hidden isolate` for the grain to render correctly
|
|
46
54
|
- The grain layers are absolute-positioned at `z-[1]` — content that should appear above must use `z-[2]` or higher
|
|
@@ -35,8 +35,18 @@
|
|
|
35
35
|
</Dialog>
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
## Composability
|
|
39
|
+
- Built on Radix Dialog primitives — every standard Radix prop passes through (`open`, `onOpenChange`, `defaultOpen`, `modal`).
|
|
40
|
+
- **Trigger composition:** `<DialogTrigger asChild>` renders the wrapped element as the trigger — typical pattern is `<DialogTrigger asChild><Button>...</Button></DialogTrigger>`. Without `asChild`, a default button is injected.
|
|
41
|
+
- **Portal rendering:** DialogContent portals to `document.body`. CSS containers (`overflow: hidden`, `transform`, stacking contexts) on ancestors of the trigger don't clip it. Container-scoped test queries miss portalled content — use `screen` or the portal root.
|
|
42
|
+
- **Focus management:** Radix traps focus inside Content while open and restores it to the trigger on close. First focusable element inside receives focus automatically.
|
|
43
|
+
- **Imperative close** from deep children: use `<DialogClose asChild>` around your own button, or `useDialogContext` — no prop drilling.
|
|
44
|
+
- **z-index:** DialogContent uses `z-dialog` (configured in Tailwind theme). Nested overlays (Popover inside Dialog) stack on top because Popover uses `z-popover` (1400) higher than `z-dialog`.
|
|
45
|
+
|
|
38
46
|
## Gotchas
|
|
39
47
|
- DialogTitle is required for accessibility — screen readers announce it when the dialog opens
|
|
48
|
+
- If your layout suppresses the title visually, use `<VisuallyHidden>` around DialogTitle — don't omit it
|
|
49
|
+
- Focus returns to the trigger on close — if the trigger is conditionally unmounted, focus lands on body; handle manually if that matters
|
|
40
50
|
|
|
41
51
|
## Changes
|
|
42
52
|
### v0.19.1
|
|
@@ -31,8 +31,18 @@
|
|
|
31
31
|
</DropdownMenu>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Composability
|
|
35
|
+
- Radix DropdownMenu underneath — same prop surface (`open`, `onOpenChange`, `defaultOpen`, `modal`).
|
|
36
|
+
- **Item variants** stack cleanly: `DropdownMenuCheckboxItem` for multi-select toggles, `DropdownMenuRadioGroup` + `DropdownMenuRadioItem` for single-select, `DropdownMenuSub` + `DropdownMenuSubTrigger/SubContent` for nested submenus. Each has its own keyboard model pre-wired.
|
|
37
|
+
- **Keyboard:** Arrow keys navigate items, Enter/Space activates, Esc closes, typeahead jumps to first letter. All handled by Radix — don't re-implement.
|
|
38
|
+
- **Trigger:** `<DropdownMenuTrigger asChild>` around any button. IconButton is the common pairing.
|
|
39
|
+
- **Shortcut hints:** `<DropdownMenuShortcut>` inside an item renders a right-aligned `⌘K`-style kbd. Visual only — does NOT bind the shortcut globally.
|
|
40
|
+
- **Closing from a handler:** Item onSelect auto-closes the menu by default. Pass `event.preventDefault()` inside the handler to keep it open (e.g. for checkbox items that shouldn't close on toggle).
|
|
41
|
+
|
|
34
42
|
## Gotchas
|
|
35
43
|
- Use `asChild` on DropdownMenuTrigger to render your own button element
|
|
44
|
+
- DropdownMenuShortcut is decorative — bind keyboard shortcuts separately (e.g. with `useHotkeys`)
|
|
45
|
+
- Sub-menus need BOTH DropdownMenuSubTrigger (visible item) and DropdownMenuSubContent (the submenu panel) — missing either silently breaks the hover-open behavior
|
|
36
46
|
|
|
37
47
|
## Changes
|
|
38
48
|
### v0.22.0
|