@antadesign/anta 0.3.26 → 0.3.28

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 (133) hide show
  1. package/README.md +26 -28
  2. package/dist/anta_helpers.d.ts +8 -0
  3. package/dist/anta_helpers.js +18 -0
  4. package/dist/box-types.d.ts +1 -1
  5. package/dist/bundle.css +1 -1
  6. package/dist/bundle.js +36 -42
  7. package/dist/capture-types.d.ts +156 -0
  8. package/dist/components/Banner.js +2 -2
  9. package/dist/components/Box.d.ts +15 -0
  10. package/dist/components/Box.js +3 -11
  11. package/dist/components/Button.js +2 -2
  12. package/dist/components/Capture.d.ts +39 -0
  13. package/dist/components/Capture.js +36 -0
  14. package/dist/components/Card.js +2 -2
  15. package/dist/components/Checkbox.d.ts +10 -11
  16. package/dist/components/Checkbox.js +5 -13
  17. package/dist/components/Expander.js +2 -2
  18. package/dist/components/Input.js +2 -2
  19. package/dist/components/InputTime.js +2 -2
  20. package/dist/components/Loader.js +2 -1
  21. package/dist/components/MenuItem.d.ts +7 -8
  22. package/dist/components/MenuItem.js +4 -4
  23. package/dist/components/Progress.js +2 -2
  24. package/dist/components/RadioGroup.d.ts +12 -13
  25. package/dist/components/RadioGroup.js +7 -23
  26. package/dist/components/Select.d.ts +12 -7
  27. package/dist/components/Select.js +4 -3
  28. package/dist/components/SelectFaceted.d.ts +7 -5
  29. package/dist/components/SelectFaceted.js +4 -3
  30. package/dist/components/Slider.js +3 -3
  31. package/dist/components/Steps.css +1 -1
  32. package/dist/components/Switch.d.ts +7 -8
  33. package/dist/components/Switch.js +3 -11
  34. package/dist/components/Tabs.js +2 -2
  35. package/dist/components/Tag.d.ts +7 -9
  36. package/dist/components/Tag.js +2 -2
  37. package/dist/components/Text.js +2 -2
  38. package/dist/components/Title.js +2 -2
  39. package/dist/components/capture-props.d.ts +30 -0
  40. package/dist/components/capture-props.js +44 -0
  41. package/dist/elements/a-avatar.css +1 -1
  42. package/dist/elements/a-banner.css +1 -1
  43. package/dist/elements/a-box.d.ts +1 -1
  44. package/dist/elements/a-box.js +11 -3
  45. package/dist/elements/a-button.css +1 -1
  46. package/dist/elements/a-button.d.ts +7 -9
  47. package/dist/elements/a-calendar.css +1 -1
  48. package/dist/elements/a-capture.css +1 -0
  49. package/dist/elements/a-capture.d.ts +10 -0
  50. package/dist/elements/a-capture.js +24 -0
  51. package/dist/elements/a-card.css +1 -1
  52. package/dist/elements/a-checkbox.css +1 -1
  53. package/dist/elements/a-checkbox.js +4 -4
  54. package/dist/elements/a-dialog.css +1 -1
  55. package/dist/elements/a-expander.css +1 -1
  56. package/dist/elements/a-expander.js +1 -0
  57. package/dist/elements/a-input-time.css +1 -1
  58. package/dist/elements/a-input-time.js +5 -7
  59. package/dist/elements/a-input.css +1 -1
  60. package/dist/elements/a-input.js +4 -6
  61. package/dist/elements/a-menu-item.css +1 -1
  62. package/dist/elements/a-menu.css +1 -1
  63. package/dist/elements/a-progress.css +1 -1
  64. package/dist/elements/a-radio.css +1 -1
  65. package/dist/elements/a-slider.css +1 -1
  66. package/dist/elements/a-slider.js +6 -9
  67. package/dist/elements/a-switch.css +1 -1
  68. package/dist/elements/a-tab.css +1 -1
  69. package/dist/elements/a-tabs.css +1 -1
  70. package/dist/elements/a-tag.css +1 -1
  71. package/dist/elements/a-text.css +1 -1
  72. package/dist/elements/a-text.js +1 -0
  73. package/dist/elements/a-title.css +1 -1
  74. package/dist/elements/a-tooltip.css +1 -1
  75. package/dist/elements/a-tooltip.d.ts +3 -4
  76. package/dist/elements/a-tooltip.js +0 -1
  77. package/dist/elements/capture-input.d.ts +5 -0
  78. package/dist/elements/capture-input.js +609 -0
  79. package/dist/elements/index.d.ts +1 -0
  80. package/dist/elements/index.js +3 -0
  81. package/dist/general_types.d.ts +56 -23
  82. package/dist/index.d.ts +4 -1
  83. package/dist/index.js +2 -0
  84. package/dist/jsx-runtime.d.ts +2 -1
  85. package/dist/reset.css +1 -1
  86. package/dist/theme-antithesis.css +1 -0
  87. package/dist/theme-antune.css +1 -0
  88. package/dist/tokens.css +1 -1
  89. package/docs/accessibility.md +24 -0
  90. package/docs/changelog.md +79 -0
  91. package/docs/colors.md +141 -0
  92. package/docs/comparison.md +463 -28
  93. package/docs/components/avatar.md +13 -17
  94. package/docs/components/banner.md +13 -27
  95. package/docs/components/box.md +226 -154
  96. package/docs/components/breadcrumbs.md +49 -12
  97. package/docs/components/button.md +48 -37
  98. package/docs/components/capture.md +345 -0
  99. package/docs/components/card.md +17 -38
  100. package/docs/components/checkbox.md +27 -50
  101. package/docs/components/dialog.md +14 -36
  102. package/docs/components/expander.md +15 -40
  103. package/docs/components/icon.md +111 -9
  104. package/docs/components/input-autocomplete.md +9 -11
  105. package/docs/components/input-date.md +33 -23
  106. package/docs/components/input-time.md +15 -23
  107. package/docs/components/input.md +27 -76
  108. package/docs/components/loader.md +7 -5
  109. package/docs/components/menu.md +75 -80
  110. package/docs/components/progress.md +10 -14
  111. package/docs/components/radio.md +28 -46
  112. package/docs/components/select-faceted.md +8 -25
  113. package/docs/components/select.md +33 -105
  114. package/docs/components/slider.md +16 -21
  115. package/docs/components/steps.md +38 -8
  116. package/docs/components/switch.md +16 -19
  117. package/docs/components/tabs.md +52 -40
  118. package/docs/components/tag.md +15 -24
  119. package/docs/components/text.md +10 -23
  120. package/docs/components/title.md +7 -8
  121. package/docs/components/toaster.md +6 -3
  122. package/docs/components/tooltip.md +13 -23
  123. package/docs/index.md +3 -1
  124. package/docs/install-config.md +42 -8
  125. package/docs/normalization.md +48 -3
  126. package/docs/packages/stickers.md +56 -0
  127. package/docs/theming.md +362 -14
  128. package/package.json +7 -4
  129. package/dist/components/InputDate.module.css +0 -1
  130. package/dist/components/Select.module.css +0 -1
  131. package/dist/components/SelectFaceted.module.css +0 -1
  132. package/dist/theme-anta.css +0 -1
  133. /package/dist/{search-index.json → capture-types.js} +0 -0
