@viraui/react 2026.6.5 → 2026.7.0-next.1

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 (168) hide show
  1. package/dist/catalog.json +24 -0
  2. package/dist/components/accordion/accordion-item.d.ts +10 -10
  3. package/dist/components/accordion/accordion.d.ts +2 -2
  4. package/dist/components/annotate/annotate.d.ts +15 -15
  5. package/dist/components/autocomplete/autocomplete-item.d.ts +3 -3
  6. package/dist/components/autocomplete/autocomplete.d.ts +12 -12
  7. package/dist/components/autocomplete/autocomplete.js +1 -1
  8. package/dist/components/avatar/avatar.d.ts +6 -6
  9. package/dist/components/avatar-group/avatar-group.d.ts +6 -6
  10. package/dist/components/badge/badge.d.ts +5 -5
  11. package/dist/components/basic-input/basic-input.d.ts +3 -2
  12. package/dist/components/basic-input/basic-input.js +7 -0
  13. package/dist/components/basic-input/input-control-group.d.ts +2 -2
  14. package/dist/components/beam/beam-pulse-driver.d.ts +1 -0
  15. package/dist/components/beam/beam-pulse-driver.js +2 -2
  16. package/dist/components/beam/beam.css +1 -1
  17. package/dist/components/beam/beam.d.ts +17 -14
  18. package/dist/components/beam/beam.js +31 -26
  19. package/dist/components/bleed/bleed.d.ts +3 -3
  20. package/dist/components/button/button-link.d.ts +1 -1
  21. package/dist/components/button/button.d.ts +1 -1
  22. package/dist/components/checkbox/checkbox-group.d.ts +1 -1
  23. package/dist/components/checkbox/checkbox.d.ts +7 -7
  24. package/dist/components/chip/chip.d.ts +6 -6
  25. package/dist/components/clamp-text/clamp-text.d.ts +5 -5
  26. package/dist/components/dialog/dialog-close.d.ts +1 -1
  27. package/dist/components/dialog/dialog-indent-background.d.ts +1 -1
  28. package/dist/components/dialog/dialog-indent.d.ts +1 -1
  29. package/dist/components/dialog/dialog-sheet.d.ts +10 -10
  30. package/dist/components/dialog/dialog-sheet.js +1 -1
  31. package/dist/components/dialog/dialog-trigger.d.ts +1 -1
  32. package/dist/components/dialog/dialog.d.ts +1 -1
  33. package/dist/components/disclosure/disclosure-panel.d.ts +12 -0
  34. package/dist/components/disclosure/disclosure-panel.js +13 -0
  35. package/dist/components/disclosure/disclosure-trigger.d.ts +46 -0
  36. package/dist/components/disclosure/disclosure-trigger.js +82 -0
  37. package/dist/components/disclosure/disclosure.css +1 -0
  38. package/dist/components/disclosure/disclosure.d.ts +25 -0
  39. package/dist/components/disclosure/disclosure.js +30 -0
  40. package/dist/components/disclosure/disclosure.module.js +15 -0
  41. package/dist/components/disclosure/index.d.ts +4 -0
  42. package/dist/components/elevator/elevator.d.ts +7 -7
  43. package/dist/components/fieldset/fieldset.d.ts +4 -4
  44. package/dist/components/fit-text/fit-text.d.ts +2 -2
  45. package/dist/components/glow/glow.d.ts +12 -12
  46. package/dist/components/grid/grid-item.d.ts +8 -8
  47. package/dist/components/grid/grid.d.ts +12 -12
  48. package/dist/components/icon-button/icon-button-link.d.ts +2 -2
  49. package/dist/components/icon-button/icon-button.d.ts +2 -2
  50. package/dist/components/index.d.ts +4 -0
  51. package/dist/components/linear-progress/linear-progress.d.ts +4 -4
  52. package/dist/components/masonry/masonry-item.d.ts +3 -3
  53. package/dist/components/masonry/masonry.d.ts +4 -4
  54. package/dist/components/menu/menu-checkbox-item.d.ts +4 -4
  55. package/dist/components/menu/menu-item.d.ts +4 -4
  56. package/dist/components/menu/menu-link-item.d.ts +4 -4
  57. package/dist/components/menu/menu-popup.d.ts +2 -2
  58. package/dist/components/menu/menu-popup.js +1 -1
  59. package/dist/components/menu/menu-radio-group.d.ts +2 -2
  60. package/dist/components/menu/menu-radio-item.d.ts +4 -4
  61. package/dist/components/menu/menu-separator.d.ts +1 -1
  62. package/dist/components/menu/menu-submenu-trigger.d.ts +3 -3
  63. package/dist/components/menu/menu.d.ts +3 -3
  64. package/dist/components/meter/meter.css +1 -1
  65. package/dist/components/meter/meter.d.ts +15 -5
  66. package/dist/components/meter/meter.js +2 -1
  67. package/dist/components/number-field/index.d.ts +2 -0
  68. package/dist/components/number-field/number-field.css +1 -0
  69. package/dist/components/number-field/number-field.d.ts +78 -0
  70. package/dist/components/number-field/number-field.js +120 -0
  71. package/dist/components/number-field/number-field.module.js +21 -0
  72. package/dist/components/otp-field/index.d.ts +4 -0
  73. package/dist/components/otp-field/otp-field-input.d.ts +12 -0
  74. package/dist/components/otp-field/otp-field-input.js +29 -0
  75. package/dist/components/otp-field/otp-field-separator.d.ts +13 -0
  76. package/dist/components/otp-field/otp-field-separator.js +20 -0
  77. package/dist/components/otp-field/otp-field.css +1 -0
  78. package/dist/components/otp-field/otp-field.d.ts +48 -0
  79. package/dist/components/otp-field/otp-field.js +78 -0
  80. package/dist/components/otp-field/otp-field.module.js +23 -0
  81. package/dist/components/popover/popover-sheet.d.ts +6 -6
  82. package/dist/components/popover/popover.d.ts +5 -5
  83. package/dist/components/progressive-blur/progressive-blur.d.ts +5 -5
  84. package/dist/components/prose/index.d.ts +2 -0
  85. package/dist/components/prose/prose.css +1 -0
  86. package/dist/components/prose/prose.d.ts +40 -0
  87. package/dist/components/prose/prose.js +27 -0
  88. package/dist/components/prose/prose.module.js +5 -0
  89. package/dist/components/radio/radio-group.d.ts +1 -1
  90. package/dist/components/radio/radio.d.ts +6 -6
  91. package/dist/components/select/select-indicator-slot.d.ts +1 -1
  92. package/dist/components/select/select-option.d.ts +4 -4
  93. package/dist/components/select/select-separator.d.ts +1 -1
  94. package/dist/components/select/select.d.ts +10 -10
  95. package/dist/components/select/select.js +1 -1
  96. package/dist/components/separator/separator.d.ts +15 -8
  97. package/dist/components/separator/separator.js +2 -1
  98. package/dist/components/shimmer/shimmer.d.ts +6 -6
  99. package/dist/components/skeleton/skeleton-overlay.d.ts +5 -5
  100. package/dist/components/skeleton/skeleton.d.ts +9 -9
  101. package/dist/components/slider/slider.d.ts +7 -7
  102. package/dist/components/spinner/spinner.d.ts +3 -3
  103. package/dist/components/stack/stack.d.ts +17 -17
  104. package/dist/components/static-noise/static-noise.d.ts +5 -5
  105. package/dist/components/surface/surface.d.ts +12 -12
  106. package/dist/components/switch/switch.d.ts +7 -7
  107. package/dist/components/tabs/tabs-list.d.ts +1 -1
  108. package/dist/components/tabs/tabs-panel.d.ts +1 -1
  109. package/dist/components/tabs/tabs-tab.d.ts +3 -3
  110. package/dist/components/tabs/tabs.d.ts +2 -2
  111. package/dist/components/text/text.css +1 -1
  112. package/dist/components/text/text.d.ts +24 -23
  113. package/dist/components/text/text.js +4 -2
  114. package/dist/components/textarea/textarea.d.ts +6 -6
  115. package/dist/components/textfield/textfield.css +1 -1
  116. package/dist/components/textfield/textfield.d.ts +19 -11
  117. package/dist/components/textfield/textfield.js +43 -39
  118. package/dist/components/textfield/textfield.module.js +3 -1
  119. package/dist/components/title/title.css +1 -1
  120. package/dist/components/title/title.d.ts +22 -21
  121. package/dist/components/title/title.js +4 -2
  122. package/dist/components/toast/toast-action.d.ts +1 -1
  123. package/dist/components/toast/toast-banner.d.ts +7 -7
  124. package/dist/components/toast/toast-banner.js +1 -1
  125. package/dist/components/toast/toast-viewport.d.ts +2 -2
  126. package/dist/components/toggle-button/toggle-button.d.ts +6 -6
  127. package/dist/components/toggle-group/toggle-group.d.ts +1 -1
  128. package/dist/components/tooltip/tooltip-content.d.ts +2 -2
  129. package/dist/components/typewriter/typewriter.d.ts +10 -10
  130. package/dist/index.js +7 -3
  131. package/dist/specs/components/accordion/usage.xml +1 -0
  132. package/dist/specs/components/beam/a11y.xml +3 -3
  133. package/dist/specs/components/beam/props.xml +22 -1
  134. package/dist/specs/components/beam/usage.xml +1 -0
  135. package/dist/specs/components/disclosure/a11y.xml +9 -0
  136. package/dist/specs/components/disclosure/meta.xml +20 -0
  137. package/dist/specs/components/disclosure/patterns.xml +55 -0
  138. package/dist/specs/components/disclosure/props.xml +54 -0
  139. package/dist/specs/components/disclosure/usage.xml +11 -0
  140. package/dist/specs/components/meter/patterns.xml +12 -0
  141. package/dist/specs/components/meter/props.xml +7 -0
  142. package/dist/specs/components/meter/usage.xml +2 -0
  143. package/dist/specs/components/number-field/a11y.xml +10 -0
  144. package/dist/specs/components/number-field/meta.xml +21 -0
  145. package/dist/specs/components/number-field/patterns.xml +43 -0
  146. package/dist/specs/components/number-field/props.xml +35 -0
  147. package/dist/specs/components/number-field/usage.xml +12 -0
  148. package/dist/specs/components/otp-field/a11y.xml +10 -0
  149. package/dist/specs/components/otp-field/meta.xml +20 -0
  150. package/dist/specs/components/otp-field/patterns.xml +66 -0
  151. package/dist/specs/components/otp-field/props.xml +29 -0
  152. package/dist/specs/components/otp-field/usage.xml +13 -0
  153. package/dist/specs/components/prose/a11y.xml +7 -0
  154. package/dist/specs/components/prose/meta.xml +18 -0
  155. package/dist/specs/components/prose/patterns.xml +59 -0
  156. package/dist/specs/components/prose/props.xml +37 -0
  157. package/dist/specs/components/prose/usage.xml +12 -0
  158. package/dist/specs/components/separator/props.xml +3 -0
  159. package/dist/specs/components/separator/usage.xml +1 -0
  160. package/dist/specs/components/text/props.xml +2 -2
  161. package/dist/specs/components/text/usage.xml +1 -0
  162. package/dist/specs/components/textfield/meta.xml +1 -0
  163. package/dist/specs/components/textfield/props.xml +6 -1
  164. package/dist/specs/components/textfield/usage.xml +2 -1
  165. package/dist/specs/components/title/props.xml +2 -2
  166. package/dist/specs/components/title/usage.xml +1 -0
  167. package/dist/specs/index.xml +41 -1
  168. package/package.json +2 -2
