@sableui/react 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/bin/sable-lint.mjs +5 -1
  3. package/dist/{_contract-CkqXDVww.d.ts → _contract-CDa9-NdB.d.ts} +47 -1
  4. package/dist/blocks/wallet-block.js +2 -2
  5. package/dist/components/app-shell/app-shell-frame.js +16 -0
  6. package/dist/components/app-shell/app-shell-main.js +12 -0
  7. package/dist/components/app-shell/app-shell.js +28 -4
  8. package/dist/components/app-shell/app-shell.meta.js +88 -4
  9. package/dist/components/area-chart/area-chart.meta.js +6 -1
  10. package/dist/components/attachment/attachment.meta.js +2 -1
  11. package/dist/components/attachment/attachment.variants.js +1 -1
  12. package/dist/components/badge/badge.meta.js +8 -1
  13. package/dist/components/badge/badge.variants.js +7 -7
  14. package/dist/components/banner/banner.meta.js +6 -1
  15. package/dist/components/banner/banner.variants.js +5 -5
  16. package/dist/components/bar-chart/bar-chart.meta.js +6 -1
  17. package/dist/components/caret-menu/caret-menu.js +5 -6
  18. package/dist/components/chat-composer/chat-composer.meta.js +2 -2
  19. package/dist/components/chat-composer/chat-composer.variants.js +1 -1
  20. package/dist/components/color-field/color-field.js +6 -8
  21. package/dist/components/combobox/combobox.js +27 -5
  22. package/dist/components/combobox/combobox.meta.js +10 -2
  23. package/dist/components/command-menu/command-menu.js +14 -3
  24. package/dist/components/command-menu/command-menu.meta.js +9 -1
  25. package/dist/components/date-picker/date-picker.meta.js +2 -2
  26. package/dist/components/feedback/feedback.js +1 -1
  27. package/dist/components/feedback/feedback.meta.js +2 -1
  28. package/dist/components/gradient-art/gradient-art.js +8 -5
  29. package/dist/components/gradient-art/gradient-art.meta.js +35 -2
  30. package/dist/components/input/input.meta.js +11 -3
  31. package/dist/components/input-group/input-group.js +1 -1
  32. package/dist/components/input-group/input-group.meta.js +1 -1
  33. package/dist/components/line-chart/line-chart.meta.js +6 -1
  34. package/dist/components/menu/menu.js +1 -1
  35. package/dist/components/meter/meter.js +53 -7
  36. package/dist/components/meter/meter.meta.js +51 -4
  37. package/dist/components/meter/meter.variants.js +43 -7
  38. package/dist/components/note/note.meta.js +5 -1
  39. package/dist/components/note/note.variants.js +4 -4
  40. package/dist/components/number-field/number-field.meta.js +2 -2
  41. package/dist/components/otp-field/otp-field.meta.js +2 -2
  42. package/dist/components/panel-group/panel-group.js +5 -8
  43. package/dist/components/pie-chart/pie-chart.meta.js +6 -1
  44. package/dist/components/radar-chart/radar-chart.meta.js +6 -1
  45. package/dist/components/radial-chart/radial-chart.meta.js +6 -1
  46. package/dist/components/search-input/search-input.meta.js +11 -3
  47. package/dist/components/segmented-bar/segmented-bar.meta.js +8 -1
  48. package/dist/components/segmented-bar/segmented-bar.variants.js +7 -7
  49. package/dist/components/select/select.js +1 -1
  50. package/dist/components/select/select.meta.js +2 -2
  51. package/dist/components/sheet/sheet.js +5 -4
  52. package/dist/components/sidebar/sidebar.js +16 -1
  53. package/dist/components/sidebar/sidebar.meta.js +7 -2
  54. package/dist/components/sparkline/sparkline.meta.js +8 -1
  55. package/dist/components/status-dot/status-dot.meta.js +8 -1
  56. package/dist/components/status-dot/status-dot.variants.js +7 -7
  57. package/dist/components/stepper/stepper.meta.js +2 -1
  58. package/dist/components/stepper/stepper.variants.js +1 -1
  59. package/dist/components/table/table.meta.js +4 -4
  60. package/dist/components/textarea/textarea.js +5 -0
  61. package/dist/components/textarea/textarea.meta.js +3 -3
  62. package/dist/file-hashes.json +91 -88
  63. package/dist/foundations/accessibility.js +5 -0
  64. package/dist/index.d.ts +132 -24
  65. package/dist/index.js +9 -1
  66. package/dist/lib/chart/types.js +8 -8
  67. package/dist/lib/chart/use-arrival.js +5 -4
  68. package/dist/lib/field-shell.js +1 -1
  69. package/dist/lib/highlight-glide.js +6 -6
  70. package/dist/lib/scrub-gesture.js +6 -6
  71. package/dist/lib/use-caret-trigger.js +11 -18
  72. package/dist/lib/use-match-highlight.js +69 -0
  73. package/dist/lib/use-smooth-wheel.js +10 -8
  74. package/dist/presets/index.d.ts +13 -2
  75. package/dist/presets/index.js +17 -1
  76. package/dist/styles.css +100 -0
  77. package/dist/{theme-provider-CdSicAad.d.ts → theme-provider-BydfM5Z0.d.ts} +1 -1
  78. package/dist/themes/_contract.js +14 -0
  79. package/dist/themes/atelier/atelier.css +18 -0
  80. package/dist/themes/atelier/index.d.ts +1 -1
  81. package/dist/themes/contrast.js +48 -1
  82. package/dist/themes/ember/ember.css +18 -0
  83. package/dist/themes/ember/index.d.ts +1 -1
  84. package/dist/themes/index.d.ts +2 -2
  85. package/dist/themes/meridian/index.d.ts +1 -1
  86. package/dist/themes/meridian/meridian.css +18 -0
  87. package/dist/themes/poppy/index.d.ts +1 -1
  88. package/dist/themes/poppy/poppy.css +18 -0
  89. package/dist/themes/prism/index.d.ts +1 -1
  90. package/dist/themes/prism/prism.css +18 -0
  91. package/dist/themes/sable/index.d.ts +1 -1
  92. package/dist/themes/sable/sable.css +18 -0
  93. package/dist/themes/verdant/index.d.ts +1 -1
  94. package/dist/themes/verdant/verdant.css +18 -0
  95. package/llms/blocks/wallet-block.md +5 -4
  96. package/llms/components/app-shell.md +72 -3
  97. package/llms/components/area-chart.md +1 -1
  98. package/llms/components/attachment.md +1 -1
  99. package/llms/components/badge.md +1 -1
  100. package/llms/components/banner.md +1 -1
  101. package/llms/components/bar-chart.md +1 -1
  102. package/llms/components/chat-composer.md +1 -1
  103. package/llms/components/combobox.md +2 -1
  104. package/llms/components/command-menu.md +3 -2
  105. package/llms/components/date-picker.md +1 -1
  106. package/llms/components/feedback.md +1 -1
  107. package/llms/components/gradient-art.md +28 -1
  108. package/llms/components/input-group.md +1 -1
  109. package/llms/components/input.md +4 -2
  110. package/llms/components/line-chart.md +1 -1
  111. package/llms/components/meter.md +33 -4
  112. package/llms/components/note.md +1 -1
  113. package/llms/components/number-field.md +1 -1
  114. package/llms/components/otp-field.md +1 -1
  115. package/llms/components/pie-chart.md +1 -1
  116. package/llms/components/radar-chart.md +1 -1
  117. package/llms/components/radial-chart.md +1 -1
  118. package/llms/components/search-input.md +20 -2
  119. package/llms/components/segmented-bar.md +1 -1
  120. package/llms/components/select.md +1 -1
  121. package/llms/components/sidebar.md +3 -2
  122. package/llms/components/sparkline.md +1 -1
  123. package/llms/components/status-dot.md +1 -1
  124. package/llms/components/stepper.md +1 -1
  125. package/llms/components/table.md +2 -2
  126. package/llms/components/textarea.md +2 -2
  127. package/llms/foundations/accessibility.md +1 -0
  128. package/llms/reference/token-intent.md +22 -2
  129. package/llms/reference/utilities.md +5 -2
  130. package/llms-full.txt +222 -49
  131. package/llms.txt +2 -2
  132. package/package.json +1 -1
  133. package/registry.json +396 -57
  134. package/scripts/lint-rules.mjs +6 -3
package/registry.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://sable.design/registry.schema.json",
3
3
  "name": "@sableui/react",
4
- "version": "0.15.0",
4
+ "version": "0.16.0",
5
5
  "description": "Themeable React components, semantic tokens, layout patterns, presets, and package-owned agent skills. Default theme: Sable.",