@@ -92,25 +92,19 @@ works for one at the bottom.
92
92
  `round` makes the track fully round. Pass a number or CSS length for a custom
93
93
  radius.
94
94
 
95
- ### Props
95
+ ## Component props
96
96
 
97
97
  | Prop | Type | Default | Description |
98
98
  |------|------|---------|-------------|
99
- | `hint?` | string | — | Right-aligned hint text (e.g. "3 of 7"). Like `label`, it's not rendered
100
- when custom `children` are provided but still feeds the accessible name. |
101
- | `label?` | string | — | Text label displayed after the percentage, or on its own for
102
- indeterminate progress. When you provide custom `children` (which replace
103
- the default label row), `label` is no longer rendered — but it still
104
- supplies the progressbar's accessible name. |
99
+ | `hint?` | string | — | Right-aligned hint text (e.g. "3 of 7"). Like `label`, it's not rendered when custom `children` are provided but still feeds the accessible name. |
100
+ | `label?` | string | — | Text label displayed after the percentage, or on its own for indeterminate progress. When you provide custom `children` (which replace the default label row), `label` is no longer rendered — but it still supplies the progressbar's accessible name. |
105
101
  | `max?` | number | 100 | Upper bound of the range. |
106
- | `round?` | boolean \| number \| string | — | Fully-round track (`border-radius: 999px`); the fill is clipped to it. Pass a
107
- `number` (px) or a CSS length string for a custom radius. |
102
+ | `round?` | boolean \| number \| string | — | Fully-round track (`border-radius: 999px`); the fill is clipped to it. Pass a `number` (px) or a CSS length string for a custom radius. |
108
103
  | `size?` | 'small' \| 'medium' \| 'large' | medium | Size variant. Scales the track and the default label row together. |
109
- | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color variant, or any literal CSS color for a one-off custom tone (the
110
- surface / indicator / text are derived from it in oklch). Named tones track
111
- light/dark automatically. |
112
- | `value?` | number \| false | — | Current progress value. Omit this prop, or pass `false`, to show
113
- indeterminate progress. Negative values are clamped to 0. |
104
+ | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color variant, or any literal CSS color for a one-off custom tone (the surface / indicator / text are derived from it in oklch). Named tones track light/dark automatically. |
105
+ | `value?` | number \| false | — | Current progress value. Omit this prop, or pass `false`, to show indeterminate progress. Negative values are clamped to 0. |
106
+
107
+ ## Web Component
114
108
 
115
109
  ```html
116
110
  <a-progress style="width: 100%" value="42" max="100" tone="info" role="progressbar"
@@ -158,6 +152,8 @@ is absent, while using Anta's track, fill, tone, and size treatments. Native
158
152
  progress does not render Anta's label or hint structure; give it an accessible
159
153
  name instead.
160
154
 
155
+ ## Styling
156
+
161
157
  ```css
162
158
  /* a fancy bar: rounded track (all sides), a multi-stop gradient fill with a glow,
163
159
  and a crisp hard right edge (the default soft right-edge fade is cleared). */
@@ -57,7 +57,8 @@ one. Any literal CSS color works too, for a one-off custom tone.
57
57
 
58
58
  ```tsx
59
59
  <RadioGroup
60
- toneSelected="brand"
60
+ tone="brand"
61
+ toneScope="selected"
61
62
  defaultValue="a"
62
63
  options={[
63
64
  { value: 'a', label: 'Option A' },
@@ -66,10 +67,10 @@ one. Any literal CSS color works too, for a one-off custom tone.
66
67
  />
67
68
  ```
68
69
 
69
- `toneSelected` tones the **selected option only** — every unselected ring stays
70
- neutral grey. Reach for it instead of `tone` when a resting tinted border would read
71
- as a validation error. Same tone set; set it on the group, or on a single option to
72
- override one.
70
+ `toneScope="selected"` applies the group's `tone` to the **selected option only** —
71
+ every unselected ring stays neutral grey. Use it when a resting tinted border would
72
+ read as a validation error. Set the scope on the group, or on a single option to
73
+ override the group.
73
74
 
74
75
  To color the **label and hint**, there's no prop — add a `color` rule on the
75
76
  option's `a-radio-label` / `a-radio-hint` with a `--text-N-{tone}` value.
@@ -250,50 +251,29 @@ element — `Input`, and the composed `Select` — skip it and expose only
250
251
  <RadioGroup onValueChange={(_e, { value }) => save(value)} options={…} />