@@ -19,7 +19,7 @@
19
19
  <description>Effect family: rotating border, bottom line travel, or pulse breathe (outside/inside).</description>
20
20
  </prop>
21
21
  <prop name="size" kind="react">
22
- <description>Border-only size preset (small compact / medium card). Ignored for other variants.</description>
22
+ <description>Size preset for border geometry and pulse-inside inner glow band (small compact / medium card). Ignored for line and pulse-outside.</description>
23
23
  </prop>
24
24
  <prop name="color" kind="react">
25
25
  <description>Beam color: primary → --global-primary, highlight token name → --highlight-*, colorful → upstream neon multi-stop RGB palette.</description>
@@ -81,10 +81,31 @@
81
81
  <prop name="hue" kind="css">
82
82
  <description>Pulse hue drift angle written by the shared pulse driver.</description>
83
83
  </prop>
84
+ <prop name="hue-base" kind="css">
85
+ <description>Base hue for hue-rotate filters on glow layers.</description>
86
+ </prop>
87
+ <prop name="stroke-opacity" kind="css">
88
+ <description>Opacity of the stroke/conic layer; variant CSS may override.</description>
89
+ </prop>
90
+ <prop name="inner-opacity" kind="css">
91
+ <description>Opacity of the inner glow layer; variant CSS may override.</description>
92
+ </prop>
93
+ <prop name="bloom-opacity" kind="css">
94
+ <description>Opacity of the bloom layer; variant CSS may override.</description>
95
+ </prop>
84
96
  <prop name="pulse-glow-sx" kind="css">