6
6
  "engine": {
7
7
  "behavior": "@base-ui/react",
@@ -349,7 +349,7 @@
349
349
  {
350
350
  "name": "input",
351
351
  "intent": "The outline of a form control specifically.",
352
- "whenToUse": "Text inputs, textareas and selects. Not the edge of a checkbox, radio or switch — that is `control-border`.",
352
+ "whenToUse": "Text inputs, textareas and selects (through `field-border`, which derives from it). Not the edge of a checkbox, radio or switch — that is `control-border`.",
353
353
  "insteadOf": "`border`. They are often the same value, but a theme is entitled to make form controls read differently from other chrome, and only this token gives it the hook."
354
354
  },
355
355
  {
@@ -1413,6 +1413,103 @@
1413
1413
  "intent": "The edge of a floating surface. Fainter than `border`: the shadow carries the elevation.",
1414
1414
  "whenToUse": "Every floating surface — popover, menu, select, tooltip, dialog, sheet, toast, a floating panel — as `border-border-floating` or `ring-border-floating`, together with `bg-popover` and a `shadow-md`+ shadow. Derived for every theme (a faint alpha of the foreground); a theme may tune it with `--theme-border-floating`.",
1415
1415
  "insteadOf": "`border`. A full hairline plus a shadow stacks into a heavy outline around anything that floats. `border` is for resting edges: inputs, cards, badges."
1416
+ },
1417
+ {
1418
+ "name": "field",
1419
+ "intent": "The fill of a text field: Input, Textarea, Select, Combobox, SearchInput, InputGroup, ChatComposer.",
1420
+ "whenToUse": "Read by every field through its shell, so you rarely name it. Derived for every theme (`card`, an outlined field on the card); a theme fills its fields instead with `--theme-field: var(--muted)` and `--theme-field-border: transparent`, and every field changes at once. Name it only for a field-shaped surface of your own that must match.",
1421
+ "insteadOf": "`card` or `muted` on a hand-built field. A field that paints `card` keeps its outline when the theme fills the rest, and one that paints `muted` stays filled when the theme outlines them.",
1422
+ "pairsWith": [
1423
+ "field-border"
1424
+ ]
1425
+ },
1426
+ {
1427
+ "name": "field-border",
1428
+ "intent": "The outline of a text field. Derived from `input`; `transparent` in a theme with filled fields.",
1429
+ "whenToUse": "With `field`, on the same field-shaped surfaces. Tune it with `--theme-field-border`.",
1430
+ "insteadOf": "`input` on a text field. `input` stays the theme's outline colour for form chrome; this is the field's outline, which a filled theme turns off.",
1431
+ "pairsWith": [
1432
+ "field"
1433
+ ]
1434
+ },
1435
+ {
1436
+ "name": "shell-ground",
1437
+ "intent": "The ground of an inset app frame: the rail and the gap around the raised main panel.",
1438
+ "whenToUse": "Painted by `<AppShell frame=\"inset\">` and the Sidebar in its slot; you rarely name it. Derived for every theme as one step off `sidebar` toward its ink, so the panel reads as lifted even where the rail is the page colour. Tune it with `--theme-shell-ground`.",
1439
+ "insteadOf": "`sidebar` or `canvas` behind an inset panel. `sidebar` is the page colour in most themes, so the panel would sit on itself; `canvas` is a workspace's artboard, not app chrome.",
1440
+ "pairsWith": [
1441
+ "sidebar"
1442
+ ]
1443
+ },
1444
+ {
1445
+ "name": "destructive-mark",
1446
+ "intent": "`destructive` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1447
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-destructive-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-destructive-mark` or gets one derived from `destructive`.",
1448
+ "insteadOf": "`bg-destructive` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-destructive` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1449
+ "pairsWith": [
1450
+ "background",
1451
+ "card"
1452
+ ]
1453
+ },
1454
+ {
1455
+ "name": "success-mark",
1456
+ "intent": "`success` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1457
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-success-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-success-mark` or gets one derived from `success`.",
1458
+ "insteadOf": "`bg-success` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-success` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1459
+ "pairsWith": [
1460
+ "background",
1461
+ "card"
1462
+ ]
1463
+ },
1464
+ {
1465
+ "name": "tone-warning-mark",
1466
+ "intent": "`tone-warning` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1467
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-warning-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-warning-mark` or gets one derived from `tone-warning`.",
1468
+ "insteadOf": "`bg-tone-warning` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-warning` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1469
+ "pairsWith": [
1470
+ "background",
1471
+ "card"
1472
+ ]
1473
+ },
1474
+ {
1475
+ "name": "tone-info-mark",
1476
+ "intent": "`tone-info` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1477
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-info-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-info-mark` or gets one derived from `tone-info`.",
1478
+ "insteadOf": "`bg-tone-info` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-info` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1479
+ "pairsWith": [
1480
+ "background",
1481
+ "card"
1482
+ ]
1483
+ },
1484
+ {
1485
+ "name": "tone-1-mark",
1486
+ "intent": "`tone-1` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1487
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-1-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-1-mark` or gets one derived from `tone-1`.",
1488
+ "insteadOf": "`bg-tone-1` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-1` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1489
+ "pairsWith": [
1490
+ "background",
1491
+ "card"
1492
+ ]
1493
+ },
1494
+ {
1495
+ "name": "tone-2-mark",
1496
+ "intent": "`tone-2` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1497
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-2-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-2-mark` or gets one derived from `tone-2`.",
1498
+ "insteadOf": "`bg-tone-2` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-2` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1499
+ "pairsWith": [
1500
+ "background",
1501
+ "card"
1502
+ ]
1503
+ },
1504
+ {
1505
+ "name": "tone-3-mark",
1506
+ "intent": "`tone-3` at graphic strength: the same hue lifted and saturated, for a mark that carries no text.",
1507
+ "whenToUse": "A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-3-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-3-mark` or gets one derived from `tone-3`.",
1508
+ "insteadOf": "`bg-tone-3` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-3` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.",
1509
+ "pairsWith": [
1510
+ "background",
1511
+ "card"
1512
+ ]
1416
1513
  }
1417
1514
  ],
1418
1515
  "palette": {
@@ -2959,7 +3056,12 @@
2959
3056
  "dock",
2960
3057
  "player bar",
2961
3058
  "now playing",
2962
- "persistent"
3059
+ "persistent",
3060
+ "inset",
3061
+ "inset frame",
3062
+ "floating panel",
3063
+ "rounded content",
3064
+ "scroll container"
2963
3065
  ],
2964
3066
  "usage": {
2965
3067
  "description": "Use AppShell as the outer product frame for authenticated or app-like experiences. It coordinates responsive chrome slots and guarantees a skip link plus main landmark; put route content inside the children and let AppHeader, Sidebar, BottomNav, and Banner own their own semantics.",
@@ -2980,10 +3082,25 @@
2980
3082
  "guidance": "do",
2981
3083
  "description": "Wrap EVERY return of a route in its own Page or Region — including early returns for loading, empty and error states. AppShell's <main> deliberately carries no padding (it is a frame, and padding belongs to the region that chose the width), so a route that returns a bare spinner or error renders flush against the chrome. This is the most common conversion bug: the happy path gets a Page, the three early returns do not."
2982
3084
  },
3085
+ {
3086
+ "guidance": "do",
3087
+ "description": "Use frame=\"inset\" for dense, multi-pane product apps — a CRM, an issue tracker, an AI workspace — where framing the content as one raised panel on the rail's ground helps it read as the workspace and the rail as chrome. Keep the Sidebar on surface=\"rail\" so its tint is the ground. Inset moves the page scroll from the window to <main id=\"main-content\"> on desktop: point scroll listeners, scroll restoration and scroll-to-top at that element, not window."
3088
+ },
2983
3089
  {
2984
3090
  "guidance": "dont",
2985
3091
  "description": "Nest AppShell inside route cards or panels. It is page chrome, not local content."
2986
3092
  },
