@devalok/shilp-sutra 0.52.0 → 0.54.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/AGENTS.md +7 -1
- package/BREAKING.json +29 -0
- package/MIGRATION.md +61 -0
- package/dist/_chunks/motion-provider.js +7 -6
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/success.js +53 -53
- package/dist/ai/command-bar.js +158 -158
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +5 -5
- package/dist/composed/avatar-group.d.ts +11 -9
- package/dist/composed/avatar-group.d.ts.map +1 -1
- package/dist/composed/avatar-group.js +108 -140
- package/dist/composed/avatar-group.js.map +1 -1
- package/dist/composed/bulk-action-bar.d.ts +19 -11
- package/dist/composed/bulk-action-bar.d.ts.map +1 -1
- package/dist/composed/bulk-action-bar.js +81 -110
- package/dist/composed/bulk-action-bar.js.map +1 -1
- package/dist/composed/command-palette.js +17 -17
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/error-boundary.d.ts +15 -3
- package/dist/composed/error-boundary.d.ts.map +1 -1
- package/dist/composed/error-boundary.js +43 -26
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/loading-skeleton.d.ts +2 -0
- package/dist/composed/loading-skeleton.d.ts.map +1 -1
- package/dist/composed/loading-skeleton.js +79 -56
- package/dist/composed/loading-skeleton.js.map +1 -1
- package/dist/composed/master-detail.d.ts +21 -8
- package/dist/composed/master-detail.d.ts.map +1 -1
- package/dist/composed/master-detail.js +91 -77
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/page-skeletons.d.ts +6 -0
- package/dist/composed/page-skeletons.d.ts.map +1 -1
- package/dist/composed/page-skeletons.js +93 -71
- package/dist/composed/page-skeletons.js.map +1 -1
- package/dist/composed/priority-indicator.d.ts +15 -6
- package/dist/composed/priority-indicator.d.ts.map +1 -1
- package/dist/composed/priority-indicator.js +37 -88
- package/dist/composed/priority-indicator.js.map +1 -1
- package/dist/composed/schedule-view.d.ts +17 -2
- package/dist/composed/schedule-view.d.ts.map +1 -1
- package/dist/composed/schedule-view.js +163 -64
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.d.ts +32 -6
- package/dist/shell/bottom-navbar.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +156 -129
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/index.d.ts +5 -3
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +2 -3
- package/dist/shell/notification-preferences.d.ts.map +1 -1
- package/dist/shell/notification-preferences.js +2 -0
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/tokens/primitives.css +6 -2
- package/dist/tokens/utilities.css +6 -0
- package/dist/ui/autocomplete.d.ts +34 -32
- package/dist/ui/autocomplete.d.ts.map +1 -1
- package/dist/ui/autocomplete.js +115 -110
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/combobox.d.ts +1 -1
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +133 -128
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/file-upload.d.ts.map +1 -1
- package/dist/ui/file-upload.js +124 -138
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/form.d.ts +7 -0
- package/dist/ui/form.d.ts.map +1 -1
- package/dist/ui/form.js +4 -2
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/icon-button.d.ts +2 -1
- package/dist/ui/icon-button.d.ts.map +1 -1
- package/dist/ui/icon-button.js +1 -1
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/index.js +30 -30
- package/dist/ui/label.d.ts.map +1 -1
- package/dist/ui/label.js +7 -6
- package/dist/ui/label.js.map +1 -1
- package/dist/ui/search-input.js +4 -4
- package/dist/ui/sidebar.js +7 -7
- package/dist/ui/spinner.d.ts.map +1 -1
- package/dist/ui/spinner.js +50 -44
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/switch.d.ts.map +1 -1
- package/dist/ui/switch.js +24 -24
- package/dist/ui/switch.js.map +1 -1
- package/dist/ui/table.js +1 -1
- package/dist/ui/table.js.map +1 -1
- package/docs/components/composed/bulk-action-bar.md +9 -3
- package/docs/components/composed/error-boundary.md +18 -2
- package/docs/components/composed/master-detail.md +12 -2
- package/docs/components/composed/page-skeletons.md +2 -2
- package/docs/components/composed/priority-indicator.md +22 -11
- package/docs/components/composed/rich-chat-input.md +18 -6
- package/docs/components/composed/schedule-view.md +20 -5
- package/docs/components/composed/simple-tooltip.md +1 -1
- package/docs/components/shell/app-command-palette.md +2 -1
- package/docs/components/shell/bottom-navbar.md +28 -9
- package/docs/components/shell/command-registry.md +2 -2
- package/docs/components/shell/link-context.md +2 -2
- package/docs/components/shell/top-bar.md +1 -1
- package/docs/components/ui/autocomplete.md +26 -10
- package/docs/components/ui/search-input.md +2 -2
- package/docs/components/ui/slider.md +2 -2
- package/docs/components/ui/split-button.md +3 -3
- package/llms.txt +2 -2
- package/make-kit/Guidelines.md +1 -1
- package/make-kit/components/overview.md +2 -2
- package/make-kit/foundations/surfaces.md +1 -1
- package/mcp-manifest.json +581 -172
- package/package.json +1 -6
- package/skill/SKILL.md +1 -1
- package/skill/chat-skill/README.md +18 -0
- package/skill/chat-skill/SKILL.md +78 -0
- package/skill/chat-skill/chatgpt-instructions.md +26 -0
- package/skill/chat-skill/gemini-instructions.md +25 -0
- package/skill/references/components.md +2 -2
- package/dist/shell/sidebar.d.ts +0 -113
- package/dist/shell/sidebar.d.ts.map +0 -1
- package/dist/shell/sidebar.js +0 -293
- package/dist/shell/sidebar.js.map +0 -1
- package/docs/components/shell/sidebar.md +0 -103
package/mcp-manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "./mcp-manifest.schema.json",
|
|
3
3
|
"manifestVersion": "1.2.0",
|
|
4
4
|
"package": "@devalok/shilp-sutra",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.54.0",
|
|
6
6
|
"components": {
|
|
7
7
|
"accordion": {
|
|
8
8
|
"displayName": "Accordion",
|
|
@@ -386,7 +386,16 @@
|
|
|
386
386
|
"name": "union",
|
|
387
387
|
"raw": "AutocompleteOption | null"
|
|
388
388
|
},
|
|
389
|
-
"required": false
|
|
389
|
+
"required": false,
|
|
390
|
+
"description": "controlled"
|
|
391
|
+
},
|
|
392
|
+
"defaultValue": {
|
|
393
|
+
"type": {
|
|
394
|
+
"name": "union",
|
|
395
|
+
"raw": "AutocompleteOption | null"
|
|
396
|
+
},
|
|
397
|
+
"required": false,
|
|
398
|
+
"description": "uncontrolled initial"
|
|
390
399
|
},
|
|
391
400
|
"onValueChange": {
|
|
392
401
|
"type": {
|
|
@@ -414,6 +423,46 @@
|
|
|
414
423
|
},
|
|
415
424
|
"required": false
|
|
416
425
|
},
|
|
426
|
+
"size": {
|
|
427
|
+
"type": {
|
|
428
|
+
"name": "object",
|
|
429
|
+
"raw": "(forwarded to Input)"
|
|
430
|
+
},
|
|
431
|
+
"required": false
|
|
432
|
+
},
|
|
433
|
+
"state": {
|
|
434
|
+
"type": {
|
|
435
|
+
"name": "enum",
|
|
436
|
+
"value": [
|
|
437
|
+
"default",
|
|
438
|
+
"error",
|
|
439
|
+
"warning",
|
|
440
|
+
"success"
|
|
441
|
+
]
|
|
442
|
+
},
|
|
443
|
+
"required": false,
|
|
444
|
+
"description": "forwarded to Input"
|
|
445
|
+
},
|
|
446
|
+
"isLoading": {
|
|
447
|
+
"type": {
|
|
448
|
+
"name": "boolean"
|
|
449
|
+
},
|
|
450
|
+
"required": false
|
|
451
|
+
},
|
|
452
|
+
"loadingText": {
|
|
453
|
+
"type": {
|
|
454
|
+
"name": "string"
|
|
455
|
+
},
|
|
456
|
+
"required": false,
|
|
457
|
+
"defaultValue": "Loading…"
|
|
458
|
+
},
|
|
459
|
+
"renderOption": {
|
|
460
|
+
"type": {
|
|
461
|
+
"name": "function",
|
|
462
|
+
"raw": "(option, query) => ReactNode"
|
|
463
|
+
},
|
|
464
|
+
"required": false
|
|
465
|
+
},
|
|
417
466
|
"className": {
|
|
418
467
|
"type": {
|
|
419
468
|
"name": "string"
|
|
@@ -429,25 +478,34 @@
|
|
|
429
478
|
},
|
|
430
479
|
"composition": {
|
|
431
480
|
"notes": [
|
|
432
|
-
"**
|
|
433
|
-
"**
|
|
434
|
-
"**
|
|
481
|
+
"**Composes `Input`** — the field is the DS `Input`, so it inherits `size`, error/`state` painting, read-only, hover, and FormField wiring. Autocomplete owns only the dropdown + behavior.",
|
|
482
|
+
"**Autocomplete vs Combobox:** Autocomplete allows free-text input (users can type anything); Combobox enforces selection from the list.",
|
|
483
|
+
"**Value shape is an object** (`{ value, label }`), not a plain string. Controlled via `value`, or uncontrolled via `defaultValue`.",
|
|
484
|
+
"**FormField:** auto-consumes FormField state (via the composed Input) — inside a FormField, error border + `aria-invalid`/`aria-describedby`/`required` are wired automatically. Pass `state` to override.",
|
|
485
|
+
"**Async / \"type to search\":** set `isLoading` to show a spinner (in the field + the listbox) with `loadingText`.",
|
|
486
|
+
"**Matched-text highlight:** the query substring is bolded in each option by default; override the whole row with `renderOption`.",
|
|
435
487
|
"**Portal rendering:** Dropdown portals to body with z-popover (1400) — stacks above Dialog/Sheet.",
|
|
436
|
-
"**Keyboard:** ArrowDown/Up navigate
|
|
488
|
+
"**Keyboard:** ArrowDown/Up/Home/End navigate, Enter selects, Esc closes."
|
|
437
489
|
]
|
|
438
490
|
},
|
|
439
491
|
"docPath": "docs/components/ui/autocomplete.md",
|
|
440
492
|
"defaults": {
|
|
441
|
-
"emptyText": "No options"
|
|
493
|
+
"emptyText": "No options",
|
|
494
|
+
"loadingText": "Loading…"
|
|
442
495
|
},
|
|
443
496
|
"examples": [
|
|
444
497
|
"<Autocomplete\n options={[{ value: 'mumbai', label: 'Mumbai' }]}\n value={selectedCity}\n onValueChange={setSelectedCity}\n placeholder=\"Search cities...\"\n/>"
|
|
445
498
|
],
|
|
446
499
|
"gotchas": [
|
|
447
500
|
"Allows free-text input (no forced selection) — use Combobox for forced selection",
|
|
448
|
-
"value is an object { value, label }, NOT just a string"
|
|
501
|
+
"value is an object { value, label }, NOT just a string",
|
|
502
|
+
"Client-side filtering only (known list). For huge/remote lists, drive `options` yourself with `isLoading` — no built-in virtualization."
|
|
449
503
|
],
|
|
450
504
|
"changes": [
|
|
505
|
+
{
|
|
506
|
+
"version": "0.53.0",
|
|
507
|
+
"summary": "**Changed** Re-parented onto the DS `Input` primitive — inherits `size`, error/`state` painting, read-only, hover, and FormField auto-consumption (previously re-rolled its own `<input>` and read FormField error but never painted it)."
|
|
508
|
+
},
|
|
451
509
|
{
|
|
452
510
|
"version": "0.18.0",
|
|
453
511
|
"summary": "**Fixed** Added `useEffect` to sync query when external value changes"
|
|
@@ -5159,6 +5217,7 @@
|
|
|
5159
5217
|
"type": {
|
|
5160
5218
|
"name": "enum",
|
|
5161
5219
|
"value": [
|
|
5220
|
+
"xs",
|
|
5162
5221
|
"sm",
|
|
5163
5222
|
"md",
|
|
5164
5223
|
"lg"
|
|
@@ -5200,7 +5259,7 @@
|
|
|
5200
5259
|
"**`onClear` makes the X button appear** only when `value` is non-empty. Pair them so users can reset.",
|
|
5201
5260
|
"**`loading={true}` swaps the clear button for a spinner** with `aria-busy=\"true\"` on the input — useful for debounced/async search.",
|
|
5202
5261
|
"Doesn't auto-consume FormField (no `state` prop) — wrap a regular Input inside FormField for validated search fields.",
|
|
5203
|
-
"Keyboard: Escape
|
|
5262
|
+
"Keyboard: Escape is NOT wired to clear (the input is not `type=\"search\"`). Reset via the X button, or handle Escape yourself and call your `value` setter."
|
|
5204
5263
|
]
|
|
5205
5264
|
},
|
|
5206
5265
|
"docPath": "docs/components/ui/search-input.md",
|
|
@@ -5637,139 +5696,168 @@
|
|
|
5637
5696
|
]
|
|
5638
5697
|
},
|
|
5639
5698
|
"sidebar": {
|
|
5640
|
-
"displayName": "
|
|
5641
|
-
"tier": "
|
|
5642
|
-
"import": "@devalok/shilp-sutra/
|
|
5699
|
+
"displayName": "Sidebar",
|
|
5700
|
+
"tier": "ui",
|
|
5701
|
+
"import": "@devalok/shilp-sutra/ui/sidebar",
|
|
5643
5702
|
"serverSafe": false,
|
|
5644
5703
|
"description": "",
|
|
5645
|
-
"props": {
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5704
|
+
"props": {},
|
|
5705
|
+
"composition": {
|
|
5706
|
+
"notes": [
|
|
5707
|
+
"`Sidebar` — applies collapsed / expanded / off-canvas styles based on `state`",
|
|
5708
|
+
"`SidebarTrigger` — calls `toggleSidebar()` on click; reflects aria-expanded",
|
|
5709
|
+
"`SidebarMenuButton` — uses `state === 'collapsed'` to show its `tooltip` (hidden label appears only when sidebar is icon-width)",
|
|
5710
|
+
"`SidebarInset` — main content area adjusts its left offset based on sidebar width + state",
|
|
5711
|
+
"`SidebarRail` — invisible hit target on the outer edge for click-to-toggle",
|
|
5712
|
+
"Any user component that calls `useSidebar()` — full access to open/isMobile/toggle **Desktop vs mobile:** Context tracks `isMobile` via the `use-mobile` hook and branches behavior: on desktop the sidebar collapses to an icon rail; on mobile it becomes an off-canvas drawer controlled by `openMobile`. **Controlled or uncontrolled:** `SidebarProvider` accepts `open` + `onOpenChange` (controlled) or `defaultOpen` (uncontrolled). State is synced to a cookie for cross-route persistence. **Next.js / router integration:** `SidebarMenuButton` with `asChild` wraps any link element (`next/link`, `react-router Link`, plain `<a>`) — it transfers its styling + isActive state to the child while preserving the link's navigation semantics."
|
|
5713
|
+
],
|
|
5714
|
+
"parts": [
|
|
5715
|
+
{
|
|
5716
|
+
"name": "SidebarProvider",
|
|
5717
|
+
"description": "context provider — must wrap everything"
|
|
5649
5718
|
},
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
"user": {
|
|
5654
|
-
"type": {
|
|
5655
|
-
"name": "union",
|
|
5656
|
-
"raw": "SidebarUser | null — { name, email?, image?, designation?, role? }"
|
|
5719
|
+
{
|
|
5720
|
+
"name": "Sidebar",
|
|
5721
|
+
"description": "root panel"
|
|
5657
5722
|
},
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
"navGroups": {
|
|
5661
|
-
"type": {
|
|
5662
|
-
"name": "object",
|
|
5663
|
-
"raw": "NavGroup[] — { label: string, items: NavItem[], action?: ReactNode }"
|
|
5723
|
+
{
|
|
5724
|
+
"name": "SidebarHeader"
|
|
5664
5725
|
},
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
"logo": {
|
|
5668
|
-
"type": {
|
|
5669
|
-
"name": "ReactNode"
|
|
5726
|
+
{
|
|
5727
|
+
"name": "SidebarContent"
|
|
5670
5728
|
},
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
"footerLinks": {
|
|
5674
|
-
"type": {
|
|
5675
|
-
"name": "object",
|
|
5676
|
-
"raw": "Array<{ label: string, href: string }>"
|
|
5729
|
+
{
|
|
5730
|
+
"name": "SidebarGroup"
|
|
5677
5731
|
},
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
},
|
|
5681
|
-
"footer": {
|
|
5682
|
-
"type": {
|
|
5683
|
-
"name": "object",
|
|
5684
|
-
"raw": "SidebarFooterConfig — structured footer"
|
|
5732
|
+
{
|
|
5733
|
+
"name": "SidebarGroupLabel"
|
|
5685
5734
|
},
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
},
|
|
5689
|
-
"headerSlot": {
|
|
5690
|
-
"type": {
|
|
5691
|
-
"name": "ReactNode"
|
|
5735
|
+
{
|
|
5736
|
+
"name": "SidebarGroupAction"
|
|
5692
5737
|
},
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
"preFooterSlot": {
|
|
5696
|
-
"type": {
|
|
5697
|
-
"name": "ReactNode"
|
|
5738
|
+
{
|
|
5739
|
+
"name": "SidebarGroupContent"
|
|
5698
5740
|
},
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
"preFooterClassName": {
|
|
5702
|
-
"type": {
|
|
5703
|
-
"name": "object",
|
|
5704
|
-
"raw": "string — className on preFooterSlot wrapper div"
|
|
5741
|
+
{
|
|
5742
|
+
"name": "SidebarMenu"
|
|
5705
5743
|
},
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
"renderItem": {
|
|
5709
|
-
"type": {
|
|
5710
|
-
"name": "function",
|
|
5711
|
-
"raw": "(item: NavItem, defaultRender: () => ReactNode) => ReactNode | null — custom item rendering"
|
|
5744
|
+
{
|
|
5745
|
+
"name": "SidebarMenuItem"
|
|
5712
5746
|
},
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
"type": {
|
|
5717
|
-
"name": "string"
|
|
5747
|
+
{
|
|
5748
|
+
"name": "SidebarMenuButton",
|
|
5749
|
+
"description": "tooltip, isActive"
|
|
5718
5750
|
},
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5751
|
+
{
|
|
5752
|
+
"name": "SidebarMenuAction"
|
|
5753
|
+
},
|
|
5754
|
+
{
|
|
5755
|
+
"name": "SidebarMenuBadge"
|
|
5756
|
+
},
|
|
5757
|
+
{
|
|
5758
|
+
"name": "SidebarMenuSub"
|
|
5759
|
+
},
|
|
5760
|
+
{
|
|
5761
|
+
"name": "SidebarMenuSubItem"
|
|
5762
|
+
},
|
|
5763
|
+
{
|
|
5764
|
+
"name": "SidebarMenuSubButton",
|
|
5765
|
+
"description": "isActive"
|
|
5766
|
+
},
|
|
5767
|
+
{
|
|
5768
|
+
"name": "SidebarFooter"
|
|
5769
|
+
},
|
|
5770
|
+
{
|
|
5771
|
+
"name": "SidebarSeparator"
|
|
5772
|
+
},
|
|
5773
|
+
{
|
|
5774
|
+
"name": "SidebarRail"
|
|
5775
|
+
},
|
|
5776
|
+
{
|
|
5777
|
+
"name": "SidebarInset",
|
|
5778
|
+
"description": "main content area"
|
|
5779
|
+
},
|
|
5780
|
+
{
|
|
5781
|
+
"name": "SidebarTrigger",
|
|
5782
|
+
"description": "hamburger button"
|
|
5783
|
+
},
|
|
5784
|
+
{
|
|
5785
|
+
"name": "SidebarInput",
|
|
5786
|
+
"description": "search input in sidebar"
|
|
5787
|
+
},
|
|
5788
|
+
{
|
|
5789
|
+
"name": "SidebarMenuSkeleton",
|
|
5790
|
+
"description": "loading placeholder"
|
|
5791
|
+
}
|
|
5730
5792
|
]
|
|
5731
5793
|
},
|
|
5732
|
-
"docPath": "docs/components/
|
|
5794
|
+
"docPath": "docs/components/ui/sidebar.md",
|
|
5795
|
+
"defaults": {
|
|
5796
|
+
"variant": "default",
|
|
5797
|
+
"size": "md"
|
|
5798
|
+
},
|
|
5799
|
+
"subComponents": {
|
|
5800
|
+
"SidebarMenuButton": {
|
|
5801
|
+
"props": {
|
|
5802
|
+
"variant": {
|
|
5803
|
+
"type": {
|
|
5804
|
+
"name": "enum",
|
|
5805
|
+
"value": [
|
|
5806
|
+
"default",
|
|
5807
|
+
"outline"
|
|
5808
|
+
]
|
|
5809
|
+
},
|
|
5810
|
+
"required": false
|
|
5811
|
+
},
|
|
5812
|
+
"size": {
|
|
5813
|
+
"type": {
|
|
5814
|
+
"name": "enum",
|
|
5815
|
+
"value": [
|
|
5816
|
+
"sm",
|
|
5817
|
+
"md",
|
|
5818
|
+
"lg"
|
|
5819
|
+
]
|
|
5820
|
+
},
|
|
5821
|
+
"required": false
|
|
5822
|
+
},
|
|
5823
|
+
"isActive": {
|
|
5824
|
+
"type": {
|
|
5825
|
+
"name": "boolean"
|
|
5826
|
+
},
|
|
5827
|
+
"required": false,
|
|
5828
|
+
"description": "highlights as current nav item"
|
|
5829
|
+
},
|
|
5830
|
+
"tooltip": {
|
|
5831
|
+
"type": {
|
|
5832
|
+
"name": "ReactNode"
|
|
5833
|
+
},
|
|
5834
|
+
"required": false,
|
|
5835
|
+
"description": "shown when sidebar is collapsed"
|
|
5836
|
+
},
|
|
5837
|
+
"asChild": {
|
|
5838
|
+
"type": {
|
|
5839
|
+
"name": "boolean"
|
|
5840
|
+
},
|
|
5841
|
+
"required": false,
|
|
5842
|
+
"description": "render as Slot — common with next/link"
|
|
5843
|
+
}
|
|
5844
|
+
}
|
|
5845
|
+
}
|
|
5846
|
+
},
|
|
5733
5847
|
"examples": [
|
|
5734
|
-
"<
|
|
5848
|
+
"<SidebarProvider>\n <Sidebar>\n <SidebarHeader>Logo</SidebarHeader>\n <SidebarContent>\n <SidebarGroup>\n <SidebarGroupLabel>Navigation</SidebarGroupLabel>\n <SidebarGroupContent>\n <SidebarMenu>\n <SidebarMenuItem>\n <SidebarMenuButton isActive>\n <IconHome /> Dashboard\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n </SidebarContent>\n </Sidebar>\n <SidebarInset>\n <SidebarTrigger />\n <main>Page content</main>\n </SidebarInset>\n</SidebarProvider>"
|
|
5735
5849
|
],
|
|
5736
5850
|
"gotchas": [
|
|
5737
|
-
"
|
|
5738
|
-
"
|
|
5739
|
-
"`
|
|
5740
|
-
"
|
|
5741
|
-
"Collapsible nav items auto-open when a child is active (matching `currentPath`)",
|
|
5742
|
-
"Badge numbers > 99 display as \"99+\""
|
|
5851
|
+
"SidebarProvider MUST wrap both Sidebar and SidebarInset",
|
|
5852
|
+
"Use SidebarMenuButton for nav items (supports tooltip in collapsed state)",
|
|
5853
|
+
"`tooltip` is only visible when sidebar is collapsed — providing one doesn't duplicate the visible label",
|
|
5854
|
+
"Cookie-based state persistence means the sidebar defaults to its prior state on page reload — use `defaultOpen` to override if needed"
|
|
5743
5855
|
],
|
|
5744
5856
|
"changes": [
|
|
5745
|
-
{
|
|
5746
|
-
"version": "0.19.0",
|
|
5747
|
-
"summary": "**Changed** Background elevated from `bg-surface-1` to `bg-surface-2` for visual hierarchy above app background"
|
|
5748
|
-
},
|
|
5749
5857
|
{
|
|
5750
5858
|
"version": "0.18.0",
|
|
5751
5859
|
"summary": "**Fixed** `bg-interactive-subtle` changed to `bg-accent-2` (OKLCH migration)"
|
|
5752
5860
|
},
|
|
5753
|
-
{
|
|
5754
|
-
"version": "0.16.0",
|
|
5755
|
-
"summary": "**Added** `preFooterClassName?: string` — custom className on preFooterSlot wrapper"
|
|
5756
|
-
},
|
|
5757
|
-
{
|
|
5758
|
-
"version": "0.14.0",
|
|
5759
|
-
"summary": "**Changed** `footer.version` now accepts `string | { label: string; href: string }` — version can link to changelog"
|
|
5760
|
-
},
|
|
5761
|
-
{
|
|
5762
|
-
"version": "0.13.0",
|
|
5763
|
-
"summary": "**Added** `SidebarPromo` type and `footer.promo` prop — dismissable promo/upsell banner"
|
|
5764
|
-
},
|
|
5765
|
-
{
|
|
5766
|
-
"version": "0.10.0",
|
|
5767
|
-
"summary": "**Added** Collapsible nav items with `children` array and `NavSubItem` type"
|
|
5768
|
-
},
|
|
5769
|
-
{
|
|
5770
|
-
"version": "0.1.1",
|
|
5771
|
-
"summary": "**Changed** Decoupled from Next.js via LinkProvider"
|
|
5772
|
-
},
|
|
5773
5861
|
{
|
|
5774
5862
|
"version": "0.1.0",
|
|
5775
5863
|
"summary": "**Added** Initial release"
|
|
@@ -6091,7 +6179,7 @@
|
|
|
6091
6179
|
"Radix Slider primitive — keyboard navigation (arrow keys, Home/End, PageUp/PageDown) pre-wired.",
|
|
6092
6180
|
"**Value is always an array** — single-thumb: `[50]`; range: `[25, 75]`. Don't pass a plain number.",
|
|
6093
6181
|
"**Multi-thumb range:** Pass `[start, end]` — renders two thumbs that can cross each other by default. Use `minStepsBetweenThumbs` to enforce a gap.",
|
|
6094
|
-
"**FormField:** Slider
|
|
6182
|
+
"**FormField:** Slider consumes FormField for a11y wiring (`aria-invalid` / `aria-describedby` / `aria-required`) but renders no visual validation treatment — values are valid by construction, so there's no error UX to hand-wire.",
|
|
6095
6183
|
"**No label pairing via Label** — use `aria-label` or `aria-labelledby` directly on the Slider. The thumb is the focusable/labeled element.",
|
|
6096
6184
|
"Not portal-rendered — inline; overflow rules of parents apply."
|
|
6097
6185
|
]
|
|
@@ -6107,7 +6195,7 @@
|
|
|
6107
6195
|
"gotchas": [
|
|
6108
6196
|
"value is number[] (array), not a single number",
|
|
6109
6197
|
"Multi-thumb: Pass array `defaultValue={[25, 75]}` for range sliders — renders one thumb per value",
|
|
6110
|
-
"Slider
|
|
6198
|
+
"Slider consumes FormField for a11y wiring (aria-invalid/describedby/required) but shows no validation visuals by design — don't hand-wire what it already does"
|
|
6111
6199
|
],
|
|
6112
6200
|
"changes": [
|
|
6113
6201
|
{
|
|
@@ -6237,9 +6325,9 @@
|
|
|
6237
6325
|
"composition": {
|
|
6238
6326
|
"notes": [
|
|
6239
6327
|
"**Two-in-one button:** visually unified `[Action | ▼]` with the left half being the primary click and the right half opening a dropdown. Use for actions that have a most-common choice plus alternatives (Save vs. Save-As-Draft, Send vs. Schedule).",
|
|
6240
|
-
"**
|
|
6328
|
+
"**Composes the DS Popover internally** and shares the `color` type + a `variant`/`size` subset with Button (currently `solid`/`soft`/`outline` × the Button colors; no `ghost`/`link`/`lg`). Note: the half styling is implemented locally, not inherited from `Button` — a few Button niceties (e.g. `solid`'s `hover:shadow-brand`) don't apply. Popover placement via `top-end` default suits most top-of-page toolbars.",
|
|
6241
6329
|
"**Dropdown content is consumer-provided** — pass any JSX via `dropdownContent` (typically a DropdownMenu, list of actions, a custom panel, or a small form). Don't try to shove a full-featured menu into the chevron; keep it focused on 2–5 alternatives.",
|
|
6242
|
-
"**ButtonGroup
|
|
6330
|
+
"**ButtonGroup:** SplitButton does NOT consume `ButtonGroup` context — set its `variant`/`color`/`size` explicitly to match a surrounding group.",
|
|
6243
6331
|
"**Controlled dropdown:** Pass `open` + `onOpenChange` for controlled state; omit for uncontrolled. Useful when the dropdown must close programmatically after a selection."
|
|
6244
6332
|
]
|
|
6245
6333
|
},
|
|
@@ -6251,7 +6339,7 @@
|
|
|
6251
6339
|
"changes": [
|
|
6252
6340
|
{
|
|
6253
6341
|
"version": "0.44.2",
|
|
6254
|
-
"summary": "**Fixed** The dropdown is now keyboard-accessible. It previously used a hand-rolled floating panel (`role=\"menu\"`) with no focus management, arrow keys, or Escape — keyboard users couldn't reach or dismiss it. It now composes the DS **Popover** primitive: focus moves in on open, Escape and outside-click close, focus returns to the trigger, and on mobile it opens as a bottom sheet.
|
|
6342
|
+
"summary": "**Fixed** The dropdown is now keyboard-accessible. It previously used a hand-rolled floating panel (`role=\"menu\"`) with no focus management, arrow keys, or Escape — keyboard users couldn't reach or dismiss it. It now composes the DS **Popover** primitive: focus moves in on open, Escape and outside-click close, focus returns to the trigger, and on mobile it opens as a bottom sheet."
|
|
6255
6343
|
},
|
|
6256
6344
|
{
|
|
6257
6345
|
"version": "0.33.0",
|
|
@@ -8486,6 +8574,20 @@
|
|
|
8486
8574
|
},
|
|
8487
8575
|
"required": false
|
|
8488
8576
|
},
|
|
8577
|
+
"totalCount": {
|
|
8578
|
+
"type": {
|
|
8579
|
+
"name": "number"
|
|
8580
|
+
},
|
|
8581
|
+
"required": false,
|
|
8582
|
+
"description": "optional — total selectable items; enables \"Select all\""
|
|
8583
|
+
},
|
|
8584
|
+
"onSelectAll": {
|
|
8585
|
+
"type": {
|
|
8586
|
+
"name": "function",
|
|
8587
|
+
"raw": "() => void (optional — called by the \"Select all\" control)"
|
|
8588
|
+
},
|
|
8589
|
+
"required": false
|
|
8590
|
+
},
|
|
8489
8591
|
"className": {
|
|
8490
8592
|
"type": {
|
|
8491
8593
|
"name": "string"
|
|
@@ -8514,10 +8616,10 @@
|
|
|
8514
8616
|
"icon": {
|
|
8515
8617
|
"type": {
|
|
8516
8618
|
"name": "object",
|
|
8517
|
-
"raw": "
|
|
8619
|
+
"raw": "IconInput"
|
|
8518
8620
|
},
|
|
8519
8621
|
"required": false,
|
|
8520
|
-
"description": "optional icon component"
|
|
8622
|
+
"description": "optional — any icon component or element"
|
|
8521
8623
|
},
|
|
8522
8624
|
"onClick": {
|
|
8523
8625
|
"type": {
|
|
@@ -8530,17 +8632,44 @@
|
|
|
8530
8632
|
"type": {
|
|
8531
8633
|
"name": "enum",
|
|
8532
8634
|
"value": [
|
|
8533
|
-
"
|
|
8534
|
-
"error"
|
|
8635
|
+
"accent",
|
|
8636
|
+
"error",
|
|
8637
|
+
"success",
|
|
8638
|
+
"warning",
|
|
8639
|
+
"info",
|
|
8640
|
+
"neutral"
|
|
8535
8641
|
]
|
|
8536
8642
|
},
|
|
8537
|
-
"required": false
|
|
8643
|
+
"required": false,
|
|
8644
|
+
"defaultValue": "accent"
|
|
8538
8645
|
},
|
|
8539
8646
|
"disabled": {
|
|
8540
8647
|
"type": {
|
|
8541
8648
|
"name": "boolean"
|
|
8542
8649
|
},
|
|
8543
|
-
"required": false
|
|
8650
|
+
"required": false,
|
|
8651
|
+
"description": "optional"
|
|
8652
|
+
},
|
|
8653
|
+
"loading": {
|
|
8654
|
+
"type": {
|
|
8655
|
+
"name": "boolean"
|
|
8656
|
+
},
|
|
8657
|
+
"required": false,
|
|
8658
|
+
"description": "optional — pending spinner on the action"
|
|
8659
|
+
},
|
|
8660
|
+
"requiresConfirmation": {
|
|
8661
|
+
"type": {
|
|
8662
|
+
"name": "boolean"
|
|
8663
|
+
},
|
|
8664
|
+
"required": false,
|
|
8665
|
+
"description": "optional — inline confirm before executing"
|
|
8666
|
+
},
|
|
8667
|
+
"confirmMessage": {
|
|
8668
|
+
"type": {
|
|
8669
|
+
"name": "string"
|
|
8670
|
+
},
|
|
8671
|
+
"required": false,
|
|
8672
|
+
"description": "optional — default \"Are you sure?\""
|
|
8544
8673
|
}
|
|
8545
8674
|
}
|
|
8546
8675
|
}
|
|
@@ -9809,9 +9938,30 @@
|
|
|
9809
9938
|
"onReset": {
|
|
9810
9939
|
"type": {
|
|
9811
9940
|
"name": "function",
|
|
9812
|
-
"raw": "() => void (optional
|
|
9941
|
+
"raw": "() => void (optional — renders a \"Try Again\" button)"
|
|
9813
9942
|
},
|
|
9814
9943
|
"required": false
|
|
9944
|
+
},
|
|
9945
|
+
"actions": {
|
|
9946
|
+
"type": {
|
|
9947
|
+
"name": "ReactNode"
|
|
9948
|
+
},
|
|
9949
|
+
"required": false,
|
|
9950
|
+
"description": "optional — custom recovery actions; replaces the default button"
|
|
9951
|
+
},
|
|
9952
|
+
"fullPage": {
|
|
9953
|
+
"type": {
|
|
9954
|
+
"name": "boolean"
|
|
9955
|
+
},
|
|
9956
|
+
"required": false,
|
|
9957
|
+
"defaultValue": "true — center in a min-h-[60vh] region; false = inline"
|
|
9958
|
+
},
|
|
9959
|
+
"autoFocusReset": {
|
|
9960
|
+
"type": {
|
|
9961
|
+
"name": "boolean"
|
|
9962
|
+
},
|
|
9963
|
+
"required": false,
|
|
9964
|
+
"defaultValue": "false — focus the recovery button on mount"
|
|
9815
9965
|
}
|
|
9816
9966
|
},
|
|
9817
9967
|
"composition": {
|
|
@@ -9824,6 +9974,48 @@
|
|
|
9824
9974
|
]
|
|
9825
9975
|
},
|
|
9826
9976
|
"docPath": "docs/components/composed/error-boundary.md",
|
|
9977
|
+
"subComponents": {
|
|
9978
|
+
"ErrorBoundary": {
|
|
9979
|
+
"props": {
|
|
9980
|
+
"children": {
|
|
9981
|
+
"type": {
|
|
9982
|
+
"name": "ReactNode"
|
|
9983
|
+
},
|
|
9984
|
+
"required": true
|
|
9985
|
+
},
|
|
9986
|
+
"onReset": {
|
|
9987
|
+
"type": {
|
|
9988
|
+
"name": "function",
|
|
9989
|
+
"raw": "() => void (optional — called after the boundary resets)"
|
|
9990
|
+
},
|
|
9991
|
+
"required": false
|
|
9992
|
+
},
|
|
9993
|
+
"onError": {
|
|
9994
|
+
"type": {
|
|
9995
|
+
"name": "function",
|
|
9996
|
+
"raw": "(error: unknown, info: React.ErrorInfo) => void (optional — wire Sentry/logging)"
|
|
9997
|
+
},
|
|
9998
|
+
"required": false
|
|
9999
|
+
},
|
|
10000
|
+
"resetKeys": {
|
|
10001
|
+
"type": {
|
|
10002
|
+
"name": "object",
|
|
10003
|
+
"raw": "unknown[]"
|
|
10004
|
+
},
|
|
10005
|
+
"required": false,
|
|
10006
|
+
"description": "optional — auto-reset when any value changes; react-error-boundary parity"
|
|
10007
|
+
},
|
|
10008
|
+
"fallback": {
|
|
10009
|
+
"type": {
|
|
10010
|
+
"name": "function",
|
|
10011
|
+
"raw": "(props: { error: unknown; onReset: () => void }) => ReactNode (optional — defaults to ErrorDisplay)"
|
|
10012
|
+
},
|
|
10013
|
+
"required": false
|
|
10014
|
+
}
|
|
10015
|
+
},
|
|
10016
|
+
"note": "class boundary — wrap a subtree"
|
|
10017
|
+
}
|
|
10018
|
+
},
|
|
9827
10019
|
"examples": [
|
|
9828
10020
|
"<ErrorDisplay error={error} onReset={() => refetch()} />"
|
|
9829
10021
|
],
|
|
@@ -10496,9 +10688,31 @@
|
|
|
10496
10688
|
"raw": "string | null"
|
|
10497
10689
|
},
|
|
10498
10690
|
"required": false,
|
|
10499
|
-
"description": "
|
|
10691
|
+
"description": "CONTROLLED selected item id; omit for uncontrolled",
|
|
10500
10692
|
"defaultValue": "{null}"
|
|
10501
10693
|
},
|
|
10694
|
+
"defaultSelected": {
|
|
10695
|
+
"type": {
|
|
10696
|
+
"name": "union",
|
|
10697
|
+
"raw": "string | null"
|
|
10698
|
+
},
|
|
10699
|
+
"required": false,
|
|
10700
|
+
"description": "uncontrolled initial selection"
|
|
10701
|
+
},
|
|
10702
|
+
"onSelect": {
|
|
10703
|
+
"type": {
|
|
10704
|
+
"name": "function",
|
|
10705
|
+
"raw": "(value: string) => void (called with a row's `value` when chosen)"
|
|
10706
|
+
},
|
|
10707
|
+
"required": false
|
|
10708
|
+
},
|
|
10709
|
+
"label": {
|
|
10710
|
+
"type": {
|
|
10711
|
+
"name": "string"
|
|
10712
|
+
},
|
|
10713
|
+
"required": false,
|
|
10714
|
+
"description": "accessible name for the listbox; default \"Items\""
|
|
10715
|
+
},
|
|
10502
10716
|
"onBack": {
|
|
10503
10717
|
"type": {
|
|
10504
10718
|
"name": "function",
|
|
@@ -10526,6 +10740,20 @@
|
|
|
10526
10740
|
"required": false,
|
|
10527
10741
|
"description": "below this, stacked mobile mode activates",
|
|
10528
10742
|
"defaultValue": "md"
|
|
10743
|
+
},
|
|
10744
|
+
"emptyState": {
|
|
10745
|
+
"type": {
|
|
10746
|
+
"name": "ReactNode"
|
|
10747
|
+
},
|
|
10748
|
+
"required": false,
|
|
10749
|
+
"description": "shown in the detail pane when nothing is selected"
|
|
10750
|
+
},
|
|
10751
|
+
"onNavigate": {
|
|
10752
|
+
"type": {
|
|
10753
|
+
"name": "function",
|
|
10754
|
+
"raw": "(direction: \"up\" | \"down\") => void"
|
|
10755
|
+
},
|
|
10756
|
+
"required": false
|
|
10529
10757
|
}
|
|
10530
10758
|
},
|
|
10531
10759
|
"composition": {
|
|
@@ -10546,12 +10774,19 @@
|
|
|
10546
10774
|
"subComponents": {
|
|
10547
10775
|
"MasterDetail.ListItem": {
|
|
10548
10776
|
"props": {
|
|
10777
|
+
"value": {
|
|
10778
|
+
"type": {
|
|
10779
|
+
"name": "string"
|
|
10780
|
+
},
|
|
10781
|
+
"required": false,
|
|
10782
|
+
"description": "row id — enables derived selection + auto-fires onSelect on activate"
|
|
10783
|
+
},
|
|
10549
10784
|
"active": {
|
|
10550
10785
|
"type": {
|
|
10551
10786
|
"name": "boolean"
|
|
10552
10787
|
},
|
|
10553
10788
|
"required": false,
|
|
10554
|
-
"description": "
|
|
10789
|
+
"description": "explicit highlight; omit to derive from value === selected"
|
|
10555
10790
|
}
|
|
10556
10791
|
}
|
|
10557
10792
|
}
|
|
@@ -10939,9 +11174,9 @@
|
|
|
10939
11174
|
"notes": [
|
|
10940
11175
|
"**Full-page skeleton layouts** for route-level loading states. Each mimics a common page shape (dashboard tiles, project list with filters, task detail with sidebar).",
|
|
10941
11176
|
"**Server-safe** — use in Next.js app router `loading.tsx` files for instant route-transition feedback while data streams.",
|
|
10942
|
-
"**
|
|
11177
|
+
"**Assembled from `ui/Skeleton`** — these compose the base `Skeleton` primitive directly into page-shaped layouts (they do NOT wrap the `LoadingSkeleton` regional exports). Each root is a `role=\"status\"` / `aria-busy` region with an sr-only label.",
|
|
10943
11178
|
"**When to use which skeleton tier:** - `<Skeleton>` (ui) — single shape for a single element - `<CardSkeleton>` / `<TableSkeleton>` (LoadingSkeleton) — individual region shape - `<DashboardSkeleton>` / etc. (PageSkeletons) — full page placeholder",
|
|
10944
|
-
"**Fixed layout structure** — the className prop adjusts the outer container, but internal layout isn't customizable. For custom page skeletons, compose LoadingSkeleton
|
|
11179
|
+
"**Fixed layout structure** — the className prop adjusts the outer container, but internal layout isn't customizable. For custom page skeletons, compose `ui/Skeleton` (or the `LoadingSkeleton` regional exports) yourself."
|
|
10945
11180
|
]
|
|
10946
11181
|
},
|
|
10947
11182
|
"docPath": "docs/components/composed/page-skeletons.md",
|
|
@@ -10968,7 +11203,7 @@
|
|
|
10968
11203
|
"displayName": "PriorityIndicator",
|
|
10969
11204
|
"tier": "composed",
|
|
10970
11205
|
"import": "@devalok/shilp-sutra/composed/priority-indicator",
|
|
10971
|
-
"serverSafe":
|
|
11206
|
+
"serverSafe": false,
|
|
10972
11207
|
"description": "",
|
|
10973
11208
|
"props": {
|
|
10974
11209
|
"priority": {
|
|
@@ -10978,6 +11213,13 @@
|
|
|
10978
11213
|
},
|
|
10979
11214
|
"required": false
|
|
10980
11215
|
},
|
|
11216
|
+
"iconOnly": {
|
|
11217
|
+
"type": {
|
|
11218
|
+
"name": "boolean"
|
|
11219
|
+
},
|
|
11220
|
+
"required": false,
|
|
11221
|
+
"description": "icon-only chip, no visible text"
|
|
11222
|
+
},
|
|
10981
11223
|
"display": {
|
|
10982
11224
|
"type": {
|
|
10983
11225
|
"name": "enum",
|
|
@@ -10987,31 +11229,41 @@
|
|
|
10987
11229
|
]
|
|
10988
11230
|
},
|
|
10989
11231
|
"required": false,
|
|
10990
|
-
"
|
|
11232
|
+
"description": "@deprecated — use iconOnly"
|
|
11233
|
+
},
|
|
11234
|
+
"children": {
|
|
11235
|
+
"type": {
|
|
11236
|
+
"name": "ReactNode"
|
|
11237
|
+
},
|
|
11238
|
+
"required": false,
|
|
11239
|
+
"description": "override the label, e.g. i18n"
|
|
10991
11240
|
}
|
|
10992
11241
|
},
|
|
10993
11242
|
"composition": {
|
|
10994
11243
|
"notes": [
|
|
10995
|
-
"**
|
|
11244
|
+
"**Composes `Badge`** — radius, color semantics, a11y labelling, and reduced-motion handling all come from one place (no bespoke re-roll).",
|
|
10996
11245
|
"**Composes inside list rows, DataTable cells, Card headers, task panels** — anywhere a priority flag fits.",
|
|
10997
|
-
"
|
|
10998
|
-
"**
|
|
10999
|
-
"
|
|
11246
|
+
"**`iconOnly`** shows only the icon with a real accessible name (`role=\"img\"` + `aria-label`), for tight cells. Omit it (default) for icon + label.",
|
|
11247
|
+
"**Severity by weight, not motion** — URGENT renders as a solid fill so the top tier reads at a glance; the others are soft. No animation (removes the prior perpetual pulse).",
|
|
11248
|
+
"**Case-insensitive priority** — accepts both UPPERCASE and lowercase; unknown values fall back to MEDIUM instead of throwing.",
|
|
11249
|
+
"**`children`** overrides the label for i18n / custom copy.",
|
|
11250
|
+
"Color semantics: LOW = slate (neutral), MEDIUM = warning, HIGH = error (soft), URGENT = error (solid)."
|
|
11000
11251
|
]
|
|
11001
11252
|
},
|
|
11002
11253
|
"docPath": "docs/components/composed/priority-indicator.md",
|
|
11003
|
-
"defaults": {
|
|
11004
|
-
"display": "full"
|
|
11005
|
-
},
|
|
11006
11254
|
"examples": [
|
|
11007
|
-
"<PriorityIndicator priority=\"HIGH\" />\n<PriorityIndicator priority=\"low\"
|
|
11255
|
+
"<PriorityIndicator priority=\"HIGH\" />\n<PriorityIndicator priority=\"low\" iconOnly />\n<PriorityIndicator priority=\"URGENT\">Critical</PriorityIndicator>"
|
|
11008
11256
|
],
|
|
11009
11257
|
"gotchas": [
|
|
11010
|
-
"Case-insensitive — \"low\" and \"LOW\" both work",
|
|
11011
|
-
"
|
|
11012
|
-
"`
|
|
11258
|
+
"Case-insensitive — \"low\" and \"LOW\" both work; unknown values fall back to MEDIUM",
|
|
11259
|
+
"`iconOnly` shows only the icon (accessible-named); default shows icon + text label",
|
|
11260
|
+
"`display` is deprecated — use `iconOnly`"
|
|
11013
11261
|
],
|
|
11014
11262
|
"changes": [
|
|
11263
|
+
{
|
|
11264
|
+
"version": "0.53.0",
|
|
11265
|
+
"summary": "**Changed** Recomposed on the `Badge` primitive (was a bespoke re-rolled chip): inherits pill radius, color semantics, accessible labelling."
|
|
11266
|
+
},
|
|
11015
11267
|
{
|
|
11016
11268
|
"version": "0.2.0",
|
|
11017
11269
|
"summary": "**Added** Identified as server-safe component"
|
|
@@ -11193,7 +11445,7 @@
|
|
|
11193
11445
|
"onSubmit": {
|
|
11194
11446
|
"type": {
|
|
11195
11447
|
"name": "function",
|
|
11196
|
-
"raw": "(
|
|
11448
|
+
"raw": "(message: RichChatInputMessage) => void (REQUIRED)"
|
|
11197
11449
|
},
|
|
11198
11450
|
"required": false
|
|
11199
11451
|
},
|
|
@@ -11211,24 +11463,27 @@
|
|
|
11211
11463
|
"required": false,
|
|
11212
11464
|
"defaultValue": false
|
|
11213
11465
|
},
|
|
11466
|
+
"content": {
|
|
11467
|
+
"type": {
|
|
11468
|
+
"name": "object",
|
|
11469
|
+
"raw": "string — initial HTML"
|
|
11470
|
+
},
|
|
11471
|
+
"required": false,
|
|
11472
|
+
"description": "not reactive; use for message editing"
|
|
11473
|
+
},
|
|
11214
11474
|
"variant": {
|
|
11215
11475
|
"type": {
|
|
11216
11476
|
"name": "enum",
|
|
11217
11477
|
"value": [
|
|
11218
11478
|
"compact",
|
|
11219
11479
|
"expanded",
|
|
11220
|
-
"minimal"
|
|
11480
|
+
"minimal",
|
|
11481
|
+
"inline"
|
|
11221
11482
|
]
|
|
11222
11483
|
},
|
|
11223
11484
|
"required": false,
|
|
11224
11485
|
"defaultValue": "compact"
|
|
11225
11486
|
},
|
|
11226
|
-
"maxRows": {
|
|
11227
|
-
"type": {
|
|
11228
|
-
"name": "number"
|
|
11229
|
-
},
|
|
11230
|
-
"required": false
|
|
11231
|
-
},
|
|
11232
11487
|
"enterBehavior": {
|
|
11233
11488
|
"type": {
|
|
11234
11489
|
"name": "enum",
|
|
@@ -11247,6 +11502,19 @@
|
|
|
11247
11502
|
},
|
|
11248
11503
|
"required": false
|
|
11249
11504
|
},
|
|
11505
|
+
"charCountDisplay": {
|
|
11506
|
+
"type": {
|
|
11507
|
+
"name": "enum",
|
|
11508
|
+
"value": [
|
|
11509
|
+
"always",
|
|
11510
|
+
"focus",
|
|
11511
|
+
"near-limit",
|
|
11512
|
+
"hidden"
|
|
11513
|
+
]
|
|
11514
|
+
},
|
|
11515
|
+
"required": false,
|
|
11516
|
+
"defaultValue": "near-limit"
|
|
11517
|
+
},
|
|
11250
11518
|
"mentions": {
|
|
11251
11519
|
"type": {
|
|
11252
11520
|
"name": "object",
|
|
@@ -11289,6 +11557,34 @@
|
|
|
11289
11557
|
},
|
|
11290
11558
|
"required": false
|
|
11291
11559
|
},
|
|
11560
|
+
"onVoiceRecord": {
|
|
11561
|
+
"type": {
|
|
11562
|
+
"name": "function",
|
|
11563
|
+
"raw": "(audio: Blob, duration: number) => void"
|
|
11564
|
+
},
|
|
11565
|
+
"required": false
|
|
11566
|
+
},
|
|
11567
|
+
"onTranscribe": {
|
|
11568
|
+
"type": {
|
|
11569
|
+
"name": "function",
|
|
11570
|
+
"raw": "(blob: Blob, duration: number) => Promise<string | null> — transcribe after recording; return null to attach as a voice note"
|
|
11571
|
+
},
|
|
11572
|
+
"required": false
|
|
11573
|
+
},
|
|
11574
|
+
"maxDuration": {
|
|
11575
|
+
"type": {
|
|
11576
|
+
"name": "object",
|
|
11577
|
+
"raw": "number — max voice-recording seconds"
|
|
11578
|
+
},
|
|
11579
|
+
"required": false
|
|
11580
|
+
},
|
|
11581
|
+
"replyTo": {
|
|
11582
|
+
"type": {
|
|
11583
|
+
"name": "function",
|
|
11584
|
+
"raw": "{ id: string; author: string; preview: string; onDismiss: () => void } — reply banner above the input"
|
|
11585
|
+
},
|
|
11586
|
+
"required": false
|
|
11587
|
+
},
|
|
11292
11588
|
"onTyping": {
|
|
11293
11589
|
"type": {
|
|
11294
11590
|
"name": "function",
|
|
@@ -11339,16 +11635,50 @@
|
|
|
11339
11635
|
"toolbar": {
|
|
11340
11636
|
"type": {
|
|
11341
11637
|
"name": "union",
|
|
11342
|
-
"raw": "boolean | ChatToolbarItem[]"
|
|
11638
|
+
"raw": "boolean | ChatToolbarItem[] | ReactNode (default: true) — true = default toolbar, array = whitelist, ReactNode = custom, false = hidden"
|
|
11639
|
+
},
|
|
11640
|
+
"required": false
|
|
11641
|
+
},
|
|
11642
|
+
"actionButton": {
|
|
11643
|
+
"type": {
|
|
11644
|
+
"name": "ReactNode"
|
|
11343
11645
|
},
|
|
11344
11646
|
"required": false,
|
|
11345
|
-
"
|
|
11647
|
+
"description": "replaces the default attach button; false hides it"
|
|
11648
|
+
},
|
|
11649
|
+
"emojiSet": {
|
|
11650
|
+
"type": {
|
|
11651
|
+
"name": "enum",
|
|
11652
|
+
"value": [
|
|
11653
|
+
"native",
|
|
11654
|
+
"apple",
|
|
11655
|
+
"google",
|
|
11656
|
+
"twitter",
|
|
11657
|
+
"facebook"
|
|
11658
|
+
]
|
|
11659
|
+
},
|
|
11660
|
+
"required": false,
|
|
11661
|
+
"defaultValue": "native"
|
|
11662
|
+
},
|
|
11663
|
+
"onSchedule": {
|
|
11664
|
+
"type": {
|
|
11665
|
+
"name": "function",
|
|
11666
|
+
"raw": "(message: RichChatInputMessage, scheduledAt: Date) => void — if set, a schedule button appears next to send"
|
|
11667
|
+
},
|
|
11668
|
+
"required": false
|
|
11669
|
+
},
|
|
11670
|
+
"sendOptions": {
|
|
11671
|
+
"type": {
|
|
11672
|
+
"name": "function",
|
|
11673
|
+
"raw": "Array<{ label: string; icon?: ComponentType<{ className?: string }>; onSelect: () => void }> — split-send dropdown options"
|
|
11674
|
+
},
|
|
11675
|
+
"required": false
|
|
11346
11676
|
}
|
|
11347
11677
|
}
|
|
11348
11678
|
}
|
|
11349
11679
|
},
|
|
11350
11680
|
"examples": [
|
|
11351
|
-
"<RichChatInput\n onSubmit={(
|
|
11681
|
+
"<RichChatInput\n onSubmit={(message) => sendMessage(message.html)}\n mentions={teamMembers}\n onFileUpload={uploadFile}\n slashCommands={[{ label: 'Actions', commands: [...] }]}\n/>\n\n<RichChatInput\n variant=\"expanded\"\n onSubmit={handleSubmit}\n maxLength={2000}\n disclaimer=\"AI-generated content may be inaccurate.\"\n/>\n\n<RichChatInput\n variant=\"minimal\"\n enterBehavior=\"newline\"\n onSubmit={handleReply}\n/>"
|
|
11352
11682
|
],
|
|
11353
11683
|
"gotchas": [
|
|
11354
11684
|
"Tiptap is bundled — no need to install `@tiptap/*` packages separately",
|
|
@@ -11596,13 +11926,55 @@
|
|
|
11596
11926
|
"required": false,
|
|
11597
11927
|
"description": "minutes, default: 30",
|
|
11598
11928
|
"defaultValue": 30
|
|
11929
|
+
},
|
|
11930
|
+
"selectedEventId": {
|
|
11931
|
+
"type": {
|
|
11932
|
+
"name": "string"
|
|
11933
|
+
},
|
|
11934
|
+
"required": false,
|
|
11935
|
+
"description": "rings the active event"
|
|
11936
|
+
},
|
|
11937
|
+
"renderEvent": {
|
|
11938
|
+
"type": {
|
|
11939
|
+
"name": "function",
|
|
11940
|
+
"raw": "(event) => ReactNode (custom event body)"
|
|
11941
|
+
},
|
|
11942
|
+
"required": false
|
|
11943
|
+
},
|
|
11944
|
+
"header": {
|
|
11945
|
+
"type": {
|
|
11946
|
+
"name": "ReactNode"
|
|
11947
|
+
},
|
|
11948
|
+
"required": false,
|
|
11949
|
+
"description": "toolbar slot above the grid"
|
|
11950
|
+
},
|
|
11951
|
+
"emptyState": {
|
|
11952
|
+
"type": {
|
|
11953
|
+
"name": "ReactNode"
|
|
11954
|
+
},
|
|
11955
|
+
"required": false,
|
|
11956
|
+
"description": "shown when events is empty"
|
|
11957
|
+
},
|
|
11958
|
+
"height": {
|
|
11959
|
+
"type": {
|
|
11960
|
+
"name": "union",
|
|
11961
|
+
"raw": "number | string"
|
|
11962
|
+
},
|
|
11963
|
+
"required": false,
|
|
11964
|
+
"description": "grid body height, default 480",
|
|
11965
|
+
"defaultValue": 480
|
|
11599
11966
|
}
|
|
11600
11967
|
},
|
|
11601
11968
|
"composition": {
|
|
11602
11969
|
"notes": [
|
|
11603
11970
|
"**Day / Week calendar view** for time-block display (meetings, shifts, availability). Not a full calendar app — no month view, no drag-to-create.",
|
|
11604
11971
|
"**Event data is consumer-owned:** You pass `events` as an array; ScheduleView doesn't fetch, doesn't cache, doesn't expand recurring events. All scheduling logic lives in your app.",
|
|
11605
|
-
"**Event click + slot click** — `onEventClick` for existing events; `onSlotClick` for creating new events (fires with start/end of the empty slot).",
|
|
11972
|
+
"**Event click + slot click** — `onEventClick` for existing events; `onSlotClick` for creating new events (fires with start/end of the empty slot). **Slots are only interactive (focusable + keyboard-navigable) when `onSlotClick` is set** — otherwise they render as inert grid lines, so a read-only schedule adds no keyboard/AT tab stops.",
|
|
11973
|
+
"**Keyboard (interactive slots):** roving tabindex — Arrow keys move between slots (up/down within a day, left/right across days, RTL-aware), Home/End jump within the day; only one slot is in the tab order at a time.",
|
|
11974
|
+
"**Overlapping events** are partitioned into side-by-side columns automatically so double-booked times stay legible.",
|
|
11975
|
+
"**Live now-line** ticks every minute and scrolls into view on mount.",
|
|
11976
|
+
"**`renderEvent`** customizes the event block body; **`header`** adds a toolbar; **`selectedEventId`** rings the active event; **`emptyState`** shows when there are no events.",
|
|
11977
|
+
"**Composes the DS card shell tokens** (`surface-2` + `rounded-surface` + border) and is RTL-safe (logical properties throughout).",
|
|
11606
11978
|
"**Color vocabulary matches the DS** — `accent/success/warning/error/info/neutral`. Map your event types to these at the data layer.",
|
|
11607
11979
|
"**endHour is exclusive:** `endHour=18` means the last visible slot starts at 17:30 (with 30min slots). Match your UX expectation: 9-5 typically means `startHour=9, endHour=18`.",
|
|
11608
11980
|
"**Pairs with date-picker/composed** — use DatePicker or DateRangePicker to choose which date to show; pass that as ScheduleView's `date`."
|
|
@@ -11612,7 +11984,8 @@
|
|
|
11612
11984
|
"defaults": {
|
|
11613
11985
|
"startHour": 8,
|
|
11614
11986
|
"endHour": 18,
|
|
11615
|
-
"slotDuration": 30
|
|
11987
|
+
"slotDuration": 30,
|
|
11988
|
+
"height": 480
|
|
11616
11989
|
},
|
|
11617
11990
|
"examples": [
|
|
11618
11991
|
"<ScheduleView\n view=\"week\"\n date={new Date()}\n events={calendarEvents}\n onEventClick={(e) => openEvent(e.id)}\n/>"
|
|
@@ -11623,6 +11996,10 @@
|
|
|
11623
11996
|
"Events that span outside `startHour`/`endHour` may be clipped"
|
|
11624
11997
|
],
|
|
11625
11998
|
"changes": [
|
|
11999
|
+
{
|
|
12000
|
+
"version": "0.53.0",
|
|
12001
|
+
"summary": "**Changed** Read-only schedules no longer flood the tab order — slots are interactive only when `onSlotClick` is set; otherwise inert grid lines. Interactive slots use roving tabindex + Arrow/Home/End keyboard navigation (RTL-aware)."
|
|
12002
|
+
},
|
|
11626
12003
|
{
|
|
11627
12004
|
"version": "0.49.0",
|
|
11628
12005
|
"summary": "**BREAKING** `ScheduleEvent.color` value `\"primary\"` renamed `\"accent\"` (DS colour vocabulary). It was the default, so untyped events are unaffected."
|
|
@@ -11695,7 +12072,7 @@
|
|
|
11695
12072
|
"notes": [
|
|
11696
12073
|
"**One-liner Tooltip** — wraps TooltipProvider + Tooltip + TooltipTrigger + TooltipContent so consumers don't have to manually compose them for a simple label.",
|
|
11697
12074
|
"**When to use:** 90% of tooltip use cases (icon-only button labels, abbreviated text expansions, secondary info). Use the ui/Tooltip compound for advanced cases (controlled open, nested triggers, custom animations).",
|
|
11698
|
-
"**
|
|
12075
|
+
"**Always mounts its own TooltipProvider** — safe to drop anywhere. Note it does NOT inherit an ancestor `TooltipProvider`'s `delayDuration`; its own `delayDuration` prop (default 300ms) always wins. Set it per-tooltip via the prop.",
|
|
11699
12076
|
"**Content must be inert** — same rule as ui/Tooltip. For interactive popped content, use Popover or HoverCard.",
|
|
11700
12077
|
"**Pairs with IconButton** — the canonical pattern for labeled icon buttons."
|
|
11701
12078
|
]
|
|
@@ -11929,11 +12306,12 @@
|
|
|
11929
12306
|
},
|
|
11930
12307
|
"docPath": "docs/components/shell/app-command-palette.md",
|
|
11931
12308
|
"examples": [
|
|
11932
|
-
"<AppCommandPalette\n user={{ name: 'John', role: '
|
|
12309
|
+
"<AppCommandPalette\n user={{ name: 'John', role: 'Admin' }}\n isAdmin={true}\n onNavigate={(path) => router.push(path)}\n searchResults={results}\n onSearchResultSelect={(r) => router.push(`/${r.entityType}/${r.id}`)}\n/>"
|
|
11933
12310
|
],
|
|
11934
12311
|
"gotchas": [
|
|
11935
12312
|
"Uses CommandRegistry context for page navigation items (see CommandRegistryProvider)",
|
|
11936
12313
|
"`isAdmin` takes precedence over `user.role` for showing admin command groups",
|
|
12314
|
+
"**Role detection is case-sensitive:** `user.role` only auto-enables admin groups when it is exactly `'Admin'` or `'SuperAdmin'`. `'admin'` (lowercase) silently shows nothing — pass `isAdmin` explicitly if your role strings differ.",
|
|
11937
12315
|
"Should be placed at the app root level, typically alongside TopBar"
|
|
11938
12316
|
],
|
|
11939
12317
|
"changes": [
|
|
@@ -11967,7 +12345,7 @@
|
|
|
11967
12345
|
"raw": "BottomNavbarUser | null"
|
|
11968
12346
|
},
|
|
11969
12347
|
"required": false,
|
|
11970
|
-
"description": "optional"
|
|
12348
|
+
"description": "drives per-item role gating, optional"
|
|
11971
12349
|
},
|
|
11972
12350
|
"primaryItems": {
|
|
11973
12351
|
"type": {
|
|
@@ -11983,7 +12361,30 @@
|
|
|
11983
12361
|
"raw": "BottomNavItem[]"
|
|
11984
12362
|
},
|
|
11985
12363
|
"required": false,
|
|
11986
|
-
"description": "overflow items in \"More\"
|
|
12364
|
+
"description": "overflow items in \"More\" sheet, optional"
|
|
12365
|
+
},
|
|
12366
|
+
"indicator": {
|
|
12367
|
+
"type": {
|
|
12368
|
+
"name": "enum",
|
|
12369
|
+
"value": [
|
|
12370
|
+
"pill",
|
|
12371
|
+
"underline",
|
|
12372
|
+
"tint",
|
|
12373
|
+
"none"
|
|
12374
|
+
]
|
|
12375
|
+
},
|
|
12376
|
+
"required": false,
|
|
12377
|
+
"description": "active-item indicator; default 'pill'"
|
|
12378
|
+
},
|
|
12379
|
+
"labelVisibility": {
|
|
12380
|
+
"type": {
|
|
12381
|
+
"name": "enum",
|
|
12382
|
+
"value": [
|
|
12383
|
+
"always",
|
|
12384
|
+
"selected"
|
|
12385
|
+
]
|
|
12386
|
+
},
|
|
12387
|
+
"required": false
|
|
11987
12388
|
},
|
|
11988
12389
|
"className": {
|
|
11989
12390
|
"type": {
|
|
@@ -11994,11 +12395,15 @@
|
|
|
11994
12395
|
},
|
|
11995
12396
|
"composition": {
|
|
11996
12397
|
"notes": [
|
|
11997
|
-
"**Mobile-only bottom nav** — fixed to bottom of viewport. Desktop should use
|
|
11998
|
-
"**Responsive switch pattern:** Use `useIsMobile()` hook to conditionally render
|
|
12398
|
+
"**Mobile-only bottom nav** — fixed to bottom of viewport. Desktop should use Sidebar instead.",
|
|
12399
|
+
"**Responsive switch pattern:** Use `useIsMobile()` hook to conditionally render Sidebar (desktop) or BottomNavbar (mobile). Example: ```jsx const isMobile = useIsMobile() return isMobile ? <BottomNavbar ... /> : <Sidebar ... /> ```",
|
|
11999
12400
|
"**Primary vs overflow:** `primaryItems` (max 4) for the always-visible slots; `moreItems` go into a \"More\" sheet that opens on tap. Don't exceed 4 primary — the bar becomes cramped.",
|
|
12000
12401
|
"**Router integration via LinkProvider:** Each nav item is rendered using the framework-specific Link component registered in LinkProvider. Without LinkProvider, you get full-page reloads on tap.",
|
|
12001
|
-
"**Badge numbers** cap at 99+ (
|
|
12402
|
+
"**Badge numbers** cap at 99+ (composes the `Badge` primitive).",
|
|
12403
|
+
"**Role gating:** each item may declare `roles: string[]` (shown only when `user.role` matches) or a `canView(user)` predicate for arbitrary logic (`canView` wins). Items with neither are always visible. Gating applies to both `primaryItems` and `moreItems`.",
|
|
12404
|
+
"**Overflow sheet:** the \"More\" surface is the DS `Sheet` (`side=\"bottom\"`) — it inherits focus trap, scroll lock, return-focus, and `aria-modal`; the trigger is wired with `aria-haspopup`/`aria-controls` automatically.",
|
|
12405
|
+
"**Indicator (animated):** the active indicator slides to the selected item (shared-element `layoutId`) and fades in on first appearance. Modes: `pill` (default, Material-3 tonal pill behind the icon), `underline` (top accent bar), `tint` (subtle bg on the whole active cell), `none` (no shape — pair with `activeIcon` for the iOS filled-icon look). `labelVisibility=\"selected\"` shows labels only for the active item.",
|
|
12406
|
+
"**Filled-when-active:** set `activeIcon` on an item (e.g. a Tabler `*Filled` variant) to swap the icon for a filled version while it's the active route; falls back to `icon`.",
|
|
12002
12407
|
"**Not for desktop:** The viewport-fixed positioning + touch-optimized sizing don't translate well to desktop. Hide behind `md:hidden`."
|
|
12003
12408
|
]
|
|
12004
12409
|
},
|
|
@@ -12009,10 +12414,14 @@
|
|
|
12009
12414
|
"gotchas": [
|
|
12010
12415
|
"Designed for mobile viewports — fixed to bottom of screen",
|
|
12011
12416
|
"Max 4 `primaryItems` recommended; overflow goes in `moreItems` shown in a \"More\" sheet",
|
|
12012
|
-
"Use with `useIsMobile()` hook to conditionally render instead of
|
|
12417
|
+
"Use with `useIsMobile()` hook to conditionally render instead of Sidebar",
|
|
12013
12418
|
"Requires LinkProvider for framework-specific link components (e.g., Next.js Link)"
|
|
12014
12419
|
],
|
|
12015
12420
|
"changes": [
|
|
12421
|
+
{
|
|
12422
|
+
"version": "0.53.0",
|
|
12423
|
+
"summary": "**Changed** Overflow \"More\" menu re-founded on the DS `Sheet` primitive — inherits focus trap, scroll lock, return-focus, `aria-modal`, and trigger↔panel ARIA wiring (was a hand-rolled `role=\"dialog\"` with none of these). Composes `Badge` for notification counts and the Sheet's built-in close (≥ touch target)."
|
|
12424
|
+
},
|
|
12016
12425
|
{
|
|
12017
12426
|
"version": "0.19.0",
|
|
12018
12427
|
"summary": "**Changed** Background elevated from `bg-surface-1` to `bg-surface-2` for visual hierarchy above app background"
|
|
@@ -12046,7 +12455,7 @@
|
|
|
12046
12455
|
"notes": [
|
|
12047
12456
|
"**Context provider for AppCommandPalette.** Registers page-level navigation items that the command palette surfaces as commands.",
|
|
12048
12457
|
"**Place at app root** — wrap both AppCommandPalette and the rest of the app inside `<CommandRegistryProvider>`. Positioning matters: any AppCommandPalette outside the provider gets `useCommandRegistry() === null` and falls back to minimal functionality.",
|
|
12049
|
-
"**Separation of pages vs adminPages** —
|
|
12458
|
+
"**Separation of pages vs adminPages** — this is an ORGANIZATIONAL split, not access control. The component does NOT enforce anything: YOU populate `adminPages` conditionally (e.g. only when the signed-in user is an admin). Anything you put in `adminPages` is still shipped to the client — do real authorization on the server, not here.",
|
|
12050
12459
|
"**useCommandRegistry()** is the consumer hook — returns the full registry or null. Use in your own command-aware components (e.g. a Spotlight-style keyboard-search embed elsewhere in the app).",
|
|
12051
12460
|
"**Works with LinkProvider** — CommandPaletteItems navigate via `onNavigate` prop on AppCommandPalette, which routes to your framework's Link component."
|
|
12052
12461
|
]
|
|
@@ -12121,7 +12530,7 @@
|
|
|
12121
12530
|
},
|
|
12122
12531
|
"composition": {
|
|
12123
12532
|
"notes": [
|
|
12124
|
-
"**The framework router bridge for all shell components.** Without LinkProvider,
|
|
12533
|
+
"**The framework router bridge for all shell components.** Without LinkProvider, Sidebar / BottomNavbar / TopBar.UserMenu / AppCommandPalette render plain `<a>` tags — that means full page reloads instead of client-side navigation.",
|
|
12125
12534
|
"**Required setup:** ```tsx // Next.js import Link from 'next/link' <LinkProvider component={Link}> <App /> </LinkProvider> ```",
|
|
12126
12535
|
"**Place at app root** — above every shell component that renders nav links.",
|
|
12127
12536
|
"**component must be forwardRef** (Next.js Link, Remix Link, react-router Link all qualify). Custom components need to forward ref + forward className + forward all anchor props.",
|
|
@@ -12144,7 +12553,7 @@
|
|
|
12144
12553
|
}
|
|
12145
12554
|
},
|
|
12146
12555
|
"examples": [
|
|
12147
|
-
"import Link from 'next/link'\n\n<LinkProvider component={Link}>\n <
|
|
12556
|
+
"import Link from 'next/link'\n\n<LinkProvider component={Link}>\n <Sidebar ... />\n <BottomNavbar ... />\n</LinkProvider>"
|
|
12148
12557
|
],
|
|
12149
12558
|
"gotchas": [
|
|
12150
12559
|
"Without LinkProvider, shell components render plain `<a>` tags (full page reloads)",
|
|
@@ -12429,7 +12838,7 @@
|
|
|
12429
12838
|
"**NotificationCenter lives inside TopBar.Right** — it's a complete bell+popover component. Drop it in a TopBar.Section next to other icon buttons.",
|
|
12430
12839
|
"**UserMenu is composable:** `userMenuItems` inserts custom items between the built-in Profile and the color-mode toggle. Each item can navigate (href), run an action (onClick), or show a separator/badge/color decoration.",
|
|
12431
12840
|
"**Responsive hiding:** Actions that shouldn't appear on mobile use `className=\"hidden md:flex\"` on the IconButton — the component doesn't enforce mobile hiding; that's layout responsibility.",
|
|
12432
|
-
"**Pairs with
|
|
12841
|
+
"**Pairs with Sidebar** — desktop app shell is typically `<TopBar>` + `<Sidebar>` + main content region."
|
|
12433
12842
|
]
|
|
12434
12843
|
},
|
|
12435
12844
|
"docPath": "docs/components/shell/top-bar.md",
|