85
97
  <description>Per-axis X scale for pulse-outside glow geometry relative to a 350×140 reference.</description>
86
98
  </prop>
87
99
  <prop name="pulse-glow-sy" kind="css">
88
100
  <description>Per-axis Y scale for pulse-outside glow geometry relative to a 350×140 reference.</description>
89
101
  </prop>
102
+ <prop name="pulse-glow-boost" kind="css">
103
+ <description>Extra pulse-outside glow intensity multiplier (internal default 1; not a React prop).</description>
104
+ </prop>
105
+ <prop name="core-blur" kind="css">
106
+ <description>Core glow blur radius (BorderBeam glowSize=1 default).</description>
107
+ </prop>
108
+ <prop name="bloom-blur" kind="css">
109
+ <description>Bloom layer blur radius (BorderBeam glowSize=1 default).</description>
110
+ </prop>
90
111
  </props>
@@ -5,6 +5,7 @@
5
5
  <do>Pick `variant` for the job: `border` spin, `line` travel, `pulse-outside` / `pulse-inside` breathe — use Glow instead when the highlight should follow the pointer</do>
6
6
  <do>Use sparingly as a focal accent — shared pulse rAF still paints per instance; prefer one Beam per view</do>
7
7
  <dont>Treating Beam as Surface color/padding/border chrome — nest Surface/Stack children for the real card</dont>
8
+ <dont>Confusing prefers-reduced-motion (static rest stays visible) with `animate={false}` (effect fades away)</dont>
8
9
  <dont>Relying on Beam for keyboard focus or status — decorative only</dont>
9
10
  <dont>Expecting theme light/dark auto-tuning — colors are token-driven and theme-agnostic</dont>
10
11
  <dont>Scattering many Beam instances on one page</dont>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <a11y surface="disclosure">