3093
+ {
3094
+ "guidance": "dont",
3095
+ "description": "Wrap a route in its own h-full overflow-y-auto box inside an inset shell. main is already the page's scroll container; a second one traps the scrollbar inside a smaller box and breaks sticky headers and the skip link's scroll target. Scroll a genuinely separate pane (a list beside a detail view) with Scroller.",
3096
+ "instead": [
3097
+ "Scroller"
3098
+ ]
3099
+ },
3100
+ {
3101
+ "guidance": "dont",
3102
+ "description": "Combine frame=\"inset\" with a full-width header bar above the rail. The inset ground is the rail running the full height of the window; a bar across the top cuts it off. Use the flush frame with Sidebar surface=\"page\" for that layout."
3103
+ },
2987
3104
  {
2988
3105
  "guidance": "dont",
2989
3106
  "description": "Put desktop-only navigation in the mobile header slot or mobile-only controls in the sidebar slot."
@@ -3008,7 +3125,7 @@
3008
3125
  {
3009
3126
  "name": "Main",
3010
3127
  "required": true,
3011
- "description": "The route content landmark with id main-content."
3128
+ "description": "The route content landmark with id main-content. With frame=\"inset\", from lg it is a rounded, bordered panel that scrolls inside itself."
3012
3129
  },
3013
3130
  {
3014
3131
  "name": "Bottom nav",
@@ -3066,6 +3183,12 @@
3066
3183
  "name": "overlays",
3067
3184
  "type": "ReactNode",
3068
3185
  "description": "Floating overlays — a message launcher, FAB, or modal mount points."
3186
+ },
3187
+ {
3188
+ "name": "frame",
3189
+ "type": "\"flush\" | \"inset\"",
3190
+ "default": "\"flush\"",
3191
+ "description": "How the desktop frame (lg and up) holds the content; below lg both are the same mobile layout with page scroll. \"flush\": main sits on the page beside the rail and the document scrolls. \"inset\": the shell fills the viewport and paints the shell-ground token (one step off the rail's surface, tunable with --theme-shell-ground) behind the rail and around the panel; main becomes a rounded-lg panel with a hairline border and shadow-sm, inset by a spacing step from the window edges, that scrolls inside itself (scrollbar-quiet) while the rail stays put. The Sidebar in the sidebar slot drops its right border and fills the row. main stays the #main-content target (tabIndex -1, so the skip link lands focus in the scroller) and the inline-size query container; sticky children stick to the panel's top; banners and the dock stay in flow, so the panel's bottom gap sits above a dock. With Sidebar surface=\"page\" the ground is the page colour and the panel's border alone lifts it."
3069
3192
  }
3070
3193
  ],
3071
3194
  "subcomponents": [
@@ -3079,13 +3202,17 @@
3079
3202
  "background",
3080
3203
  "foreground",
3081
3204
  "primary",
3082
- "primary-foreground"
3205
+ "primary-foreground",
3206
+ "sidebar",
3207
+ "shell-ground",
3208
+ "border"
3083
3209
  ],
3084
3210
  "a11y": [
3085
3211
  "Renders a skip link to #main-content as the first focusable element.",
3086
3212
  "Wraps content in a <main id=\"main-content\"> landmark.",
3087
3213
  "Slot components own their own ARIA (nav landmarks, labels).",
3088
- "The dock follows <main> in DOM order, so keyboard and screen-reader users reach the player after the page content, not before it."
3214
+ "The dock follows <main> in DOM order, so keyboard and screen-reader users reach the player after the page content, not before it.",
3215
+ "With frame=\"inset\", <main> is the desktop scroll container and takes tabIndex -1: the skip link moves focus into it, so PageDown and the arrow keys scroll the content, without adding a tab stop."
3089
3216
  ],