251
252
  ```
252
253
 
254
+ ## RadioGroup props
255
+
253
256
  | Prop | Type | Default | Description |
254
257
  |------|------|---------|-------------|
255
- | `options` | RadioOption[] | — | The options. The wrapper renders one `<a-radio>` per entry and computes its
256
- `selected` / roving `tabindex` / `role` declaratively. |
258
+ | `options` | RadioOption[] | — | The options. The wrapper renders one `<a-radio>` per entry and computes its `selected` / roving `tabindex` / `role` declaratively. |
257
259
  | `defaultValue?` | string | — | Initial selected value for uncontrolled use. |
258
260
  | `disabled?` | boolean | — | Disable the whole group. |
259
- | `hint?` | string | — | Plain-text description for the group, rendered directly under `label` (above
260
- the options) — typically instructional copy. Per-option helper text goes on
261
- the option's own `hint` instead. |
261
+ | `hint?` | string | — | Plain-text description for the group, rendered directly under `label` (above the options) — typically instructional copy. Per-option helper text goes on the option's own `hint` instead. |
262
262
  | `label?` | string | — | Plain-text label for the whole group, rendered above the options. |
263
- | `name?` | string | — | Form field name — the group submits one `name=value` (it's the
264
- form-associated element). |
263
+ | `name?` | string | — | Form field name — the group submits one `name=value` (it's the form-associated element). |
265
264
  | `onBlur?` | (event) => void | — | Fired when focus leaves the group entirely — wired to `focusout`. |
266
- | `onChange?` | (event) => void | — | Fired *after* the selection changes — a native `change` event (the post-apply
267
- counterpart to `onStateChange`). Not cancelable; for a controlled group it
268
- fires once you've updated `value`. |
269
- | `onFocus?` | (event) => void | — | Fired when focus enters the group (any option) — wired to `focusin`, since
270
- focus lands on an individual option, not the group element itself. |
271
- | `onStateChange?` | (event, detail) => void | — | Fired whenever selection changes — event-first. `detail` is
272
- `{ next, prev, reason }`: `next`/`prev` are values (`null` = nothing selected);
273
- `reason` is `'user'` \| `'reset'` \| `'restore'`. A `'user'` pick fires *before*
274
- applying and is **cancelable** — `event.preventDefault()` vetoes it
275
- (uncontrolled), or in controlled mode answer by updating `value` (reject by
276
- doing nothing). `'reset'` (form reset) and `'restore'` (bfcache / autofill) are
277
- not cancelable — filter on `reason` if you only track user picks. |
278
- | `onValueChange?` | (event, attrs) => void | — | Like `onChange`, but with a `{ value, name }` snapshot as the second argument,
279
- matching `Input`. |
265
+ | `onChange?` | (event) => void | — | Fired *after* the selection changes — a native `change` event (the post-apply counterpart to `onStateChange`). Not cancelable; for a controlled group it fires once you've updated `value`. |
266
+ | `onFocus?` | (event) => void | — | Fired when focus enters the group (any option) — wired to `focusin`, since focus lands on an individual option, not the group element itself. |
267
+ | `onStateChange?` | (event, detail) => void | — | Fired whenever selection changes — event-first. `detail` is `{ next, prev, reason }`: `next`/`prev` are values (`null` = nothing selected); `reason` is `'user'` \| `'reset'` \| `'restore'`. A `'user'` pick fires *before* applying and is **cancelable** — `event.preventDefault()` vetoes it (uncontrolled), or in controlled mode answer by updating `value` (reject by doing nothing). `'reset'` (form reset) and `'restore'` (bfcache / autofill) are not cancelable — filter on `reason` if you only track user picks. |
268
+ | `onValueChange?` | (event, attrs) => void | — | Like `onChange`, but with a `{ value, name }` snapshot as the second argument, matching `Input`. |
280
269
  | `orientation?` | 'vertical' \| 'horizontal' | 'vertical' | Layout + arrow-key axis. |
281
270
  | `size?` | 'small' \| 'medium' \| 'large' | 'medium' | Size applied to every option (an option's own `size` wins). |
282
- | `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | 'neutral' | Validation/feedback tone for the group `hint` — recolors it (same tone set
283
- as `Input`'s `status`). Use `critical` for an error message, etc.; omit for
284
- the neutral default. |
285
- | `tone?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Mark tone applied to every option (an option's own `tone` wins), or any literal
286
- CSS color for a one-off custom tone. Colors the selected-ring fill + dot *and*
287
- the unselected ring border. Named tones track light/dark mode. Use `toneSelected`
288
- instead to tone only the selected option and leave the rest neutral. The option
289
- text stays neutral — recolor it in plain CSS via the `--text-N-{tone}` tokens. |
290
- | `toneSelected?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Like `tone`, but colored onto the **selected option only** — every unselected
291
- ring stays neutral grey. Applied to every option (an option's own `toneSelected`
292
- wins). Prefer this over `tone` when a resting tinted border would read as a
293
- validation state. |
294
- | `value?` | string | — | Controlled selected value. The group follows this prop and reports a
295
- requested change through `onStateChange`. Leave it undefined for
296
- uncontrolled use. |
271
+ | `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | 'neutral' | Validation/feedback tone for the group `hint` — recolors it (same tone set as `Input`'s `status`). Use `critical` for an error message, etc.; omit for the neutral default. |
272
+ | `tone?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Mark tone applied to every option (an option's own `tone` wins), or any literal CSS color for a one-off custom tone. In the default `all` scope it colors the selected-ring fill + dot and the unselected ring border. Named tones track light/dark mode. Set `toneScope="selected"` to tone only the selected option and leave the rest neutral. The option text stays neutral — recolor it in plain CSS via the `--text-N-{tone}` tokens. |
273
+ | `toneScope?` | ToneScope | 'all' | Apply `tone` to every state, or only to the selected option so unselected rings stay neutral. An option's own `toneScope` wins. |
274
+ | `value?` | string | — | Controlled selected value. The group follows this prop and reports a requested change through `onStateChange`. Leave it undefined for uncontrolled use. |
275
+
276
+ ## Web Component
297
277
 
298
278
  Use the web component directly when you are not using React or Preact and a native control does not fit.
299
279
 
@@ -315,20 +295,22 @@ For a standard HTML form, add `data-anta` to each native radio. Radios that shar
315
295
  a `name` retain the browser's selection, keyboard behavior, labels, and form
316
296
  submission while using Anta's control surface.
317
297
 
318
- `size`, `tone`, and `tone-selected` use the matching RadioGroup option
298
+ `size`, `tone`, and `tone-scope` use the matching RadioGroup option
319
299
  treatments.
320
300
 
321
301
  ```html
322
302
  <div style="display: grid; gap: 8px">
323
303
  <label><input data-anta type="radio" name="plan" value="starter" size="small" tone="brand"> Starter</label>
324
- <label><input data-anta type="radio" name="plan" value="pro" tone-selected="success" checked> Pro</label>
304
+ <label><input data-anta type="radio" name="plan" value="pro" tone="success" tone-scope="selected" checked> Pro</label>
325
305
  <label><input data-anta type="radio" name="plan" value="enterprise" size="large" tone="warning"> Enterprise</label>
326
306
  </div>
327
307
  ```
328
308
 
329
- Reach for the props first: **`tone`** colors the mark in every state,
330
- **`toneSelected`** only the selected option (any CSS color for a custom tone, set on
331
- the group or a single option — derives the full curve in oklch), **`size`** the
309
+ ## Styling
310
+
311
+ Reach for the props first: **`tone`** chooses the mark color and **`toneScope`**
312
+ chooses whether it applies in all states or only to the selected option (any CSS
313
+ color can be set on the group or one option and derives the full curve in oklch), **`size`** the
332
314
  dimensions + type. To tint the label + hint, add a `color` rule on the option's
333
315
  `a-radio-label` / `a-radio-hint` with the `--text-N-{tone}` values — there's no
334
316
  text-tone prop. The focus ring is the global [`--focus-ring`](../colors.md#focus-ring).
@@ -358,7 +358,7 @@ const recency: SelectFacetCustom<Recency> = {
358
358
  // concrete date (or take the day as-is) and filter your rows with it
359
359
  ```
360
360
 
361
- ### Props
361
+ ## Component props
362
362
 
363
363
  | Prop | Type | Default | Description |
364
364
  |------|------|---------|-------------|
@@ -370,33 +370,16 @@ const recency: SelectFacetCustom<Recency> = {
370
370
  | `icon?` | IconShape | filter | Default trigger's leading icon. |
371
371
  | `label?` | string | Filter | Default trigger's button label. |
372
372
  | `offset?` | number | 4 | Gap in pixels between the trigger and the filter menu. |
373
- | `onValueChange?` | (value, attrs) => void | — | Fires after any facet changes. `value` is the whole new record (a facet key →
374
- that facet's value; a cleared facet is absent). `attrs` says what changed:
375
- `{ facet, kind, value }` for a single facet edit, or `{ all: true }` for the
376
- "Clear all" row — narrow on `'all' in attrs` before reading `facet`. |
377
- | `placement?` | 'left' \| 'right' \| 'bottom' \| 'top' \| 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' | bottom-start | Preferred placement of the root filter menu relative to its trigger. The
378
- menu auto-flips vertically and clamps horizontally when needed. |
373
+ | `onValueChange?` | (value, attrs) => void | — | Fires after any facet changes. `value` is the whole new record (a facet key → that facet's value; a cleared facet is absent). `attrs` says what changed: `{ facet, kind, value }` for a single facet edit, or `{ all: true }` for the "Clear all" row — narrow on `'all' in attrs` before reading `facet`. |
374
+ | `placement?` | 'left' \| 'right' \| 'bottom' \| 'top' \| 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' | bottom-start | Preferred placement of the root filter menu relative to its trigger. The menu auto-flips vertically and clamps horizontally when needed. |
379
375
  | `priority?` | 'primary' \| 'secondary' | secondary | Default trigger's button priority. |
380
- | `renderTrigger?` | (state) => ReactNode | — | Replaces the default `Button` with a trigger returned from this function.
381
- Receives a `SelectFacetedTriggerState`. Return exactly one focusable element:
382
- the menu is positioned relative to that element and opens when it is clicked.
383
- Add `aria-haspopup="menu"` and `aria-expanded={state.open}` to the returned
384
- element, on a role that supports them (an Anta `Button` already carries
385
- `role="button"`; otherwise add `role="combobox"`). `className`, `style`, and
386
- other trigger props apply only to the default Button, so add styling and
387
- attributes to the returned element. |
388
- | `searchable?` | boolean | — | Adds a search field at the top of the root menu. It searches the options of
389
- every `single` and `multiple` facet in one list. For example, "alice" can
390
- appear under application-defined Assignee and Owner facets. `text` and
391
- `custom` facets remain available when the search is empty. Each facet uses
392
- its `filter` function when supplied, or the built-in substring match. |
376
+ | `renderTrigger?` | (state) => ReactNode | — | Replaces the default `Button` with a trigger returned from this function. Receives a `SelectFacetedTriggerState`. Return exactly one focusable element: the menu is positioned relative to that element and opens when it is clicked. Add `aria-haspopup="menu"` and `aria-expanded={state.open}` to the returned element, on a role that supports them (an Anta `Button` already carries `role="button"`; otherwise add `role="combobox"`). `className`, `style`, and other trigger props apply only to the default Button, so add styling and attributes to the returned element. |
377
+ | `searchable?` | boolean | — | Adds a search field at the top of the root menu. It searches the options of every `single` and `multiple` facet in one list. For example, "alice" can appear under application-defined Assignee and Owner facets. `text` and `custom` facets remain available when the search is empty. Each facet uses its `filter` function when supplied, or the built-in substring match. |
393
378
  | `searchPlaceholder?` | string | Filter… | Placeholder for the global search field. |
394
379
  | `size?` | 'small' \| 'medium' \| 'large' | medium | Default trigger's button size. |
395
- | `toneSelected?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | — | Tone applied to a selected option row in the facet flyouts (label, selected
396
- tint, and the check / checkbox indicator). A named tone or a custom CSS
397
- color, matching `Select`'s `toneSelected`. Defaults to a neutral selection. |
398
- | `value?` | SelectFacetedValue | — | Controlled value record, keyed by facet. When provided, update it through
399
- `onValueChange`. Leave it undefined for uncontrolled use. |
380
+ | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | — | Default option-row tone in facet flyouts. An option's own `tone` wins. |
381
+ | `toneScope?` | ToneScope | 'all' | Apply the default row tone in every state, or only to selected rows. An option's own `toneScope` wins. |
382
+ | `value?` | SelectFacetedValue | — | Controlled value record, keyed by facet. When provided, update it through `onValueChange`. Leave it undefined for uncontrolled use. |
400
383
 
401
384
  ### The `SelectFacet` type
402
385
 
@@ -40,8 +40,8 @@ skipped by the keyboard.
40
40
  <Select options={OPTIONS} value={one} onValueChange={setOne} /> // tint only (default)
41
41
 
42
42
  // Tone the selected row: named tone or custom color (the indicator adopts it)
43
- <Select indicator="check" toneSelected="brand" options={OPTIONS} value={one} onValueChange={setOne} />
44
- <Select indicator="radio" toneSelected="#c026d3" options={OPTIONS} value={one} onValueChange={setOne} />
43
+ <Select indicator="check" tone="brand" toneScope="selected" options={OPTIONS} value={one} onValueChange={setOne} />
44
+ <Select indicator="radio" tone="#c026d3" toneScope="selected" options={OPTIONS} value={one} onValueChange={setOne} />
45
45
 
46
46
  // Multiple: checkboxes, count summary, Select-all row (default); value is an array
47
47
  <Select
@@ -78,9 +78,9 @@ Each checkable row is the control itself (`role="menuitemcheckbox"` /
78
78
  `menuitemradio`, `aria-checked`); the checkbox / radio / check is a passive indicator
79
79
  the row drives.
80
80
 
81
- **`toneSelected`** tones the selected row(s): the whole row takes the tone, including
82
- label, icon, indicator, and tint. Pass a named tone or any CSS color (a custom color
83
- keeps its hue, with lightness pinned to the brand text). It reads strongest with
81
+ Use **`tone`** with **`toneScope="selected"`** to tone only selected rows: the whole
82
+ row takes the tone, including label, icon, indicator, and tint. Pass a named tone or
83
+ any CSS color (a custom color keeps its hue, with lightness pinned to the brand text). It reads strongest with
84
84
  `indicator` `none` / `check`, which show the row tint; `radio` / `checkbox` have no
85
85
  row tint, so it tones the label and indicator only.
86
86
 
@@ -623,117 +623,41 @@ sections is one pick (dev builds warn).
623
623
  groups (their label becomes the heading) and drops empty ones, so results read as one
624
624
  scannable list instead of hiding matches behind flyouts.
625
625
 
626
- ### Props
626
+ ## Component props
627
627
 
628
628
  | Prop | Type | Default | Description |
629
629
  |------|------|---------|-------------|
630
- | `options` | SelectItem[] | — | The options to choose from — bare strings, `SelectOption` objects, `SelectGroup`s
631
- (inline titled sections), or `SelectSubmenu`s (flyout branches). Groups and
632
- submenus nest and mix with plain options. Selection stays global (one `value`,
633
- leaf options only); a filter query flattens the tree into grouped results.
634
-
635
- `Select` infers its value type `V` from these options: `{ value: 365 }` makes
636
- `onValueChange` report `number`. A mix of value types widens `V` to the union.
637
-
638
- Each leaf `value` is the option's identity and must be **unique across the whole
639
- tree** (selection is value-keyed, so a value repeated in two sections is one logical
640
- pick: both rows toggle together, the trigger resolves to the last). Values that
641
- stringify alike (`365` and `"365"`) also collide as row keys; dev builds
642
- `console.warn` on either. |
643
- | `clearable?` | boolean | — | Add a "Clear" row pinned in the menu **footer** that empties the selection
644
- (single → none, multiple → `[]`). Shown only while something is selected, so
645
- it never scrolls away in a long or filtered list. |
630
+ | `options` | SelectItem[] | — | The options to choose from — bare strings, `SelectOption` objects, `SelectGroup`s (inline titled sections), or `SelectSubmenu`s (flyout branches). Groups and submenus nest and mix with plain options. Selection stays global (one `value`, leaf options only); a filter query flattens the tree into grouped results. `Select` infers its value type `V` from these options: `{ value: 365 }` makes `onValueChange` report `number`. A mix of value types widens `V` to the union. Each leaf `value` is the option's identity and must be **unique across the whole tree** (selection is value-keyed, so a value repeated in two sections is one logical pick: both rows toggle together, the trigger resolves to the last). Values that stringify alike (`365` and `"365"`) also collide as row keys; dev builds `console.warn` on either. |
631
+ | `clearable?` | boolean | — | Add a "Clear" row pinned in the menu **footer** that empties the selection (single → none, multiple → `[]`). Shown only while something is selected, so it never scrolls away in a long or filtered list. |
646
632
  | `clearLabel?` | string | Clear | Label for the `clearable` footer row. |
647
633
  | `defaultValue?` | V \| V[] | — | Initial selected option value for uncontrolled use. |
648
634
  | `disabled?` | boolean | — | Disable the whole select. |
649
- | `filter?` | boolean \| (option, query) => boolean | — | Add a search field at the top of the menu that filters the options as you
650
- type. `true` uses the built-in matcher — a case-insensitive substring of the
651
- option's **value / label / hint**. Pass a **function** `(option, query) =>
652
- boolean` for custom matching (called per option; return `true` to keep it). |
635
+ | `filter?` | boolean \| (option, query) => boolean | — | Add a search field at the top of the menu that filters the options as you type. `true` uses the built-in matcher — a case-insensitive substring of the option's **value / label / hint**. Pass a **function** `(option, query) => boolean` for custom matching (called per option; return `true` to keep it). |
653
636
  | `hint?` | string | — | Helper text under the field (Input's `hint`). |
654
- | `icon?` | IconShape | — | Leading icon shown at the left of the field (the default trigger's `Input`
655
- `leading` slot). With a custom `renderTrigger`, it's passed through as
656
- `state.icon` instead — the consumer places it. |
657
- | `indicator?` | 'none' \| 'check' \| 'radio' | none | The per-row mark for **single**-select: `'none'` (a tint-only highlight),
658
- `'check'` (a trailing checkmark on the selected row, keeping the tint — the
659
- canonical Select look), or `'radio'` (a leading radio on every row).
660
- Multi-select always uses checkboxes. |
637
+ | `icon?` | IconShape | — | Leading icon shown at the left of the field (the default trigger's `Input` `leading` slot). With a custom `renderTrigger`, it's passed through as `state.icon` instead — the consumer places it. |
638
+ | `indicator?` | 'none' \| 'check' \| 'radio' | none | The per-row mark for **single**-select: `'none'` (a tint-only highlight), `'check'` (a trailing checkmark on the selected row, keeping the tint — the canonical Select look), or `'radio'` (a leading radio on every row). Multi-select always uses checkboxes. |
661
639
  | `label?` | string | — | Field label, above the trigger (Input's `label`). |
662
- | `leading?` | ReactNode | — | Content for the default trigger's `leading` slot, such as a key prefix
663
- before the value. It replaces the icon derived from `icon`. Include an
664
- `<Icon>` in this content when both are needed. Ignored by `renderTrigger`. |
640
+ | `leading?` | ReactNode | — | Content for the default trigger's `leading` slot, such as a key prefix before the value. It replaces the icon derived from `icon`. Include an `<Icon>` in this content when both are needed. Ignored by `renderTrigger`. |
665
641
  | `offset?` | number | 4 | Gap in pixels between the trigger and the options menu. |
666
- | `onValueChange?` | (value, attrs) => void | — | Fires after the selection changes, with the new value and a
667
- `{ value, option }` snapshot. Select has no discrete element state, so
668
- there is no cancelable `onStateChange` (see the Input event-model note). |
642
+ | `onValueChange?` | (value, attrs) => void | — | Fires after the selection changes, with the new value and a `{ value, option }` snapshot. Select has no discrete element state, so there is no cancelable `onStateChange` (see the Input event-model note). |
669
643
  | `placeholder?` | string | — | Text shown when nothing is selected. |
670
- | `placement?` | 'left' \| 'right' \| 'bottom' \| 'top' \| 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' | bottom-start | Preferred placement of the options menu relative to the trigger. The menu
671
- auto-flips vertically and clamps horizontally when needed. |
672
- | `renderEmpty?` | (state) => ReactNode | — | Render content in the menu body when the (filtered) option list is empty —
673
- a "no results" message, a loading indicator (gated on your own external
674
- loading state), or a "create from the query" row. Receives an `EmptyState`
675
- (`query`, trimmed). There is no built-in empty message: when omitted, an empty
676
- list renders nothing. Whatever you return goes where the option rows would —
677
- a plain node is inert; return a `MenuItem` (e.g. a "Create" row) to make it
678
- focusable and selectable. |
679
- | `renderIndicator?` | (state) => ReactNode | — | Replace each row's selection **mark** with your own node, drawn at the
680
- leading edge. The row stays the control (`role` + `aria-checked` from
681
- `indicator` / `selection`); only the drawn mark changes, so pair it with an
682
- `indicator` (`'check'` / `'radio'`) or `selection="multiple"` for the
683
- semantics. Composes with `renderOption`. |
684
- | `renderOption?` | (option, state) => ReactNode | — | Replaces the built-in `label`, `hint`, and `icon` layout for each option row.
685
- Select still supplies the row container, click handling, ARIA attributes, and
686
- selection indicator. Read extra option fields through `SelectOption`'s index
687
- signature. `state` contains `value`, `selected`, and `disabled`. Filtering
688
- still matches the option's `value`, `label`, and `hint`, but Select cannot
689
- highlight matches within the returned content. |
690
- | `renderSummary?` | (selected) => string \| undefined | — | `multiple` only: build the trigger's selection summary text yourself,
691
- replacing the built-in "`All` / one label / `N selected`" logic. Receives
692
- the resolved selected options (`selected.length` is the count) and runs only
693
- while something is selected — an empty selection still shows the
694
- `placeholder`. Return a **string**: it flows into the default trigger's
695
- read-only field, so a long summary ellipsizes at the field's width just
696
- like a long value (`Engineering, Design, … `). Return `undefined` to fall
697
- back to the default for that case (e.g. customize only the count, keeping
698
- the single-label case built-in). For rich content (chips, multiple nodes)
699
- use `renderTrigger`, which replaces the whole field. |
700
- | `renderTrigger?` | (state) => ReactNode | — | Replaces the default field with a trigger returned from this function.
701
- Receives `open`, `value`, `selected`, `disabled`, and `icon`. Return exactly
702
- one focusable element, such as an Anta `Button`. The menu is positioned
703
- relative to that element and opens when it is clicked. Do not return a
704
- fragment, multiple siblings, or a non-focusable wrapper. Add
705
- `aria-haspopup="menu"` and `aria-expanded={state.open}` to the element, on a
706
- role that supports them (an Anta `Button` already carries `role="button"`;
707
- otherwise add `role="combobox"`).
708
- Field props (`label`, `hint`, `size`, `status`, `placeholder`, and `round`) and
709
- `className` / `style` apply only to the default field. Add styling and
710
- attributes to the returned element instead. |
644
+ | `placement?` | 'left' \| 'right' \| 'bottom' \| 'top' \| 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' | bottom-start | Preferred placement of the options menu relative to the trigger. The menu auto-flips vertically and clamps horizontally when needed. |
645
+ | `renderEmpty?` | (state) => ReactNode | — | Render content in the menu body when the (filtered) option list is empty — a "no results" message, a loading indicator (gated on your own external loading state), or a "create from the query" row. Receives an `EmptyState` (`query`, trimmed). There is no built-in empty message: when omitted, an empty list renders nothing. Whatever you return goes where the option rows would — a plain node is inert; return a `MenuItem` (e.g. a "Create" row) to make it focusable and selectable. |
646
+ | `renderIndicator?` | (state) => ReactNode | — | Replace each row's selection **mark** with your own node, drawn at the leading edge. The row stays the control (`role` + `aria-checked` from `indicator` / `selection`); only the drawn mark changes, so pair it with an `indicator` (`'check'` / `'radio'`) or `selection="multiple"` for the semantics. Composes with `renderOption`. |
647
+ | `renderOption?` | (option, state) => ReactNode | — | Replaces the built-in `label`, `hint`, and `icon` layout for each option row. Select still supplies the row container, click handling, ARIA attributes, and selection indicator. Read extra option fields through `SelectOption`'s index signature. `state` contains `value`, `selected`, and `disabled`. Filtering still matches the option's `value`, `label`, and `hint`, but Select cannot highlight matches within the returned content. |
648
+ | `renderSummary?` | (selected) => string \| undefined | — | `multiple` only: build the trigger's selection summary text yourself, replacing the built-in "`All` / one label / `N selected`" logic. Receives the resolved selected options (`selected.length` is the count) and runs only while something is selected — an empty selection still shows the `placeholder`. Return a **string**: it flows into the default trigger's read-only field, so a long summary ellipsizes at the field's width just like a long value (`Engineering, Design, … `). Return `undefined` to fall back to the default for that case (e.g. customize only the count, keeping the single-label case built-in). For rich content (chips, multiple nodes) use `renderTrigger`, which replaces the whole field. |
649
+ | `renderTrigger?` | (state) => ReactNode | — | Replaces the default field with a trigger returned from this function. Receives `open`, `value`, `selected`, `disabled`, and `icon`. Return exactly one focusable element, such as an Anta `Button`. The menu is positioned relative to that element and opens when it is clicked. Do not return a fragment, multiple siblings, or a non-focusable wrapper. Add `aria-haspopup="menu"` and `aria-expanded={state.open}` to the element, on a role that supports them (an Anta `Button` already carries `role="button"`; otherwise add `role="combobox"`). Field props (`label`, `hint`, `size`, `status`, `placeholder`, and `round`) and `className` / `style` apply only to the default field. Add styling and attributes to the returned element instead. |
711
650
  | `round?` | boolean \| number \| string | — | Round the field corners — `true` for fully round, or a number / CSS length. |
712
- | `selectAll?` | boolean | true | `multiple` only: shows a "Select all" row that toggles every enabled option,
713
- or only the visible options when a filter query is active. Its checkbox is
714
- mixed when some options are selected. It is on by default. Set it to `false`
715
- to remove the row and the Alt/Option-click shortcut that selects only one row. |
651
+ | `selectAll?` | boolean | true | `multiple` only: shows a "Select all" row that toggles every enabled option, or only the visible options when a filter query is active. Its checkbox is mixed when some options are selected. It is on by default. Set it to `false` to remove the row and the Alt/Option-click shortcut that selects only one row. |
716
652
  | `selectAllLabel?` | string | Select all | Label for the `selectAll` row. |
717
- | `selection?` | 'single' \| 'multiple' | single | Selection mode. `'single'` (the default) keeps `value` a single value and
718
- closes the menu on pick. Switch to `'multiple'` for checkboxes + an
719
- array value. |
653
+ | `selection?` | 'single' \| 'multiple' | single | Selection mode. `'single'` (the default) keeps `value` a single value and closes the menu on pick. Switch to `'multiple'` for checkboxes + an array value. |
720
654
  | `size?` | 'small' \| 'medium' \| 'large' | medium | Field size. |
721
655
  | `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | neutral | Validation/feedback tone for the field (Input's `status`). |
722
- | `statusIcon?` | (string & {}) \| false \| IconShape | — | Glyph shown before the `hint` when `status` is set (Input's `statusIcon`).
723
- Each status has a default; pass a shape to override, or `false` to drop it. |
724
- | `toneSelected?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | — | Tone applied to the **selected** row(s) — the whole row takes this tone
725
- (label, icon, indicator, and the background tint), like passing `tone` to just
726
- the chosen option. A named tone or a custom CSS color. Most visible with the
727
- tint-based marks (`indicator` `'none'` / `'check'`); with `'radio'` /
728
- `'checkbox'` it tones the label + indicator (those modes have no row tint). |
729
- | `value?` | V \| V[] | — | Controlled value: the selected option's `value`. Update it through
730
- `onValueChange`. Leave it undefined for uncontrolled use. |
731
- | `verbose?` | boolean | — | `multiple` only: spell the picks out in the count summary — `3 selected:
732
- A, B, C` (labels comma-joined) in place of the bare `3 selected`. Applies
733
- to the multi-count case only: `All` stays `All`, a single pick stays its
734
- own label, and an empty selection stays the `placeholder`. The list flows
735
- into the read-only field, so it ellipsizes at the field's width when long
736
- (`3 selected: Engineering, Des… `). `renderSummary` overrides this. |
656
+ | `statusIcon?` | (string & {}) \| false \| IconShape | — | Glyph shown before the `hint` when `status` is set (Input's `statusIcon`). Each status has a default; pass a shape to override, or `false` to drop it. |
657
+ | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | — | Default option-row tone. An option's own `tone` wins. A named tone or a custom CSS color. Most visible with tint-based marks (`indicator` `'none'` / `'check'`); with `'radio'` / `'checkbox'` it also tones the indicator. |
658
+ | `toneScope?` | ToneScope | 'all' | Apply the default row tone in every state, or only to selected rows. An option's own `toneScope` wins. |
659
+ | `value?` | V \| V[] | — | Controlled value: the selected option's `value`. Update it through `onValueChange`. Leave it undefined for uncontrolled use. |
660
+ | `verbose?` | boolean | — | `multiple` only: spell the picks out in the count summary — `3 selected: A, B, C` (labels comma-joined) in place of the bare `3 selected`. Applies to the multi-count case only: `All` stays `All`, a single pick stays its own label, and an empty selection stays the `placeholder`. The list flows into the read-only field, so it ellipsizes at the field's width when long (`3 selected: Engineering, Des… `). `renderSummary` overrides this. |
737
661
 
738
662
  ### The `SelectItem` type
739
663
 
@@ -829,6 +753,8 @@ inline `SelectGroup`, and a flyout `SelectSubmenu` (whose items are themselves
829
753
  />
830
754
  ```
831
755
 
756
+ ## Web Component
757
+
832
758
  Use the web component directly when you are not using React or Preact and a native control does not fit.
833
759
 
834
760
  `Select` has no host element. Compose a read-only `<a-input>` trigger with an
@@ -896,12 +822,14 @@ corners.
896
822
  </select>
897
823
  ```
898
824
 
825
+ ## Styling
826
+
899
827
  Select is an [Input](./input.md) plus a [Menu](./menu.md), so it
900
828
  inherits both surfaces' hooks. Reach for props first, then plain CSS or `::part` for
901
829
  the rest. Don't override an element's internal `--*` output tokens.
902
830
 
903
- **Selection color** routes through the props: a per-option `tone`, or `toneSelected`
904
- for the chosen row(s). Both take a named tone or any CSS color (a custom color keeps
831
+ **Selection color** routes through `tone`: set it per option or on the Select as a
832
+ default, then use `toneScope="selected"` for chosen rows only. It takes a named tone or any CSS color (a custom color keeps
905
833
  its hue, with lightness pinned to the brand text).
906
834
 
907
835
  **The field** is styled through Input's props (`size`, `status`, `round`) and its
@@ -910,7 +838,7 @@ popover** takes Menu's `::part(menu)`.
910
838
 
911
839
  ```tsx
912
840
  // Tone the selection; give the trigger a width.
913
- <Select toneSelected="brand" style={{ width: '220px' }} options={OPTIONS} />
841
+ <Select tone="brand" toneScope="selected" style={{ width: '220px' }} options={OPTIONS} />
914
842
  ```
915
843
 
916
844
  **Borderless trigger.** The field's border is an inset `box-shadow`, so you can drop
@@ -13,6 +13,9 @@ decreases it. The thumb does not move to the point where the rail was pressed.
13
13
  Set `trackClick="jump"` to move the thumb to the pressed position before
14
14
  dragging, as a native range input does.
15
15
 
16
+ Releasing the pointer or losing pointer capture ends the drag. Moving back over
17
+ the slider without pressing leaves its value unchanged.
18
+
16
19
  Arrow keys change by `step`. Home and End set the minimum and maximum. PageUp and PageDown move by one tenth of the range.
17
20
 
18
21
  ```tsx
@@ -59,43 +62,35 @@ Arrow keys change by `step`. Home and End set the minimum and maximum. PageUp an
59
62
  />
60
63
  ```
61
64
 
62
- ### Props
65
+ ## Component props
63
66
 
64
67
  | Prop | Type | Default | Description |
65
68
  |------|------|---------|-------------|
66
69
  | `defaultValue?` | number | 0 | Initial uncontrolled value. |
67
70
  | `disabled?` | boolean | — | Disables pointer and keyboard interaction. |
68
- | `label?` | ReactNode | — | Visible field label, shown above the rail. A string supplies the slider's
69
- accessible name; give a rich label an explicit `aria-label`. |
70
- | `markers?` | SliderMarker[] | — | Compact text labels positioned below the rail. They do not add dots or
71
- ticks to the rail. |
71
+ | `label?` | ReactNode | — | Visible field label, shown above the rail. A string supplies the slider's accessible name; give a rich label an explicit `aria-label`. |
72
+ | `markers?` | SliderMarker[] | — | Compact text labels positioned below the rail. They do not add dots or ticks to the rail. |
72
73
  | `max?` | number | 100 | Highest permitted value. |
73
74
  | `min?` | number | 0 | Lowest permitted value. |
74
75
  | `name?` | string | — | Form field name. The current numeric value submits under this name. |
75
76
  | `onValueChange?` | (event, attrs) => void | — | Fires on every keyboard or pointer value change. |
76
77
  | `onValueCommit?` | (event, attrs) => void | — | Fires after a drag ends and after each keyboard value change. |
77
- | `round?` | boolean \| number \| string | — | Fully round the rail and thumb. Pass a number (px) or CSS length string
78
- for a shared custom radius. |
78
+ | `round?` | boolean \| number \| string | — | Fully round the rail and thumb. Pass a number (px) or CSS length string for a shared custom radius. |
79
79
  | `size?` | 'small' \| 'medium' \| 'large' | 'medium' | Size variant. small=24px, medium=28px, large=32px tall. |
80
80
  | `step?` | number | 1 | Smallest keyboard and drag increment. |
81
- | `thumbFill?` | boolean | false | Fill the thumb with its resolved border color. This follows `thumbTone`
82
- and interactive states. |
83
- | `thumbSize?` | number \| string | 16 | Diameter of the thumb. Numbers use pixels; strings are CSS lengths. Keep
84
- it at least as large as `trackSize`. |
85
- | `thumbTone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the thumb stroke. Pass a named tone or a literal CSS color for a
86
- one-off custom tone. Omit it to keep the thumb neutral. |
87
- | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the filled rail. Pass a named tone or a literal CSS color for a
88
- one-off custom tone. The unfilled rail stays neutral. |
89
- | `trackClick?` | 'drag-only' \| 'jump' | 'drag-only' | Controls what happens when the rail is pressed. `drag-only` starts dragging
90
- from the current value. `jump` first moves to the pressed position. |
91
- | `trackSize?` | number \| string | 2 | Thickness of both rail segments. Numbers use pixels; strings are CSS
92
- lengths. Keep it no larger than the thumb diameter. |
81
+ | `thumbFill?` | boolean | false | Fill the thumb with its resolved border color. This follows `thumbTone` and interactive states. |
82
+ | `thumbSize?` | number \| string | 16 | Diameter of the thumb. Numbers use pixels; strings are CSS lengths. Keep it at least as large as `trackSize`. |
83
+ | `thumbTone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the thumb stroke. Pass a named tone or a literal CSS color for a one-off custom tone. Omit it to keep the thumb neutral. |
84
+ | `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the filled rail. Pass a named tone or a literal CSS color for a one-off custom tone. The unfilled rail stays neutral. |
85
+ | `trackClick?` | 'drag-only' \| 'jump' | 'drag-only' | Controls what happens when the rail is pressed. `drag-only` starts dragging from the current value. `jump` first moves to the pressed position. |
86
+ | `trackSize?` | number \| string | 2 | Thickness of both rail segments. Numbers use pixels; strings are CSS lengths. Keep it no larger than the thumb diameter. |
93
87
  | `value?` | number | — | Controlled value. Update it from `onValueChange`. |
94
- | `valueDisplay?` | 'end' \| 'inline' \| 'thumb' \| 'none' | 'end' | Where the live value appears. `end` puts it at the right edge of the label
95
- row. `inline` renders `Label: value`. `thumb` keeps it above the thumb. |
88
+ | `valueDisplay?` | 'end' \| 'inline' \| 'thumb' \| 'none' | 'end' | Where the live value appears. `end` puts it at the right edge of the label row. `inline` renders `Label: value`. `thumb` keeps it above the thumb. |
96
89
  | `valuePrefix?` | string | — | Text inserted before the live numeric value, such as `$`. |
97
90
  | `valueSuffix?` | string | — | Text inserted after the live numeric value, such as `%` or `°C`. |
98
91
 
92
+ ## Web Component
93
+
99
94
  Use `<a-slider>` when you are not using React or Preact. Add its `role` and accessible name yourself, then register it from `@antadesign/anta/elements`.
100
95
 
101
96
  ```html
@@ -225,6 +225,8 @@ the next step.
225
225
  </Steps>
226
226
  ```
227
227
 
228
+ ## Keyboard and accessibility
229
+
228
230
  Pass `label` to name the tablist. Arrow keys follow the orientation; `Home` and
229
231
  `End` move to the edges; `Enter` and `Space` activate a focused step. Disabled
230
232
  steps are skipped.
@@ -242,17 +244,43 @@ Events match [`Tabs`](./tabs.md#events).
242
244
  | `onChange(event)` | After selection | No | Native `change` event |
243
245
  | `onValueChange(event, { value })` | After selection | No | Selected value |
244
246
 
247
+ ## Steps props
248
+
245
249
  | Prop | Type | Default | Description |
246
250
  |------|------|---------|-------------|
247
251
  | `options` | StepOption[] | — | Ordered process phases. |
248
- | `priority?` | StepPriority | 'secondary' | Visual emphasis. Primary uses a solid selected marker and a stronger
249
- completed connector; secondary is the outlined default; tertiary is compact
250
- and borderless. |
251
- | `renderMarker?` | (option, state) => ReactNode | — | Builds a custom marker from a step and its current state. A returned node
252
- replaces `marker` and the built-in state marker; return `undefined` to use
253
- those fallbacks, or `null` for an empty ring. |
254
- | `tone?` | StepTone \| '' | 'neutral' | Tone applied to every step without its own `tone`. Error steps stay
255
- critical and disabled steps stay neutral. |
252
+ | `children?` | ReactNode | — | Optional `<TabPanel value="…">` panels, one per tab value. Each is a self-managing `<a-tabpanel>` that shows itself when its `value` is the active tab. Omit them to use `Tabs` as a bare selectable strip. To place panels in a different layout region, or to unmount an inactive panel, drive selection with a controlled `value` and render the content yourself (see the docs). |
253
+ | `defaultValue?` | string | — | Initial active value for the uncontrolled case. After first render `Tabs` owns selection itself. |
254
+ | `disabled?` | boolean | — | Disable the whole strip. |
255
+ | `fill?` | boolean | false | Makes horizontal tabs share the available inline space equally. |
256
+ | `label?` | string | — | Accessible name for the tablist (`aria-label`). |
257
+ | `onBlur?` | (event) => void | — | Focus left the strip entirely — wired to `focusout`. |
258
+ | `onChange?` | (event) => void | — | Fired *after* the active tab changes — a native `change` event. |
259
+ | `onFocus?` | (event) => void | — | Focus entered the strip (any tab) — wired to `focusin` (focus lands on a tab, not the tablist). |
260
+ | `onStateChange?` | (event, detail) => void | — | Fired whenever the active tab changes — event-first. `detail` is `{ next, prev }` (values; `null` = none). Cancelable: `event.preventDefault()` vetoes it (uncontrolled), or in controlled mode answer by updating `value`. |
261
+ | `onValueChange?` | (event, attrs) => void | — | Like `onChange`, but with a `{ value }` snapshot as the 2nd argument. |
262
+ | `orientation?` | 'horizontal' \| 'vertical' | 'horizontal' | Layout + arrow-key axis. Horizontal ellipsizes labels when tabs overflow (scroll is opt-in via CSS); vertical stacks them. |
263
+ | `priority?` | StepPriority | 'secondary' | Visual emphasis. Primary uses a solid selected marker and a stronger completed connector; secondary is the outlined default; tertiary is compact and borderless. |
264
+ | `renderMarker?` | (option, state) => ReactNode | — | Builds a custom marker from a step and its current state. A returned node replaces `marker` and the built-in state marker; return `undefined` to use those fallbacks, or `null` for an empty ring. |
265
+ | `size?` | 'small' \| 'medium' \| 'large' | 'medium' | Size — small 24px · medium 28px · large 32px tall, matching Button's scale (the tab's label leading runs a touch tighter, offset by 1px more block padding per side). |
266
+ | `tone?` | StepTone \| '' | 'neutral' | Tone applied to every step without its own `tone`. Error steps stay critical and disabled steps stay neutral. |
267
+ | `value?` | string | — | Controlled active value — the tab `value` to mark selected (and, when a `<TabPanel value="…">` shares it, the panel to reveal). When set, you own selection: the strip renders exactly what this says, and a user pick only *requests* a change via `onStateChange` — apply it by updating this prop. Leave undefined (and use `defaultValue`) for uncontrolled. |
268
+
269
+ ## Step option props
270
+
271
+ | Prop | Type | Default | Description |
272
+ |------|------|---------|-------------|
273
+ | `label` | ReactNode | — | Visible phase label. It ellipsizes in a constrained step; its full content is available in a tooltip only when clipped. |
274
+ | `state` | StepState | — | Application-owned process state. Selection and availability are separate; `error` keeps a critical icon and outline, and selection adds the fill. |
275
+ | `value` | string | — | Stable phase identity. Values must be unique within the sequence. |
276
+ | `className?` | string | — | CSS class on the option's rendered row. |
277
+ | `disabled?` | boolean | — | Disables this phase. A custom `marker` or `renderMarker` result is kept; otherwise it uses the incomplete marker. |
278
+ | `hint?` | ReactNode | — | Secondary text shown below the label. It ellipsizes in a constrained step; its full content is available in a tooltip only when clipped. |
279
+ | `marker?` | StepMarker | — | Replaces the marker derived from `state`. A number is shown directly; an Anta icon shape is rendered as an `<Icon>`. |
280
+ | `style?` | CSSProperties | — | Inline styles on the option's rendered row. |
281
+ | `tone?` | StepTone \| '' | inherits Steps `tone | Tone for this phase. It colors the label, hint, marker, and completed connector. Overrides the Steps `tone`; error steps stay critical and disabled steps stay neutral. |
282
+
283
+ ## Web Component
256
284
 
257
285
  For framework-free use, compose the same light DOM that `Steps` emits.
258
286
  `a-steps` and its `a-step-*` children are structural elements styled by the
@@ -288,6 +316,8 @@ import '@antadesign/anta/components/Steps.css'
288
316
  </div>
289
317
  ```
290
318
 
319
+ ## Styling
320
+
291
321
  Use `priority`, `size`, and `orientation` first. Set `tone` on each option. Each
292
322
  option also accepts `className`, `style`, and `data-*` attributes. Markers are
293
323
  light DOM; connectors are pseudo-elements.