3
+ <rule>Trigger is the disclosing control; Base UI wires expanded/controls relationship to the Panel</rule>
4
+ <rule>Accessible name comes from Trigger children, or explicit aria-label / aria-labelledby when icon-only</rule>
5
+ <rule>Trigger icons are decorative (aria-hidden); open/closed is communicated via Base UI attributes/ARIA, not icon alone</rule>
6
+ <rule>Disabled root ignores pointer and keyboard activation</rule>
7
+ <rule>prefers-reduced-motion disables Panel height and icon interpolate transitions; open/close still works</rule>
8
+ <rule>Do not re-apply widget role/aria that Base UI Collapsible already emits</rule>
9
+ </a11y>
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <meta id="disclosure" title="Disclosure" category="layout" shared_contract="disclosure">
3
+ <summary>Single-section expand/collapse wrapping Base UI Collapsible. Default Trigger is Surface with render → Collapsible Trigger; Panel is a height motion shell with no default content padding. Use Accordion for multi-item lists.</summary>
4
+ <exports>
5
+ <export name="Disclosure" />
6
+ </exports>
7
+ <related>
8
+ <ref id="accordion" />
9
+ <ref id="surface" />
10
+ <ref id="toggle-button" />
11
+ <ref id="stack" />
12
+ </related>
13
+ <units>
14
+ <unit kind="a11y" href="a11y.xml" />
15
+ <unit kind="props" href="props.xml" />
16
+ <unit kind="usage" href="usage.xml" />
17
+ <unit kind="patterns" href="patterns.xml" />
18
+ </units>
19
+ <base_ui href="https://base-ui.com/react/components/collapsible#api-reference" />
20
+ </meta>
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <patterns surface="disclosure">
3
+ <example title="Default Surface Trigger + Panel">
4
+ <tsx><![CDATA[
5
+ <Disclosure>
6
+ <Disclosure.Trigger hPadding="m" radius="m" vPadding="m">
7
+ Shipping details
8
+ </Disclosure.Trigger>
9
+ <Disclosure.Panel>
10
+ <Stack hPadding="m" vPadding="m">
11
+ <Text tone="muted">Orders ship within 2 business days.</Text>
12
+ </Stack>
13
+ </Disclosure.Panel>
14
+ </Disclosure>
15
+ ]]></tsx>
16
+ <notes>Default Trigger = Surface with render → Collapsible.Trigger; hoverColor defaults to 2. Panel is motion-only — pad children in the story/app.</notes>
17
+ </example>
18
+
19
+ <example title="Custom icons with interpolate">
20
+ <tsx><![CDATA[
21
+ <Disclosure>
22
+ <Disclosure.Trigger
23
+ hPadding="m"
24
+ interpolateIcons
25
+ openIcon={<Xmark size="1rem" />}
26
+ radius="m"
27
+ restingIcon={<Plus size="1rem" />}
28
+ vPadding="m"
29
+ >
30
+ Advanced
31
+ </Disclosure.Trigger>
32
+ <Disclosure.Panel>
33
+ <Stack hPadding="m" vPadding="m">
34
+ {/* advanced controls */}
35
+ </Stack>
36
+ </Disclosure.Panel>
37
+ </Disclosure>
38
+ ]]></tsx>
39
+ <notes>ToggleButton-style resting/open icons; interpolate opt-in. For multi-item lists use Accordion instead.</notes>
40
+ </example>
41
+
42
+ <example title="Custom Trigger render">
43
+ <tsx><![CDATA[
44
+ <Disclosure>
45
+ <Disclosure.Trigger render={<Button variant="secondary" />}>
46
+ Show more
47
+ </Disclosure.Trigger>
48
+ <Disclosure.Panel>
49
+ <Text>Extra details</Text>
50
+ </Disclosure.Panel>
51
+ </Disclosure>
52
+ ]]></tsx>
53
+ <notes>Consumer render replaces the whole Surface + primitive compose; Surface defaults do not apply.</notes>
54
+ </example>
55
+ </patterns>
@@ -0,0 +1,54 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <props surface="disclosure">
3
+ <when_to_use>
4
+ <item>Single-section progressive disclosure (show more, optional details, FAQ item alone)</item>
5
+ <item>Expand/collapse one block with Surface chrome Trigger and optional icon pair</item>
6
+ </when_to_use>
7
+ <when_not_to_use>
8
+ <item>Multi-item collapsible lists — use Accordion</item>
9
+ <item>Expecting default Panel content padding — Panel is a motion shell only</item>
10
+ <item>Primary navigation that should use links, Tabs, or routes</item>
11
+ </when_not_to_use>
12
+ <prop name="Trigger.restingIcon" kind="react">
13
+ <description>Decorative icon while the panel is closed. Defaults to ChromeChevronEnd when both icon slots are omitted.</description>
14
+ </prop>
15
+ <prop name="Trigger.openIcon" kind="react">
16
+ <description>Decorative icon while the panel is open. Defaults to ChromeChevronDown when both icon slots are omitted. When only restingIcon is set, that icon shows in both states.</description>
17
+ </prop>
18
+ <prop name="Trigger.interpolateIcons" kind="react">
19
+ <description>When dual icons are present, crossfade and light-rotate between them (`data-interpolate=&quot;true&quot;`). When false, swap instantly with no transition.</description>
20
+ </prop>
21
+ <prop name="Trigger.iconPosition" kind="react">
22
+ <description>Logical side of the label where the icon slot sits (`start` | `end`). Default `end`.</description>
23
+ </prop>
24
+ <prop name="Trigger.color" kind="react">
25
+ <description>Surface resting background on the default Trigger host. Omitted on consumer Trigger render.</description>
26
+ </prop>
27
+ <prop name="Trigger.hoverColor" kind="react">
28
+ <description>Surface hover background on the default Trigger host. Defaults to level 2 when omitted. Skipped when consumer supplies Trigger render.</description>
29
+ </prop>
30
+ <prop name="Trigger.border" kind="react">
31
+ <description>Surface contrast border on the default Trigger host.</description>
32
+ </prop>
33
+ <prop name="Trigger.borderStyle" kind="react">
34
+ <description>Surface border style when border is set on the default Trigger host.</description>
35
+ </prop>
36
+ <prop name="Trigger.radius" kind="react">
37
+ <description>Surface corner radius on the default Trigger host.</description>
38
+ </prop>
39
+ <prop name="Trigger.hPadding" kind="react">
40
+ <description>Surface inline padding on the default Trigger host. Defaults to `m` when omitted. Skipped when consumer supplies Trigger render.</description>
41
+ </prop>
42
+ <prop name="Trigger.vPadding" kind="react">
43
+ <description>Surface block padding on the default Trigger host. Defaults to `s` when omitted. Skipped when consumer supplies Trigger render.</description>
44
+ </prop>
45
+ <prop name="Trigger.render" kind="react">
46
+ <description>Replaces the whole default Surface + Collapsible Trigger compose with a custom host.</description>
47
+ </prop>
48
+ <prop name="Panel.hiddenUntilFound" kind="react">
49
+ <description>Allows browser find-in-page to expand the panel; Base UI Collapsible Panel pass-through.</description>
50
+ </prop>
51
+ <prop name="Panel.keepMounted" kind="react">
52
+ <description>Keeps the panel in the DOM while closed; Base UI Collapsible Panel pass-through.</description>
53
+ </prop>
54
+ </props>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <usage surface="disclosure">
3
+ <do>Compose `Disclosure` + `Disclosure.Trigger` + `Disclosure.Panel` for a single expandable section</do>
4
+ <do>Spread Surface chrome on Trigger (`color`, `hoverColor`, `border`, `radius`, padding) when using the default host</do>
5
+ <do>Supply Panel children layout (Stack/padding) yourself — Panel has no default content padding</do>
6
+ <do>Use `restingIcon` / `openIcon` / `interpolateIcons` for ToggleButton-style icon pairs; omit both for chrome chevron End/Down</do>
7
+ <do>Pass Trigger `render` when replacing the Surface compose entirely</do>
8
+ <dont>Using Accordion for a single section — Accordion is multi-item</dont>
9
+ <dont>Expecting Accordion-like default Panel padding from Disclosure.Panel</dont>
10
+ <dont>Relying on icon animation alone for open/closed meaning under reduced motion</dont>
11
+ </usage>
@@ -50,4 +50,16 @@
50
50
  ]]></tsx>