3090
3217
  "examples": [
3091
3218
  {
@@ -3093,6 +3220,11 @@
3093
3220
  "code": "<AppShell\n banners={<Banner tone=\"warning\">Sync is delayed — changes may be slow to appear.</Banner>}\n header={<AppHeader title=\"Studio\" />}\n sidebar={\n <Sidebar>\n <SidebarNav>\n <SidebarItem icon={<Icon name=\"home\" />} label=\"Home\" active render={<Link to=\"/\" />} />\n <SidebarItem icon={<Icon name=\"bell\" />} label=\"Notifications\" render={<Link to=\"/notifications\" />} />\n <SidebarItem icon={<Icon name=\"gear\" />} label=\"Settings\" render={<Link to=\"/settings\" />} />\n </SidebarNav>\n </Sidebar>\n }\n bottomNav={\n <BottomNav>\n <BottomNavItem icon={<Icon name=\"home\" />} label=\"Home\" active render={<Link to=\"/\" />} />\n <BottomNavItem icon={<Icon name=\"bell\" />} label=\"Alerts\" render={<Link to=\"/notifications\" />} />\n </BottomNav>\n }\n>\n <Region max=\"feed\">\n <PageHeader title=\"Home\" description=\"Latest posts from people you follow.\" />\n </Region>\n</AppShell>",
3094
3221
  "imports": "import { AppHeader, AppShell, Banner, BottomNav, BottomNavItem, Icon, PageHeader, Region, Sidebar, SidebarItem, SidebarNav } from \"@sableui/react\"\n// <Link> = your router's link (react-router, next/link, @tanstack/router, …)"
3095
3222
  },
3223
+ {
3224
+ "label": "Inset frame",
3225
+ "code": "<AppShell\n frame=\"inset\"\n header={<AppHeader title=\"Pipeline\" />}\n sidebar={\n <Sidebar>\n <SidebarHeader>\n <SidebarBrand mark={<Icon name=\"gem\" variant=\"solid\" />} label=\"Relay\" render={<Link to=\"/\" />} />\n </SidebarHeader>\n <SidebarNav>\n <SidebarItem icon={<Icon name=\"inbox\" />} label=\"Inbox\" render={<Link to=\"/inbox\" />} />\n <SidebarItem icon={<Icon name=\"user\" />} label=\"People\" active render={<Link to=\"/people\" />} />\n <SidebarItem icon={<Icon name=\"folder\" />} label=\"Companies\" render={<Link to=\"/companies\" />} />\n </SidebarNav>\n </Sidebar>\n }\n bottomNav={\n <BottomNav>\n <BottomNavItem icon={<Icon name=\"inbox\" />} label=\"Inbox\" render={<Link to=\"/inbox\" />} />\n <BottomNavItem icon={<Icon name=\"user\" />} label=\"People\" active render={<Link to=\"/people\" />} />\n <BottomNavItem icon={<Icon name=\"folder\" />} label=\"Companies\" render={<Link to=\"/companies\" />} />\n </BottomNav>\n }\n>\n <Page max=\"wide\" gap={4} className=\"py-6\">\n <PageHeader\n title=\"People\"\n description=\"Everyone in your pipeline, newest first.\"\n actions={<Button><Icon name=\"plus\" />Add person</Button>}\n />\n <Card>\n <CardContent flush>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Company</TableHead>\n <TableHead numeric>Deals</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableRow>\n <TableCell>Ada Lovelace</TableCell>\n <TableCell>Northwind</TableCell>\n <TableCell numeric>4</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>Grace Hopper</TableCell>\n <TableCell>Harbor Labs</TableCell>\n <TableCell numeric>2</TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </Page>\n</AppShell>",
3226
+ "imports": "import { AppHeader, AppShell, BottomNav, BottomNavItem, Button, Card, CardContent, Icon, Page, PageHeader, Sidebar, SidebarBrand, SidebarHeader, SidebarItem, SidebarNav, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"@sableui/react\"\n// <Link> = your router's link (react-router, next/link, @tanstack/router, …)"
3227
+ },
3096
3228
  {
3097
3229
  "label": "SkipLink in a layout of your own",
3098
3230
  "code": "<>\n <SkipLink />\n <header className=\"flex items-center justify-between px-(--page-inset) py-4\">\n <Link to=\"/\">Alder & Lune</Link>\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Search\"><Icon name=\"search\" /></Button>\n </header>\n <main id=\"main-content\" tabIndex={-1}>\n <Region max=\"wide\">\n <PageHeader title=\"Lighting\" />\n </Region>\n </main>\n</>",
@@ -3290,7 +3422,12 @@
3290
3422
  "popover",
3291
3423
  "popover-foreground",
3292
3424
  "foreground",
3293
- "background"
3425
+ "background",
3426
+ "tone-warning-mark",
3427
+ "tone-info-mark",
3428
+ "tone-1-mark",
3429
+ "tone-2-mark",
3430
+ "tone-3-mark"
3294
3431
  ],
3295
3432
  "motion": [
3296
3433
  {
@@ -3498,7 +3635,8 @@
3498
3635
  "destructive",
3499
3636
  "overlay",
3500
3637
  "overlay-foreground",
3501
- "ring"
3638
+ "ring",
3639
+ "destructive-mark"
3502
3640
  ],
3503
3641
  "motion": [
3504
3642
  {
@@ -4016,7 +4154,14 @@
4016
4154
  "tone-info-foreground",
4017
4155
  "success-foreground",
4018
4156
  "tone-warning-foreground",
4019
- "destructive-foreground"
4157
+ "destructive-foreground",
4158
+ "destructive-mark",
4159
+ "success-mark",
4160
+ "tone-warning-mark",
4161
+ "tone-info-mark",
4162
+ "tone-1-mark",
4163
+ "tone-2-mark",
4164
+ "tone-3-mark"
4020
4165
  ],
4021
4166
  "a11y": [
4022
4167
  "Badges are static text by default; do not rely on color alone for meaning.",
@@ -4224,7 +4369,12 @@
4224
4369
  "tone-1",
4225
4370
  "tone-1-foreground",
4226
4371
  "destructive",
4227
- "destructive-foreground"
4372
+ "destructive-foreground",
4373
+ "destructive-mark",
4374
+ "success-mark",
4375
+ "tone-warning-mark",
4376
+ "tone-info-mark",
4377
+ "tone-1-mark"
4228
4378
  ],
4229
4379
  "a11y": [
4230
4380
  "Static banners render as a labelled region (role=region); set `live` to announce dynamic status bars (role=status / role=alert) when they appear or change.",
@@ -4472,7 +4622,12 @@
4472
4622
  "popover",
4473
4623
  "popover-foreground",
4474
4624
  "foreground",
4475
- "background"
4625
+ "background",
4626
+ "tone-warning-mark",
4627
+ "tone-info-mark",
4628
+ "tone-1-mark",
4629
+ "tone-2-mark",
4630
+ "tone-3-mark"
4476
4631
  ],
4477
4632
  "motion": [
4478
4633
  {
@@ -6498,8 +6653,8 @@
6498
6653
  ]
6499
6654
  },
6500
6655
  "tokensUsed": [
6501
- "card",
6502
- "input",
6656
+ "field",
6657
+ "field-border",
6503
6658
  "ring",
6504
6659
  "destructive",
6505
6660
  "foreground",
@@ -7626,6 +7781,12 @@
7626
7781
  "default": "Base UI's locale-aware contains",
7627
7782
  "description": "How items match the query. `null` turns matching off, for items a server already filtered: pair it with `onInputValueChange` to fetch."
7628
7783
  },
7784
+ {
7785
+ "name": "highlightMatches",
7786
+ "type": "boolean",
7787
+ "default": "true",
7788
+ "description": "Paints the typed text wherever it appears in a row's label, on the `highlight` / `highlight-foreground` pair, through the CSS Custom Highlight API — no `<mark>` in the row, and the accessible name is unchanged. Only typed text counts: a field still holding the selected item's label lists everything and lights nothing. A literal, case-insensitive match within the label; a `filter` that matches differently leaves rows it kept unpainted. `false` turns it off."
7789
+ },
7629
7790
  {
7630
7791
  "name": "onInputValueChange",
7631
7792
  "type": "(inputValue: string, eventDetails) => void",
@@ -7693,8 +7854,10 @@
7693
7854
  }
7694
7855
  ],
7695
7856
  "tokensUsed": [
7696
- "input",
7697
- "card",
7857
+ "highlight",
7858
+ "highlight-foreground",
7859
+ "field-border",
7860
+ "field",
7698
7861
  "foreground",
7699
7862
  "muted-foreground",
7700
7863
  "ring",
@@ -7970,6 +8133,12 @@
7970
8133
  "default": "case-insensitive substring match on label",
7971
8134
  "description": "Replaces or disables the built-in match. A function ranks and filters items itself and its order is kept verbatim; null renders items exactly as given. Either also stops declarative CommandMenuItem children self-filtering. The query arrives raw — trimming and case are policy, and this is the prop that hands policy over."
7972
8135
  },
8136
+ {
8137
+ "name": "highlightMatches",
8138
+ "type": "boolean",
8139
+ "default": "true",
8140
+ "description": "Paints the query wherever it appears in a row's label (not its detail or hint), on the `highlight` / `highlight-foreground` pair, through the CSS Custom Highlight API — no `<mark>` in the row, and the accessible name is unchanged. A literal, case-insensitive match, so under a fuzzy `filter` a row that matched as a subsequence keeps an unpainted label. `false` turns it off. Applies to CommandMenuPanel too."
8141
+ },
7973
8142
  {
7974
8143
  "name": "listClassName",
7975
8144
  "type": "string",
@@ -8014,7 +8183,7 @@
8014
8183
  {
8015
8184
  "name": "CommandMenuTrigger",
8016
8185
  "type": "{ onOpen?: () => void; placeholder?: string; shortcut?: string | false; size?: \"sm\" | \"md\"; disabled?: boolean }",
8017
- "description": "The search field in a header that is really a button. Wears SearchInput's shell (border-input, card surface, leading magnifier, muted placeholder) on the control ladder, with a trailing Kbd: ⌘K on macOS, Ctrl K elsewhere. onOpen runs on click and on the shortcut, which it listens for page-wide (useCommandMenuShortcut). shortcut is the key (default \"k\"); false drops both the hint and the listener. size is sm in a header beside small buttons, md (default) beside Input and SearchInput. It sits outside CommandMenu, so the Dialog returns focus to it on close."
8186
+ "description": "The search field in a header that is really a button. Wears SearchInput's shell (the field fill and outline, leading magnifier, muted placeholder) on the control ladder, with a trailing Kbd: ⌘K on macOS, Ctrl K elsewhere. onOpen runs on click and on the shortcut, which it listens for page-wide (useCommandMenuShortcut). shortcut is the key (default \"k\"); false drops both the hint and the listener. size is sm in a header beside small buttons, md (default) beside Input and SearchInput. It sits outside CommandMenu, so the Dialog returns focus to it on close."
8018
8187
  },
8019
8188
  {
8020
8189
  "name": "useCommandMenuShortcut",
@@ -8038,6 +8207,8 @@
8038
8207
  }
8039
8208
  ],
8040
8209
  "tokensUsed": [
8210
+ "highlight",
8211
+ "highlight-foreground",
8041
8212
  "card",
8042
8213
  "card-foreground",
8043
8214
  "border",
@@ -8960,8 +9131,8 @@
8960
9131
  "popover",
8961
9132
  "popover-foreground",
8962
9133
  "border",
8963
- "input",
8964
- "card",
9134
+ "field-border",
9135
+ "field",
8965
9136
  "ring"
8966
9137
  ],
8967
9138
  "a11y": [
@@ -10202,7 +10373,8 @@
10202
10373
  "accent",
10203
10374
  "accent-foreground",
10204
10375
  "ring",
10205
- "success"
10376
+ "success",
10377
+ "success-mark"
10206
10378
  ],
10207
10379
  "motion": [
10208
10380
  {
@@ -11152,7 +11324,7 @@
11152
11324
  "generative"
11153
11325
  ],
11154
11326
  "usage": {
11155
- "description": "Use GradientArt where a real image belongs but none exists yet, or where the image is decoration: a product cover before upload, a profile banner, an album tile, an avatar with no photo. It reads the theme's own tokens, so it follows every preset, mode and live edit; `seed` fixes each item's composition so a list of covers or avatars stays individually recognisable.",
11327
+ "description": "Use GradientArt where a real image belongs but none exists yet, or where the image is decoration: a product cover before upload, a profile banner, an album tile, an avatar with no photo. It reads the theme's own tokens, so it follows every preset, mode and live edit; `seed` fixes each item's composition so a list of covers or avatars stays individually recognisable. `intensity=\"soft\"` paints the same art as a pastel wash — the iridescent aura AI products use as a card or modal header band, and as a stage for floating chips and logo tiles.",
11156
11328
  "bestPractices": [
11157
11329
  {
11158
11330
  "guidance": "do",
@@ -11166,6 +11338,14 @@
11166
11338
  "guidance": "do",
11167
11339
  "description": "Keep the default `mesh` for covers, tiles and avatars. Reach for `grain` where a printed, tactile surface suits — a banner, a hero card — and keep one variant per surface type so art reads as a system."
11168
11340
  },
11341
+ {
11342
+ "guidance": "do",
11343
+ "description": "Use `intensity=\"soft\"` as a stage: a card or modal header band, the art on an integration or pricing card, a field behind floating prompt chips or rounded logo tiles. Make the tiles and chips floating surfaces (`bg-popover` with `border-border-floating` and a shadow, or a `floating` Button) so they lift off the wash; soft stays light in dark mode too, so the same composition holds in both."
11344
+ },
11345
+ {
11346
+ "guidance": "dont",
11347
+ "description": "Do not put text straight on soft art with `text-overlay-foreground` ink. Soft is a light ground in every mode, so overlay ink washes out on it; put the content on a Card or a chip over the art, or use the default vivid intensity for a short overlay label."
11348
+ },
11169
11349
  {
11170
11350
  "guidance": "dont",
11171
11351
  "description": "Do not put body text over it. The art spans the palette's lightest and most saturated tones, so no single ink is guaranteed to clear contrast across it; reserve overlays for a short label on a scrim or an avatar's initials."
@@ -11204,6 +11384,12 @@
11204
11384
  "type": "string | number",
11205
11385
  "description": "Fixes the composition: the same seed paints the same art in every theme. Pass a stable id."
11206
11386
  },
11387
+ {
11388
+ "name": "intensity",
11389
+ "type": "\"vivid\" | \"soft\"",
11390
+ "default": "\"vivid\"",
11391
+ "description": "vivid: the preset's art at full strength. soft: every colour and the ground lifted to a light pastel of itself (high lightness, half chroma) — a wash for header bands and for staging chips and logo tiles, light in both modes."
11392
+ },
11207
11393
  {
11208
11394
  "name": "children",
11209
11395
  "type": "ReactNode",
@@ -11219,6 +11405,10 @@
11219
11405
  "variant": [
11220
11406
  "mesh",
11221
11407
  "grain"
11408
+ ],
11409
+ "intensity": [
11410
+ "vivid",
11411
+ "soft"
11222
11412
  ]
11223
11413
  },
11224
11414
  "tokensUsed": [
@@ -11284,6 +11474,11 @@
11284
11474
  "label": "Avatar with initials",
11285
11475
  "code": "<GradientArt seed=\"Mara Okafor\" className=\"grid size-10 place-items-center rounded-full text-label-md text-overlay-foreground\">MO</GradientArt>",
11286
11476
  "imports": "import { GradientArt } from \"@sableui/react\""
11477
+ },
11478
+ {
11479
+ "label": "Soft header band with logo tiles",
11480
+ "code": "<Card className=\"w-full max-w-sm\">\n\t<GradientArt intensity=\"soft\" seed=\"Integrations\" className=\"flex h-32 items-center justify-center gap-3 rounded-t-lg\">\n\t\t{[\"mail\", \"calendar\", \"chart\"].map((name) => (\n\t\t\t<span key={name} className=\"grid size-12 place-items-center rounded-lg border border-border-floating bg-popover text-popover-foreground shadow-md\">\n\t\t\t\t<Icon name={name} className=\"text-xl\" />\n\t\t\t</span>\n\t\t))}\n\t</GradientArt>\n\t<CardHeader>\n\t\t<CardTitle>Connect your tools</CardTitle>\n\t\t<CardDescription>Bring mail, calendar and analytics into one place.</CardDescription>\n\t</CardHeader>\n\t<CardFooter>\n\t\t<Button>Connect</Button>\n\t</CardFooter>\n</Card>",
11481
+ "imports": "import { Button, Card, CardDescription, CardFooter, CardHeader, CardTitle, GradientArt, Icon } from \"@sableui/react\""
11287
11482
  }
11288
11483
  ]
11289
11484
  },
@@ -11394,7 +11589,7 @@
11394
11589
  "group": "Forms",
11395
11590
  "register": "either",
11396
11591
  "path": "components/input",
11397
- "summary": "Styled native text input. Soft-square (rounded-sm), card surface, 2px focus ring; aria-invalid raises the destructive error treatment.",
11592
+ "summary": "Styled native text input. Soft-square (rounded-sm), the theme's field surface (outlined or filled), 2px focus ring; aria-invalid raises the destructive error treatment.",
11398
11593
  "keywords": [
11399
11594
  "input",
11400
11595
  "text input",
@@ -11425,6 +11620,14 @@
11425
11620
  "guidance": "do",
11426
11621
  "description": "Keep a focusable field at 16px or larger on mobile. iOS Safari zooms the whole page when a focused input computes under 16px and never zooms back out. Input handles this itself — below the sm breakpoint it renders text-body-lg (17px) and returns to text-body-md at sm and up. Build a custom field the same way: a second paired tier under a max-sm: variant, never a hand-set font-size."
11427
11622
  },
11623
+ {
11624
+ "guidance": "do",
11625
+ "description": "Choose outlined or filled fields once, in the theme: `--theme-field: var(--muted)` with `--theme-field-border: transparent` turns every Input, Textarea, Select, Combobox, SearchInput, InputGroup and ChatComposer into a borderless filled well; unset, they are outlined on the card. Every field reads the `field` / `field-border` pair, so they change together."
11626
+ },
11627
+ {
11628
+ "guidance": "dont",
11629
+ "description": "Restyle one Input as a filled chip with `bg-muted border-transparent`. It drifts from every other field on the page, and the theme can no longer move them together; set the field tokens instead."
11630
+ },
11428
11631
  {
11429
11632
  "guidance": "dont",
11430
11633
  "description": "Override an Input's type with a page tier below 16px (text-body-md, text-body-sm, text-label-*) without a >=16px mobile arm — that reintroduces the iOS focus zoom."
@@ -11511,8 +11714,8 @@
11511
11714
  ]
11512
11715
  },
11513
11716
  "tokensUsed": [
11514
- "input",
11515
- "card",
11717
+ "field-border",
11718
+ "field",
11516
11719
  "foreground",
11517
11720
  "muted-foreground",
11518
11721
  "ring",
@@ -11654,8 +11857,8 @@
11654
11857
  }
11655
11858
  ],
11656
11859
  "tokensUsed": [
11657
- "input",
11658
- "card",
11860
+ "field-border",
11861
+ "field",
11659
11862
  "ring",
11660
11863
  "destructive",
11661
11864
  "muted-foreground",
@@ -12321,7 +12524,12 @@
12321
12524
  "popover",
12322
12525
  "popover-foreground",
12323
12526
  "foreground",
12324
- "background"
12527
+ "background",
12528
+ "tone-warning-mark",
12529
+ "tone-info-mark",
12530
+ "tone-1-mark",
12531
+ "tone-2-mark",
12532
+ "tone-3-mark"
12325
12533
  ],
12326
12534
  "motion": [
12327
12535
  {
@@ -13781,7 +13989,12 @@
13781
13989
  "capacity",
13782
13990
  "limit",
13783
13991
  "password strength",
13784
- "level"
13992
+ "level",
13993
+ "segmented",
13994
+ "tick bar",
13995
+ "score",
13996
+ "credits",
13997
+ "spend limit"
13785
13998
  ],
13786
13999
  "usage": {
13787
14000
  "description": "Use Meter to show a static measurement against a known maximum — storage used, seats taken, API quota, password strength. It is announced as a meter, not a progress bar, so a screen-reader user hears a level rather than a task underway.",
@@ -13808,6 +14021,17 @@
13808
14021
  {
13809
14022
  "guidance": "do",
13810
14023
  "description": "Use shape=\"ring\" when the reading is a score that belongs in a small, glanceable spot on a card. It is the same measurement drawn as a circular gauge, not a different component."
14024
+ },
14025
+ {
14026
+ "guidance": "do",
14027
+ "description": "Use `segments` (a tick bar, ▮▮▮▮▮▮▯▯▯▯) for a discrete budget, score or quota read at a glance — a spend limit, credits left, an ICP lead score, months of data coverage. Pick a count that matches the unit when there is one (10 for a score out of 10, 12 for months) and otherwise size it to the track: a tick reads as a tick when it is taller than it is wide, about one per 8px of track (40 across a card row, 20 in a narrow table cell). Any reading above min shows at least one tick."
14028
+ },
14029
+ {
14030
+ "guidance": "dont",
14031
+ "description": "Do not segment a fine-grained continuous value where the exact proportion matters (disk at 73.4%) — ticks round it to the nearest mark; use the continuous bar. And do not use a tick bar for a task in flight or steps completed: that is Progress, or a Stepper for named steps.",
14032
+ "instead": [
14033
+ "Progress"
14034
+ ]
13811
14035
  }
13812
14036
  ],
13813
14037
  "anatomy": [
@@ -13819,7 +14043,7 @@
13819
14043
  {
13820
14044
  "name": "MeterIndicator",
13821
14045
  "required": true,
13822
- "description": "The fill, sized from value and coloured by tone."
14046
+ "description": "The fill, sized from value and coloured by tone. Not used with `segments`: the track draws its ticks instead."
13823
14047
  },
13824
14048
  {
13825
14049
  "name": "MeterLabel",
@@ -13880,6 +14104,11 @@
13880
14104
  "type": "boolean",
13881
14105
  "description": "Print the value in the ring's centre (formatted like MeterValue)."
13882
14106
  },
14107
+ {
14108
+ "name": "segments",
14109
+ "type": "number",
14110
+ "description": "Draw the bar as this many separate ticks instead of a continuous fill (a quota, score or spend limit). Filled ticks = round(share × N), at least one for any reading above min, none at min. Ticks take the tone; empty ones sit on the rail colour. The segmented track has its own, taller sm / md / lg ladder. Bar only: ignored for shape=\"ring\"."
14111
+ },
13883
14112
  {
13884
14113
  "name": "strokeWidth",
13885
14114
  "type": "number",
@@ -13906,7 +14135,7 @@
13906
14135
  {
13907
14136
  "name": "MeterTrack",
13908
14137
  "type": "Base UI Track props + className + size",
13909
- "description": "The rail. Rendered automatically when Meter has no children; renders a MeterIndicator by default."
14138
+ "description": "The rail. Rendered automatically when Meter has no children; renders a MeterIndicator by default — or, when the Meter has `segments`, its row of ticks (children are not rendered then)."
13910
14139
  },
13911
14140
  {
13912
14141
  "name": "MeterIndicator",
@@ -13945,11 +14174,16 @@
13945
14174
  "tokensUsed": [
13946
14175
  "secondary",
13947
14176
  "primary",
14177
+ "tone-3",
13948
14178
  "success",
13949
14179
  "tone-warning",
13950
14180
  "destructive",
13951
14181
  "foreground",
13952
- "muted-foreground"
14182
+ "muted-foreground",
14183
+ "destructive-mark",
14184
+ "success-mark",
14185
+ "tone-warning-mark",
14186
+ "tone-3-mark"
13953
14187
  ],
13954
14188
  "motion": [
13955
14189
  {
@@ -13970,6 +14204,12 @@
13970
14204
  "part": "MeterIndicator",
13971
14205
  "why": "Width and colour ease on the motion tokens (no recipe animates width) when the reading changes — freeing space after a delete visibly shrinks the bar, so the user sees the cause and effect rather than a different bar."
13972
14206
  },
14207
+ {
14208
+ "slot": "transition",
14209
+ "recipe": "custom",
14210
+ "part": "MeterTrack (segments)",
14211
+ "why": "With segments, the fill runs through the ticks from the edge it is leaving — left to right as it grows, right to left as it shrinks — each tick easing its colour on the fast token after a stagger that is a share of the slow token (a full sweep is one slow duration) × --motion-expressive. Every tick switching at once would read as a different bar, not the same budget moving; `subtle` lands them together and off is instant."
14212
+ },
13973
14213
  {
13974
14214
  "slot": "activity",
13975
14215
  "recipe": "none",
@@ -13998,6 +14238,16 @@
13998
14238
  "code": "<Meter value={7.2} max={10} tone=\"warning\" getAriaValueText={(_, v) => `${v} of 10 gigabytes used`}>\n\t<div className=\"mb-2 flex flex-wrap items-center justify-between gap-x-3 gap-y-1\">\n\t\t<MeterLabel>Storage</MeterLabel>\n\t\t<MeterValue>{(_, value) => `${value} of 10 GB`}</MeterValue>\n\t</div>\n\t<MeterTrack />\n</Meter>",
13999
14239
  "imports": "import { Meter, MeterLabel, MeterTrack, MeterValue } from \"@sableui/react\""
14000
14240
  },
14241
+ {
14242
+ "label": "Segmented spend limit",
14243
+ "code": "<Meter value={1240} max={2000} segments={40} getAriaValueText={() => \"€1,240 of €2,000 spent this month\"}>\n\t<div className=\"mb-2 flex flex-wrap items-center justify-between gap-x-3 gap-y-1\">\n\t\t<MeterLabel>Monthly spend limit</MeterLabel>\n\t\t<MeterValue>{() => \"€1,240 / €2,000\"}</MeterValue>\n\t</div>\n\t<MeterTrack />\n</Meter>",
14244
+ "imports": "import { Meter, MeterLabel, MeterTrack, MeterValue } from \"@sableui/react\""
14245
+ },
14246
+ {
14247
+ "label": "Segmented score cell",
14248
+ "code": "<div className=\"flex items-center gap-3\">\n\t<Meter value={8} max={10} segments={10} size=\"sm\" tone=\"success\" className=\"w-24\" aria-label=\"ICP score\" getAriaValueText={(_, v) => `${v} out of 10`} />\n\t<span className=\"text-mono-sm text-foreground\">8/10</span>\n</div>",
14249
+ "imports": "import { Meter } from \"@sableui/react\""
14250
+ },
14001
14251
  {
14002
14252
  "label": "Tones",
14003
14253
  "code": "<div className=\"flex flex-col gap-3\">\n\t<Meter value={30} tone=\"success\" aria-label=\"Seats used\" />\n\t<Meter value={82} tone=\"warning\" aria-label=\"API quota used\" />\n\t<Meter value={100} tone=\"destructive\" aria-label=\"Storage used\" />\n</div>",
@@ -14376,7 +14626,11 @@
14376
14626
  "tone-info",
14377
14627
  "tone-warning",
14378
14628
  "success",
14379
- "destructive"
14629
+ "destructive",
14630
+ "destructive-mark",
14631
+ "success-mark",
14632
+ "tone-warning-mark",
14633
+ "tone-info-mark"
14380
14634
  ],
14381
14635
  "motion": [
14382
14636
  {
@@ -14676,8 +14930,8 @@
14676
14930
  }
14677
14931
  ],
14678
14932
  "tokensUsed": [
14679
- "input",
14680
- "card",
14933
+ "field-border",
14934
+ "field",
14681
14935
  "foreground",
14682
14936
  "muted-foreground",
14683
14937
  "accent",
@@ -15026,8 +15280,8 @@
15026
15280
  }
15027
15281
  ],
15028
15282
  "tokensUsed": [
15029
- "input",
15030
- "card",
15283
+ "field-border",
15284
+ "field",
15031
15285
  "foreground",
15032
15286
  "muted-foreground",
15033
15287
  "border-strong",
@@ -16169,7 +16423,12 @@
16169
16423
  "popover",
16170
16424
  "popover-foreground",
16171
16425
  "foreground",
16172
- "background"
16426
+ "background",
16427
+ "tone-warning-mark",
16428
+ "tone-info-mark",
16429
+ "tone-1-mark",
16430
+ "tone-2-mark",
16431
+ "tone-3-mark"
16173
16432
  ],
16174
16433
  "motion": [
16175
16434
  {
@@ -16897,7 +17156,12 @@
16897
17156
  "popover",
16898
17157
  "popover-foreground",
16899
17158
  "foreground",
16900
- "background"
17159
+ "background",
17160
+ "tone-warning-mark",
17161
+ "tone-info-mark",
17162
+ "tone-1-mark",
17163
+ "tone-2-mark",
17164
+ "tone-3-mark"
16901
17165
  ],
16902
17166
  "motion": [
16903
17167
  {
@@ -17121,7 +17385,12 @@
17121
17385
  "popover",
17122
17386
  "popover-foreground",
17123
17387
  "foreground",
17124
- "background"
17388
+ "background",
17389
+ "tone-warning-mark",
17390
+ "tone-info-mark",
17391
+ "tone-1-mark",
17392
+ "tone-2-mark",
17393
+ "tone-3-mark"
17125
17394
  ],
17126
17395
  "motion": [
17127
17396
  {
@@ -18149,7 +18418,7 @@
18149
18418
  "group": "Forms",
18150
18419
  "register": "either",
18151
18420
  "path": "components/search-input",
18152
- "summary": "Styled search field with a leading magnifier and a clearable X. Soft-square (rounded-sm), card surface, 2px focus ring; the clear button appears only when there is a value.",
18421
+ "summary": "Styled search field with a leading magnifier and a clearable X. Soft-square (rounded-sm), the theme's field surface, 2px focus ring; the clear button appears only when there is a value.",
18153
18422
  "keywords": [
18154
18423
  "search",
18155
18424
  "input",
@@ -18171,6 +18440,10 @@
18171
18440
  "guidance": "do",
18172
18441
  "description": "When a button stands in for search (a header trigger that opens CommandMenu with ⌘K), use CommandMenuTrigger. It wears this field's shell from the same source, so the two cannot drift; a hand-styled button already did once, into a borderless chip that matched neither the field nor a button."
18173
18442
  },
18443
+ {
18444
+ "guidance": "do",
18445
+ "description": "Light the query in the results it filters with `useMatchHighlight(query)` — a callback ref for the results container, with `selector` to keep it to titles. It paints on the `highlight` pair without wrapping matches in `<mark>`, the same paint Combobox and CommandMenu use for their rows."
18446
+ },
18174
18447
  {
18175
18448
  "guidance": "dont",
18176
18449
  "description": "Do not use SearchInput as a command palette; use CommandMenu for global commands, opened from the header by CommandMenuTrigger. A SearchInput that opens a dialog on focus is a text box you cannot type in."
@@ -18238,8 +18511,8 @@
18238
18511
  }
18239
18512
  ],
18240
18513
  "tokensUsed": [
18241
- "input",
18242
- "card",
18514
+ "field-border",
18515
+ "field",
18243
18516
  "foreground",
18244
18517
  "muted-foreground",
18245
18518
  "ring",
@@ -18294,6 +18567,11 @@
18294
18567
  "code": "<Field label=\"Search posts\"><SearchInput defaultValue=\"roadmap\" className=\"max-w-80\" /></Field>",
18295
18568
  "imports": "import { Field, SearchInput } from \"@sableui/react\""
18296
18569
  },
18570
+ {
18571
+ "label": "Highlighting matches in the results",
18572
+ "code": "const [q, setQ] = useState(\"\")\nconst results = useMatchHighlight<HTMLUListElement>(q, { selector: \"[data-title]\" })\nconst shown = posts.filter((post) => post.title.toLowerCase().includes(q.trim().toLowerCase()))\n\n<SearchInput value={q} onValueChange={setQ} placeholder=\"Search posts\" />\n<ul ref={results}>\n\t{shown.map((post) => (\n\t\t<li key={post.id}><span data-title>{post.title}</span></li>\n\t))}\n</ul>",
18573
+ "imports": "import { SearchInput, useMatchHighlight } from \"@sableui/react\""
18574
+ },
18297
18575
  {
18298
18576
  "label": "Disabled",
18299
18577
  "code": "<SearchInput disabled placeholder=\"Search\" />",
@@ -18603,7 +18881,14 @@
18603
18881
  "muted-foreground",
18604
18882
  "success",
18605
18883
  "tone-warning",
18606
- "destructive"
18884
+ "destructive",
18885
+ "destructive-mark",
18886
+ "success-mark",
18887
+ "tone-warning-mark",
18888
+ "tone-info-mark",
18889
+ "tone-1-mark",
18890
+ "tone-2-mark",
18891
+ "tone-3-mark"
18607
18892
  ],
18608
18893
  "motion": [
18609
18894
  {
@@ -18789,8 +19074,8 @@
18789
19074
  }
18790
19075
  ],
18791
19076
  "tokensUsed": [
18792
- "input",
18793
- "card",
19077
+ "field-border",
19078
+ "field",
18794
19079
  "foreground",
18795
19080
  "ring",
18796
19081
  "border",
@@ -19514,6 +19799,10 @@
19514
19799
  "guidance": "do",
19515
19800
  "description": "Set surface=\"page\" when a full-width top bar sits above the rail. A theme's tinted or dark rail is for a full-height rail that frames the app."
19516
19801
  },
19802
+ {
19803
+ "guidance": "do",
19804
+ "description": "Keep surface=\"rail\" inside AppShell frame=\"inset\": the rail's tint becomes the ground the main panel floats on. Do not add a border-r class back — the gap is the divider."
19805
+ },
19517
19806
  {
19518
19807
  "guidance": "dont",
19519
19808
  "description": "Do not use Sidebar for page-local settings, filters, or temporary action groups."
@@ -19566,7 +19855,7 @@
19566
19855
  "name": "surface",
19567
19856
  "type": "\"rail\" | \"page\"",
19568
19857
  "default": "\"rail\"",
19569
- "description": "Which surface the rail is painted on. \"rail\" is its own --sidebar-* surface with a border — right for a full-height rail that frames the app, which a theme may tint or paint dark. \"page\" uses the page's surface and ink with no border — use it when a full-width header sits above the rail, where a tinted column starting under a page-coloured bar reads as pasted on. Use it instead of overriding bg-/text- classes, which the rail's re-pointed tokens defeat."
19858
+ "description": "Which surface the rail is painted on. \"rail\" is its own --sidebar-* surface with a border — right for a full-height rail that frames the app, which a theme may tint or paint dark. \"page\" uses the page's surface and ink with no border — use it when a full-width header sits above the rail, where a tinted column starting under a page-coloured bar reads as pasted on. Use it instead of overriding bg-/text- classes, which the rail's re-pointed tokens defeat. In AppShell's sidebar slot with frame=\"inset\", the rail's surface is also the shell's ground: from lg a \"rail\" rail drops its border (the gap around the main panel divides them) and either surface stretches to the shell's body row instead of sizing to the viewport. AppShell signals this to its sidebar slot only, so a Sidebar elsewhere in the page is unaffected."
19570
19859
  },
19571
19860
  {
19572
19861
  "name": "motion",
@@ -19604,7 +19893,8 @@
19604
19893
  "sidebar-border",
19605
19894
  "sidebar-accent",
19606
19895
  "sidebar-accent-foreground",
19607
- "sidebar-ring"
19896
+ "sidebar-ring",
19897
+ "shell-ground"
19608
19898
  ],
19609
19899
  "motion": [
19610
19900
  {
@@ -20305,7 +20595,14 @@
20305
20595
  "tone-warning",
20306
20596
  "muted-foreground",
20307
20597
  "success",
20308
- "destructive"
20598
+ "destructive",
20599
+ "destructive-mark",
20600
+ "success-mark",
20601
+ "tone-warning-mark",
20602
+ "tone-info-mark",
20603
+ "tone-1-mark",
20604
+ "tone-2-mark",
20605
+ "tone-3-mark"
20309
20606
  ],
20310
20607
  "motion": [
20311
20608
  {
@@ -20718,7 +21015,14 @@
20718
21015
  "tone-info",
20719
21016
  "tone-1",
20720
21017
  "tone-2",
20721
- "destructive"
21018
+ "destructive",
21019
+ "destructive-mark",
21020
+ "success-mark",
21021
+ "tone-warning-mark",
21022
+ "tone-info-mark",
21023
+ "tone-1-mark",
21024
+ "tone-2-mark",
21025
+ "tone-3-mark"
20722
21026
  ],
20723
21027
  "a11y": [
20724
21028
  "Rendered aria-hidden — purely decorative. Convey status in adjacent text, not color alone.",
@@ -20876,7 +21180,8 @@
20876
21180
  "border-strong",
20877
21181
  "destructive",
20878
21182
  "destructive-foreground",
20879
- "ring"
21183
+ "ring",
21184
+ "destructive-mark"
20880
21185
  ],
20881
21186
  "motion": [
20882
21187
  {
@@ -21358,13 +21663,13 @@
21358
21663
  },
21359
21664
  {
21360
21665
  "name": "TableHead",
21361
- "type": "ComponentPropsWithRef<\"th\">",
21362
- "description": "A column header cell (th) in muted label styling."
21666
+ "type": "ComponentPropsWithRef<\"th\"> & { numeric?: boolean }",
21667
+ "description": "A column header cell (th) in muted label styling. `numeric` marks a number column: end-aligned, tabular figures — set it on the column's cells too."
21363
21668
  },
21364
21669
  {
21365
21670
  "name": "TableCell",
21366
- "type": "ComponentPropsWithRef<\"td\">",
21367
- "description": "A data cell (td)."
21671
+ "type": "ComponentPropsWithRef<\"td\"> & { numeric?: boolean }",
21672
+ "description": "A data cell (td). `numeric` end-aligns it with tabular figures, matching its column's header."
21368
21673
  },
21369
21674
  {
21370
21675
  "name": "TableCaption",
@@ -21616,7 +21921,7 @@
21616
21921
  "group": "Forms",
21617
21922
  "register": "either",
21618
21923
  "path": "components/textarea",
21619
- "summary": "Styled native multi-line text control. Soft-square, card surface, --ring focus, and an aria-invalid destructive error state.",
21924
+ "summary": "Styled native multi-line text control. Soft-square, the theme's field surface, --ring focus, and an aria-invalid destructive error state.",
21620
21925
  "keywords": [
21621
21926
  "textarea",
21622
21927
  "multi line input",
@@ -21689,8 +21994,8 @@
21689
21994
  }
21690
21995
  ],
21691
21996
  "tokensUsed": [
21692
- "input",
21693
- "card",
21997
+ "field-border",
21998
+ "field",
21694
21999
  "foreground",
21695
22000
  "muted-foreground",
21696
22001
  "ring",
@@ -25097,7 +25402,7 @@
25097
25402
  "Amounts keep their sign in text (+49.00 / -850.00), so the direction does not depend on colour."
25098
25403
  ],
25099
25404
  "imports": "import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, cn, Entity, Icon } from \"@sableui/react\"",
25100
- "code": "const balance = \"$2,418.50\"\n\nconst activity = [\n\t{ title: \"Subscription\", detail: \"Team plan · 2h ago\", amount: \"+49.00\", tone: \"1\" },\n\t{ title: \"Refund\", detail: \"Order 1042 · Yesterday\", amount: \"-24.00\", tone: \"2\" },\n\t{ title: \"Payout\", detail: \"To checking · Mon\", amount: \"-850.00\", tone: \"3\" },\n]\n\nexport interface WalletBlockProps {\n\tclassName?: string\n\t/** false drops the card's surface and border — for a Sheet or muted section that already frames it. */\n\tframed?: boolean\n\tonSend?: () => void\n\tonReceive?: () => void\n}\n\nexport function WalletBlock({ className, framed = true, onSend, onReceive }: WalletBlockProps) {\n\treturn (\n\t\t<Card variant={framed ? \"default\" : \"flat\"} className={cn(\"w-full max-w-xs\", className)}>\n\t\t\t<CardHeader>\n\t\t\t\t<CardDescription>Balance</CardDescription>\n\t\t\t\t<CardTitle className=\"text-mono-xl\">{balance}</CardTitle>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"flex flex-col gap-3\">\n\t\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t\t<Button iconStart={<Icon name=\"arrow-up\" />} onClick={onSend}>\n\t\t\t\t\t\tSend\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button variant=\"secondary\" iconStart={<Icon name=\"arrow-down\" />} onClick={onReceive}>\n\t\t\t\t\t\tReceive\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t{activity.map((item) => (\n\t\t\t\t\t\t<Entity\n\t\t\t\t\t\t\tkey={item.title}\n\t\t\t\t\t\t\tclassName=\"px-0\"\n\t\t\t\t\t\t\tleading={\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\tclassName=\"block size-8 rounded-full\"\n\t\t\t\t\t\t\t\t\t// design-lint-disable-next-line inline-color -- relative colour derived from the theme's own --tone token, so it follows every look\n\t\t\t\t\t\t\t\t\tstyle={{ background: `oklch(from var(--tone-${item.tone}) clamp(0.5, calc(l + 0.16), 0.9) max(calc(c * 1.25), 0.1) h)` }}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={item.title}\n\t\t\t\t\t\t\tsubtitle={item.detail}\n\t\t\t\t\t\t\taction={\n\t\t\t\t\t\t\t\t<span className={cn(\"text-mono-md\", item.amount.startsWith(\"+\") ? \"text-success\" : \"text-muted-foreground\")}>\n\t\t\t\t\t\t\t\t\t{item.amount}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t)\n}"
25405
+ "code": "const balance = \"$2,418.50\"\n\nconst activity = [\n\t{ title: \"Subscription\", detail: \"Team plan · 2h ago\", amount: \"+49.00\", tone: \"1\" },\n\t{ title: \"Refund\", detail: \"Order 1042 · Yesterday\", amount: \"-24.00\", tone: \"2\" },\n\t{ title: \"Payout\", detail: \"To checking · Mon\", amount: \"-850.00\", tone: \"3\" },\n] as const\n\n/** Each row's mark: its tone at graphic strength, which every theme tunes. */\nconst TONE_MARK = { \"1\": \"bg-tone-1-mark\", \"2\": \"bg-tone-2-mark\", \"3\": \"bg-tone-3-mark\" } as const\n\nexport interface WalletBlockProps {\n\tclassName?: string\n\t/** false drops the card's surface and border — for a Sheet or muted section that already frames it. */\n\tframed?: boolean\n\tonSend?: () => void\n\tonReceive?: () => void\n}\n\nexport function WalletBlock({ className, framed = true, onSend, onReceive }: WalletBlockProps) {\n\treturn (\n\t\t<Card variant={framed ? \"default\" : \"flat\"} className={cn(\"w-full max-w-xs\", className)}>\n\t\t\t<CardHeader>\n\t\t\t\t<CardDescription>Balance</CardDescription>\n\t\t\t\t<CardTitle className=\"text-mono-xl\">{balance}</CardTitle>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"flex flex-col gap-3\">\n\t\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t\t<Button iconStart={<Icon name=\"arrow-up\" />} onClick={onSend}>\n\t\t\t\t\t\tSend\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button variant=\"secondary\" iconStart={<Icon name=\"arrow-down\" />} onClick={onReceive}>\n\t\t\t\t\t\tReceive\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t{activity.map((item) => (\n\t\t\t\t\t\t<Entity\n\t\t\t\t\t\t\tkey={item.title}\n\t\t\t\t\t\t\tclassName=\"px-0\"\n\t\t\t\t\t\t\tleading={\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\tclassName={cn(\"block size-8 rounded-full\", TONE_MARK[item.tone])}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={item.title}\n\t\t\t\t\t\t\tsubtitle={item.detail}\n\t\t\t\t\t\t\taction={\n\t\t\t\t\t\t\t\t<span className={cn(\"text-mono-md\", item.amount.startsWith(\"+\") ? \"text-success\" : \"text-muted-foreground\")}>\n\t\t\t\t\t\t\t\t\t{item.amount}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t)\n}"
25101
25406
  }
25102
25407
  ]
25103
25408
  },
@@ -26187,6 +26492,11 @@
26187
26492
  "why": "The ratio alone passes labels that read muddy. A deliberate brand pair is allowed with a recorded reason (lint disable or preset exceptions).",
26188
26493
  "enforcedBy": "sable-lint: label-contrast"
26189
26494
  },
26495
+ {
26496
+ "never": "A label fill painted on a mark that carries no text — a meter, a segmented bar, a status dot, a chart series, a soft tint.",
26497
+ "instead": "The colour's `-mark` token (`bg-success-mark`, `bg-tone-warning-mark/15`): the same hue lifted and saturated, held to 2:1 on the page. Text contrast is for text; a graphic owes visibility, and 3:1 (WCAG 1.4.11) only when it is the sole carrier of its meaning.",
26498
+ "why": "A fill is pinned dark enough for a white label. On a bar or dot with nothing to label, that darkness only reads as mud: a brown warning, a forest-green success."
26499
+ },
26190
26500
  {
26191
26501
  "never": "Blocking paste, or type=\"number\" for codes and card numbers.",
26192
26502
  "instead": "type=\"text\" inputMode=\"numeric\" with the right autocomplete.",
@@ -27580,6 +27890,29 @@
27580
27890
  "transparent pattern",
27581
27891
  "swatch background"
27582
27892
  ]
27893
+ },
27894
+ {
27895
+ "name": "texture-dither",
27896
+ "kind": "utility",
27897
+ "family": "helper",
27898
+ "intent": "A faint pixel / halftone dither field that dissolves: a small pseudo-random tile of squares painted in `--border-strong` and faded out by a gradient mask. Static, pure CSS, follows every theme and mode. Hooks: `--dither-fade` (direction, any linear-gradient side or angle, default `to bottom`), `--dither-size` (tile, default 48px = 2px squares) and `--dither-color` (default `var(--border-strong)`).",
27899
+ "whenToUse": "Decoration at the top of a content area, a panel or a card, or behind an empty-state heading. Put it on its own `aria-hidden` element, `absolute -z-10` as the first child of a `relative isolate` parent, so the content after it paints on top with no z-index of its own. It sets `pointer-events: none` and no position, so it never takes layout or catches clicks.",
27900
+ "insteadOf": "A hand-written `radial-gradient` dot grid (reads as graph paper, not dither), a PNG noise texture, a canvas, or hardcoded greys. Deliberately not named `bg-dither`, so `cn()` never merges it away against a real `bg-*` colour class.",
27901
+ "example": "<div className=\"relative isolate\"><div aria-hidden className=\"texture-dither absolute inset-x-0 top-0 -z-10 h-40\" /></div>",
27902
+ "keywords": [
27903
+ "dither",
27904
+ "halftone",
27905
+ "pixel pattern",
27906
+ "dot pattern",
27907
+ "noise texture",
27908
+ "texture",
27909
+ "fade pattern",
27910
+ "empty state background",
27911
+ "decorative background"
27912
+ ],
27913
+ "pairsWith": [
27914
+ "checkerboard"
27915
+ ]
27583
27916
  }
27584
27917
  ]
27585
27918
  },
@@ -27685,6 +28018,7 @@
27685
28018
  "bottomNav",
27686
28019
  "children",
27687
28020
  "dock",
28021
+ "frame",
27688
28022
  "header",
27689
28023
  "overlays",
27690
28024
  "sidebar"
@@ -28163,6 +28497,7 @@
28163
28497
  "form",
28164
28498
  "grid",
28165
28499
  "highlightItemOnHover",
28500
+ "highlightMatches",
28166
28501
  "id",
28167
28502
  "inline",
28168
28503
  "inputRef",
@@ -28289,6 +28624,7 @@
28289
28624
  "emptyMessage",
28290
28625
  "filter",
28291
28626
  "finalFocus",
28627
+ "highlightMatches",
28292
28628
  "inputProps",
28293
28629
  "items",
28294
28630
  "listClassName",
@@ -28318,6 +28654,7 @@
28318
28654
  "children",
28319
28655
  "emptyMessage",
28320
28656
  "filter",
28657
+ "highlightMatches",
28321
28658
  "inputProps",
28322
28659
  "items",
28323
28660
  "listClassName",
@@ -28729,6 +29066,7 @@
28729
29066
  "orientation"
28730
29067
  ],
28731
29068
  "GradientArt": [
29069
+ "intensity",
28732
29070
  "seed",
28733
29071
  "tones",
28734
29072
  "variant"
@@ -29088,6 +29426,7 @@
29088
29426
  "max",
29089
29427
  "min",
29090
29428
  "render",
29429
+ "segments",
29091
29430
  "shape",
29092
29431
  "showValue",
29093
29432
  "size",