51
51
  <notes>From preview-grid `daily-activity-goal` nested tips sheet. Meter for score-within-range; LinearProgress stays on the live activity track outside the dialog.</notes>
52
52
  </example>
53
+
54
+ <example title="Highlight variants">
55
+ <tsx><![CDATA[
56
+ <Stack rowGap="m">
57
+ <Meter label="Health" renderValue value={92} variant="green" />
58
+ <Meter label="Latency" renderValue value={38} variant="yellow" />
59
+ <Meter label="Errors" renderValue value={12} variant="red" />
60
+ <Meter label="Quota" renderValue value={64} variant="blue" />
61
+ </Stack>
62
+ ]]></tsx>
63
+ <notes>`variant` highlight tokens tint track wash + indicator together (Chip-aligned). Default `primary` keeps brand indicator + contrast track.</notes>
64
+ </example>
53
65
  </patterns>
@@ -4,6 +4,7 @@
4
4
  <item>Use for storage usage, battery level, capacity, or score within a known range.</item>
5
5
  <item>Use with a label when the metric needs a visible name.</item>
6
6
  <item>Use with `renderValue` when the formatted value should appear beside the label.</item>
7
+ <item>Use highlight `variant` values when the track and indicator should share a semantic color.</item>
7
8
  </when_to_use>
8
9
  <when_not_to_use>
9
10
  <item>Use LinearProgress for in-progress tasks or indeterminate work.</item>
@@ -19,12 +20,18 @@
19
20
  <prop name="renderValue" kind="react">
20
21
  <description>Shows the current value beside the label. Pass `true` for Base UI default formatting, or a function matching `Meter.Value` `children` to customize the printed label.</description>
21
22
  </prop>
23
+ <prop name="variant" kind="react">
24
+ <description>Selects track and indicator colors. `primary` uses brand primary on the indicator; highlight token names tint both track (wash) and indicator via `--highlight-*`, matching Chip highlight variants.</description>
25
+ </prop>
22
26
  <prop name="indicator-color" kind="css">
23
27
  <description>Determinate meter indicator color.</description>
24
28
  </prop>
25
29
  <prop name="track-background" kind="css">
26
30
  <description>Meter track background color.</description>
27
31
  </prop>
32
+ <prop name="track-opacity" kind="css">
33
+ <description>Highlight variant track wash opacity mix against the indicator color.</description>
34
+ </prop>
28
35
  <prop name="track-size" kind="css">
29
36
  <description>Meter track thickness on the root.</description>
30
37
  </prop>
@@ -4,10 +4,12 @@
4
4
  <do>Labeled metrics: `label` + `renderValue` + optional `description`; tune print with Base UI `format` / `locale`</do>
5
5
  <do>Workspace stacks: Stack `rowGap` of Meters — or nest one Meter inside Surface for sheet / tip chrome</do>
6
6
  <do>Rich labels: pass a Stack row (icon + text) as `label` when needed — no custom label CSS</do>
7
+ <do>Color-coded metrics via highlight `variant` (`green`, `red`, `yellow`, …) or default `primary` — tints track wash + indicator like Chip</do>
7
8
  <do>Prefer LinearProgress for in-progress or indeterminate tasks (`value={null}`) — Meter has no indeterminate mode</do>
8
9
  <dont>Using Meter as an interactive value control — use Slider</dont>
9
10
  <dont>Using Meter for indeterminate or in-progress work — use LinearProgress</dont>
10
11
  <dont>Modeling invalid or disabled meter state — Base UI Meter exposes neither</dont>
11
12
  <dont>Hiding the metric name when multiple meters share a view</dont>
12
13
  <dont>Passing `value={null}` — Meter `value` is required `number`</dont>
14
+ <dont>Reinventing highlight track/indicator colors with raw `--highlight-*` CSS when `variant` covers the token</dont>
13
15
  </usage>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <a11y surface="number-field">
3
+ <rule>Visible `label` on `NumberField` names the numeric input via Field.Label / htmlFor.</rule>
4
+ <rule>Description uses Field description / `aria-describedby` while valid.</rule>
5
+ <rule>Error copy shares the helper slot and replaces description while invalid and dirty (same as Textfield).</rule>
6
+ <rule>Internal steppers are icon-only IconButtons named `Decrement` and `Increment`.</rule>
7
+ <rule>Label scrub is optional chrome (`labelScrub`, default true when label present). Disable with `labelScrub={false}` or omit label.</rule>
8
+ <rule>Focus order follows `stepperPlacement`: split → decrement, input, increment; grouped → input then both. Grouped visual side follows document direction (inline-end).</rule>
9
+ <rule>When `description` is a string, NumberField sets `aria-roledescription` on the numeric input to that string; otherwise Base UI default remains.</rule>
10
+ </a11y>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <meta id="number-field" title="NumberField" category="form" shared_contract="number-field">
3
+ <summary>Single public NumberField with Field chrome, internal IconButton steppers, and optional label scrub. Group / Decrement / Increment / ScrubArea stay internal.</summary>
4
+ <exports>
5
+ <export name="NumberField" />
6
+ </exports>
7
+ <related>
8
+ <ref id="textfield" />
9
+ <ref id="icon-button" />
10
+ <ref id="fieldset" />
11
+ <ref id="text" />
12
+ <ref id="stack" />
13
+ </related>
14
+ <units>
15
+ <unit kind="a11y" href="a11y.xml" />
16
+ <unit kind="props" href="props.xml" />
17
+ <unit kind="usage" href="usage.xml" />
18
+ <unit kind="patterns" href="patterns.xml" />
19
+ </units>
20
+ <base_ui href="https://base-ui.com/react/components/number-field#api-reference" />
21
+ </meta>
@@ -0,0 +1,43 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <patterns surface="number-field">
3
+ <example title="Labeled amount">
4
+ <tsx><![CDATA[
5
+ <NumberField
6
+ defaultValue={100}
7
+ label="Amount"
8
+ description="Enter the amount in your local currency."
9
+ />
10
+ ]]></tsx>
11
+ <notes>Default split steppers. Label scrub on when label is present.</notes>
12
+ </example>
13
+
14
+ <example title="Form name + bounds">
15
+ <tsx><![CDATA[
16
+ <Form>
17
+ <NumberField name="quantity" defaultValue={1} min={0} max={99} step={1} label="Quantity" />
18
+ </Form>
19
+ ]]></tsx>
20
+ <notes>`name` / min / max / step / label on NumberField. `Form` is `@base-ui/react/form`.</notes>
21
+ </example>
22
+
23
+ <example title="Stepper placement grouped">
24
+ <tsx><![CDATA[
25
+ <NumberField defaultValue={5} label="Count" stepperPlacement="grouped" />
26
+ ]]></tsx>
27
+ <notes>Both steppers at inline-end (LTR right / RTL left). Steppers are fixed secondary IconButtons.</notes>
28
+ </example>
29
+
30
+ <example title="Full width input grow">
31
+ <tsx><![CDATA[
32
+ <NumberField defaultValue={25} label="Amount" fullWidth />
33
+ ]]></tsx>
34
+ <notes>Row fills the column; only the numeric input flex-grows.</notes>
35
+ </example>
36
+
37
+ <example title="Plain label without scrub">
38
+ <tsx><![CDATA[
39
+ <NumberField defaultValue={10} label="Amount" labelScrub={false} />
40
+ ]]></tsx>
41
+ <notes>Field label without ScrubArea.</notes>
42
+ </example>
43
+ </patterns>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <props surface="number-field">
3
+ <when_to_use>
4
+ <item>Numeric values with optional increment/decrement and label scrub</item>
5
+ <item>Form fields that submit a number via `name` (min/max/step/format on the same NumberField)</item>
6
+ <item>Textfield-aligned label / description / error with Field validation</item>
7
+ </when_to_use>
8
+ <when_not_to_use>
9
+ <item>Exposing Group / Decrement / Increment / ScrubArea as public parts — they stay internal</item>
10
+ <item>Textfield start/end addon API or custom stepper children in v1</item>
11
+ <item>Exposing a NumberField size or variant prop — steppers stay fixed IconButton `size=&quot;s&quot;` / `variant=&quot;secondary&quot;`</item>
12
+ <item>Composing a public `NumberField.Input` — chrome and steppers live on NumberField</item>
13
+ </when_not_to_use>
14
+ <prop name="description" kind="react">
15
+ <description>Helper copy rendered with `Field.Description` and `Text` while the field is valid. When a string, also sets `aria-roledescription` on the numeric input.</description>
16
+ </prop>
17
+ <prop name="error" kind="react">
18
+ <description>Error copy rendered with `Field.Error` and `Text` in the same slot as `description`. Replaces description while invalid and dirty.</description>
19
+ </prop>
20
+ <prop name="fitContent" kind="react">
21
+ <description>When `true`, sets `field-sizing: content` on the numeric input only. Steppers stay intrinsic.</description>
22
+ </prop>
23
+ <prop name="fullWidth" kind="react">
24
+ <description>When `true`, field and control row fill the column; only the numeric input flex-grows. Steppers stay intrinsic. Prefer over CSS `width: 100%` on the field.</description>
25
+ </prop>
26
+ <prop name="label" kind="react">
27
+ <description>Visible label rendered with shared internal `FieldLabel`. Hosts scrub when `labelScrub` is true.</description>
28
+ </prop>
29
+ <prop name="labelScrub" kind="react">
30
+ <description>When `true` (default) and `label` is set, wrap the label in Base UI scrub. When `false` or no label, plain field label.</description>
31
+ </prop>
32
+ <prop name="stepperPlacement" kind="react">
33
+ <description>Where steppers sit relative to the input: `split` (default, button|input|button) or `grouped` (both at inline-end; physical right in LTR, left in RTL via document direction).</description>
34
+ </prop>
35
+ </props>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <usage surface="number-field">
3
+ <do>Use a single `NumberField` for value/min/max/step/name plus label/helper/steppers</do>
4
+ <do>Put Field validation props (`invalid`, `dirty`, `touched`, `validate`, …) on NumberField</do>
5
+ <do>Steppers are fixed IconButton `size=&quot;s&quot;` / `variant=&quot;secondary&quot;` with uniform addon padding — do not expose variant/size</do>
6
+ <do>Use `fullWidth` when the numeric input should grow; steppers stay compact</do>
7
+ <do>Turn off label scrub with `labelScrub={false}` when drag-on-label is unwanted</do>
8
+ <dont>Export or compose public Group / Decrement / Increment / ScrubArea / ScrubAreaCursor</dont>
9
+ <dont>Compose a public `NumberField.Input` — there is no Input part</dont>
10
+ <dont>Add Textfield start/end addon API or custom stepper children in v1</dont>
11
+ <dont>Invent CSS width hacks when `fullWidth` / `fitContent` cover sizing</dont>
12
+ </usage>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <a11y surface="otp-field">
3
+ <rule>One Field: visible `label` names the first slot via Field.Label / htmlFor. Do not put aria-label on the first Input.</rule>
4
+ <rule>Slots after the first get `aria-label` `Character N of {length}` in English when the consumer omits `aria-label`. Consumer `aria-label` wins when passed.</rule>
5
+ <rule>Description and error copy live on the OTPField root helper slot (dirty+invalid), not per slot.</rule>
6
+ <rule>`OTPField.Separator` is a separator, not an input, and is not counted in `length`.</rule>
7
+ <rule>Slot host is always a native `input`. Chrome is Textfield `controlOnly` (no second Field).</rule>
8
+ <rule>Focus ring is per active slot (`:focus`). Input `data-focused` means any slot is focused — do not paint chrome from it.</rule>
9
+ <rule>Invalid wiggle is one-shot chrome only. Error copy / `aria-invalid` still name the error. Reduced motion skips the animation.</rule>
10
+ </a11y>
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <meta id="otp-field" title="OTPField" category="form" shared_contract="otp-field">
3
+ <summary>Field-wrapped one-time code slots. Default slots compose Textfield controlOnly; one label/helper on OTPField.</summary>
4
+ <exports>
5
+ <export name="OTPField" />
6
+ </exports>
7
+ <related>
8
+ <ref id="textfield" />
9
+ <ref id="fieldset" />
10
+ <ref id="text" />
11
+ <ref id="stack" />
12
+ </related>
13
+ <units>
14
+ <unit kind="a11y" href="a11y.xml" />
15
+ <unit kind="props" href="props.xml" />
16
+ <unit kind="usage" href="usage.xml" />
17
+ <unit kind="patterns" href="patterns.xml" />
18
+ </units>
19
+ <base_ui href="https://base-ui.com/react/components/otp-field#api-reference" />
20
+ </meta>
@@ -0,0 +1,66 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <patterns surface="otp-field">
3
+ <example title="Labeled six-slot code">
4
+ <tsx><![CDATA[
5
+ <OTPField
6
+ length={6}
7
+ label="Verification code"
8
+ description="Enter the 6-character code we sent to your device."
9
+ >
10
+ {Array.from({ length: 6 }, (_, slotIndex) => (
11
+ <OTPField.Input key={`character-${slotIndex + 1}`} />
12
+ ))}
13
+ </OTPField>
14
+ ]]></tsx>
15
+ <notes>Explicit Inputs. First slot uses the field label; later slots get generated names.</notes>
16
+ </example>
17
+
18
+ <example title="Form name + autoSubmit">
19
+ <tsx><![CDATA[
20
+ <Form>
21
+ <OTPField length={6} name="verificationCode" label="Verification code" autoSubmit>
22
+ <OTPField.Input />
23
+ <OTPField.Input />
24
+ <OTPField.Input />
25
+ <OTPField.Input />
26
+ <OTPField.Input />
27
+ <OTPField.Input />
28
+ </OTPField>
29
+ </Form>
30
+ ]]></tsx>
31
+ <notes>One concatenated form value. `autoSubmit` submits when complete. `Form` is `@base-ui/react/form`.</notes>
32
+ </example>
33
+
34
+ <example title="Grouped slots with Separator">
35
+ <tsx><![CDATA[
36
+ <OTPField length={6} label="Verification code">
37
+ <Stack columnGap="s" direction="row">
38
+ <OTPField.Input />
39
+ <OTPField.Input />
40
+ <OTPField.Input />
41
+ </Stack>
42
+ <OTPField.Separator />
43
+ <Stack columnGap="s" direction="row">
44
+ <OTPField.Input />
45
+ <OTPField.Input />
46
+ <OTPField.Input />
47
+ </Stack>
48
+ </OTPField>
49
+ ]]></tsx>
50
+ <notes>Separator is not an input and is not counted in `length`. Stack owns group gaps.</notes>
51
+ </example>
52
+
53
+ <example title="Equal-grow in a form column">
54
+ <tsx><![CDATA[
55
+ <OTPField length={6} label="Verification code" fullWidth>
56
+ <OTPField.Input />
57
+ <OTPField.Input />
58
+ <OTPField.Input />
59
+ <OTPField.Input />
60
+ <OTPField.Input />
61
+ <OTPField.Input />
62
+ </OTPField>
63
+ ]]></tsx>
64
+ <notes>Default hugs. `fullWidth` fills the column and grows slots equally.</notes>
65
+ </example>
66
+ </patterns>
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <props surface="otp-field">
3
+ <when_to_use>
4
+ <item>One-time codes, verification codes, and recovery codes as a single labeled field</item>
5
+ <item>Numeric, alphanumeric, or masked slot entry with form `name` submit of the concatenated value</item>
6
+ <item>Grouped slot rows with `OTPField.Separator` and Stack, not a `groups` prop</item>
7
+ </when_to_use>
8
+ <when_not_to_use>
9
+ <item>Auto-generating Inputs from `length` — always list one `OTPField.Input` per slot</item>
10
+ <item>Per-slot label, description, or error — Field chrome is on OTPField only</item>
11
+ <item>Swapping the slot host via `render` — host is always a native `input`; chrome is Textfield `controlOnly`</item>
12
+ <item>Inventing CSS `width: 100%` on slots when OTPField `fullWidth` covers equal-grow</item>
13
+ </when_not_to_use>
14
+ <prop name="description" kind="react">
15
+ <description>Helper copy rendered with `Field.Description` and `Text` while the field is valid.</description>
16
+ </prop>
17
+ <prop name="error" kind="react">
18
+ <description>Error copy rendered with `Field.Error` and `Text` in the same slot as `description`. Replaces description while the field is invalid and dirty.</description>
19
+ </prop>
20
+ <prop name="fullWidth" kind="react">
21
+ <description>When `true`, the field is `inline-size: 100%` and the inner slot Stack uses `fullWidth` + `expandChildren` so slots grow equally. Prefer this over CSS `width: 100%` on slots.</description>
22
+ </prop>
23
+ <prop name="label" kind="react">
24
+ <description>Visible label rendered with shared internal `FieldLabel`. Names the first slot.</description>
25
+ </prop>
26
+ <prop name="length" kind="react">
27
+ <description>Required slot count for clamp, complete, and hidden validation markup. Does not spawn Inputs — list exactly this many `OTPField.Input` children.</description>
28
+ </prop>
29
+ </props>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <usage surface="otp-field">
3
+ <do>List exactly `length` `OTPField.Input` children (Array.from or explicit)</do>
4
+ <do>Put `label` / `description` / `error` on `OTPField`</do>
5
+ <do>Let the first slot take the field label; later slots get generated `Character N of {length}` unless you pass `aria-label`</do>
6
+ <do>Group slots with Stack + `OTPField.Separator` when the code is shown as chunks</do>
7
+ <do>Span the form column with `OTPField` `fullWidth` so slots grow equally</do>
8
+ <do>Keep error copy on `OTPField` — invalid wiggle is extra chrome, not the only signal</do>
9
+ <dont>Pass `render` on Input — slot is always a native `input`; chrome is Textfield `controlOnly`</dont>
10
+ <dont>Put label/description/error on each slot</dont>
11
+ <dont>Expect `OTPField` to auto-generate Inputs from `length`</dont>
12
+ <dont>Invent a `groups` prop or width CSS on slots when Stack / `fullWidth` cover layout</dont>
13
+ </usage>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <a11y surface="prose">
3
+ <rule>Prose is grouping, not a widget — do not set a role on the root</rule>
4
+ <rule>Default root is a generic `div`; it does not require an accessible name</rule>
5
+ <rule>Landmark semantics only when the consumer replaces the root (`render={&lt;article /&gt;}` or similar) and names the landmark if needed</rule>
6
+ <rule>Children keep their own roles (headings, lists, links); Prose does not restyle or re-role them</rule>
7
+ </a11y>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <meta id="prose" title="Prose" category="typography" shared_contract="prose">
3
+ <summary>Grouping region that applies heading-aware em rhythm to direct document blocks.</summary>
4
+ <exports>
5
+ <export name="Prose" />
6
+ </exports>
7
+ <related>
8
+ <ref id="text" />
9
+ <ref id="title" />
10
+ <ref id="stack" />
11
+ </related>
12
+ <units>
13
+ <unit kind="a11y" href="a11y.xml" />
14
+ <unit kind="props" href="props.xml" />
15
+ <unit kind="usage" href="usage.xml" />
16
+ <unit kind="patterns" href="patterns.xml" />
17
+ </units>
18
+ </meta>
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <patterns surface="prose">
3
+ <example title="Article with Title and Text">
4
+ <tsx><![CDATA[
5
+ <Prose render={<article />}>
6
+ <Title size="2" lineHeight="s" render={<h2 />}>
7
+ Heading-aware document rhythm
8
+ </Title>
9
+ <Text render={<p />}>
10
+ Direct heading and paragraph children pick up Prose gaps. Type stays on Title and Text.
11
+ </Text>
12
+ <Text render={<p />}>A second paragraph uses the block gap, not the heading-end gap.</Text>
13
+ </Prose>
14
+ ]]></tsx>
15
+ <notes>Default `gap="l"`. Landmark via `render={<article />}`. Title in Prose uses `lineHeight="s"`. Do not wrap these blocks in Stack for rhythm.</notes>
16
+ </example>
17
+
18
+ <example title="Density and region align">
19
+ <tsx><![CDATA[
20
+ <Prose gap="s" align="center">
21
+ <Title size="3" lineHeight="s" render={<h3 />}>
22
+ Compact notes
23
+ </Title>
24
+ <Text render={<p />}>One Prose `align` sets the region. Omit Title/Text `align` so they inherit.</Text>
25
+ </Prose>
26
+ ]]></tsx>
27
+ <notes>`s` &lt; `m` &lt; `l`. `align` maps to `--vui-prose-align` + `text-align` on the root. Title `lineHeight="s"`.</notes>
28
+ </example>
29
+
30
+ <example title="Line height on body">
31
+ <tsx><![CDATA[
32
+ <Prose>
33
+ <Title size="2" lineHeight="s" render={<h2 />}>
34
+ Tight heading, chosen body leading
35
+ </Title>
36
+ <Text render={<p />} lineHeight="l">
37
+ Headings in Prose stay on Title `lineHeight="s"`. Body leading is a Text prop — this paragraph uses `l`.
38
+ </Text>
39
+ <Text render={<p />} lineHeight="s">
40
+ A following paragraph can use `lineHeight="s"` when the article should sit denser.
41
+ </Text>
42
+ </Prose>
43
+ ]]></tsx>
44
+ <notes>Prose does not own leading. Title inside Prose → `lineHeight="s"`. Text `lineHeight` per block.</notes>
45
+ </example>
46
+
47
+ <example title="Span hosts stay out">
48
+ <tsx><![CDATA[
49
+ <Prose>
50
+ <Title size="4" lineHeight="s">
51
+ This Title is a span — no Prose heading gap
52
+ </Title>
53
+ <Text>This Text is a span — no Prose block gap.</Text>
54
+ <Text render={<p />}>This paragraph is a matching block.</Text>
55
+ </Prose>
56
+ ]]></tsx>
57
+ <notes>Default Title/Text hosts are `span`. Use `render` for h1–h6 / `p` when they should join rhythm. Title still `lineHeight="s"`.</notes>
58
+ </example>
59
+ </patterns>