@antadesign/anta 0.3.27 → 0.3.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICES.md +32 -1
- package/dist/anta_helpers.d.ts +25 -0
- package/dist/anta_helpers.js +28 -0
- package/dist/box-observation.d.ts +8 -0
- package/dist/box-observation.js +41 -0
- package/dist/box-types.d.ts +2 -0
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +77 -46
- package/dist/components/Banner.js +2 -2
- package/dist/components/Box.d.ts +28 -12
- package/dist/components/Box.js +18 -11
- package/dist/components/Breadcrumbs.css +1 -1
- package/dist/components/Button.js +2 -2
- package/dist/components/Calendar.js +3 -5
- package/dist/components/Card.js +2 -2
- package/dist/components/Checkbox.d.ts +12 -13
- package/dist/components/Checkbox.js +5 -13
- package/dist/components/Expander.js +2 -2
- package/dist/components/Input.d.ts +8 -2
- package/dist/components/Input.js +6 -2
- package/dist/components/InputAutocomplete.js +3 -12
- package/dist/components/InputDate.css +1 -1
- package/dist/components/InputDate.js +2 -0
- package/dist/components/InputTime.js +2 -2
- package/dist/components/Loader.js +2 -1
- package/dist/components/Menu.d.ts +4 -4
- package/dist/components/Menu.js +1 -1
- package/dist/components/MenuItem.d.ts +7 -8
- package/dist/components/MenuItem.js +4 -4
- package/dist/components/Panel.d.ts +17 -0
- package/dist/components/Panel.js +22 -0
- package/dist/components/Progress.js +2 -2
- package/dist/components/RadioGroup.d.ts +14 -14
- package/dist/components/RadioGroup.js +7 -23
- package/dist/components/Select.d.ts +26 -21
- package/dist/components/Select.js +51 -38
- package/dist/components/SelectFaceted.d.ts +24 -11
- package/dist/components/SelectFaceted.js +65 -44
- package/dist/components/Slider.js +3 -3
- package/dist/components/Steps.css +1 -1
- package/dist/components/Switch.d.ts +10 -11
- package/dist/components/Switch.js +3 -11
- package/dist/components/TabPanel.d.ts +3 -8
- package/dist/components/TabPanel.js +2 -1
- package/dist/components/Tabs.d.ts +2 -2
- package/dist/components/Tabs.js +4 -3
- package/dist/components/Tag.d.ts +7 -9
- package/dist/components/Tag.js +2 -2
- package/dist/components/Text.js +2 -2
- package/dist/components/Title.js +2 -2
- package/dist/components/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip.js +1 -1
- package/dist/components/select-parts.css +1 -1
- package/dist/elements/a-avatar.css +1 -1
- package/dist/elements/a-banner.css +1 -1
- package/dist/elements/a-box.css +1 -1
- package/dist/elements/a-box.d.ts +6 -6
- package/dist/elements/a-box.js +74 -23
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +16 -10
- package/dist/elements/a-button.js +64 -1
- package/dist/elements/a-calendar.css +1 -1
- package/dist/elements/a-capture.css +1 -1
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-checkbox.d.ts +3 -0
- package/dist/elements/a-checkbox.js +17 -1
- package/dist/elements/a-copy.css +1 -1
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.js +1 -0
- package/dist/elements/a-icon.css +1 -1
- package/dist/elements/a-icon.shapes.css +1 -1
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.d.ts +8 -0
- package/dist/elements/a-input-time.js +120 -15
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +27 -1
- package/dist/elements/a-input.js +180 -41
- package/dist/elements/a-loader.css +1 -1
- package/dist/elements/a-menu-group.css +1 -1
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.js +1 -0
- package/dist/elements/a-menu-separator.css +1 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +8 -13
- package/dist/elements/a-menu.js +146 -45
- package/dist/elements/a-panel.css +1 -0
- package/dist/elements/a-panel.d.ts +16 -0
- package/dist/elements/a-panel.js +153 -0
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-radio-group.css +1 -1
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-radio.d.ts +4 -0
- package/dist/elements/a-radio.js +18 -0
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-slider.d.ts +1 -0
- package/dist/elements/a-slider.js +3 -6
- package/dist/elements/a-switch.css +1 -1
- package/dist/elements/a-switch.d.ts +3 -0
- package/dist/elements/a-switch.js +17 -1
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tabpanel.css +1 -1
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.js +1 -0
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-toast.css +1 -1
- package/dist/elements/a-toaster.css +1 -1
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +3 -4
- package/dist/elements/a-tooltip.js +30 -8
- package/dist/elements/focus.d.ts +9 -0
- package/dist/elements/focus.js +41 -0
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/elements/panel-focus.d.ts +10 -0
- package/dist/elements/panel-focus.js +86 -0
- package/dist/elements/shadow-aria.d.ts +10 -0
- package/dist/elements/shadow-aria.js +155 -0
- package/dist/general_types.d.ts +70 -42
- package/dist/generate-icons.mjs +3 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2 -0
- package/dist/jsx-runtime.d.ts +10 -1
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +1 -0
- package/dist/theme-antune.css +1 -0
- package/dist/tokens.css +1 -1
- package/docs/accessibility.md +4 -2
- package/docs/changelog.md +135 -0
- package/docs/colors.md +7 -7
- package/docs/comparison.md +2 -2
- package/docs/components/box.md +98 -34
- package/docs/components/breadcrumbs.md +75 -6
- package/docs/components/button.md +2 -2
- package/docs/components/capture.md +8 -8
- package/docs/components/checkbox.md +21 -16
- package/docs/components/input-autocomplete.md +6 -0
- package/docs/components/input-date.md +8 -2
- package/docs/components/input.md +99 -40
- package/docs/components/menu.md +5 -6
- package/docs/components/panel.md +189 -0
- package/docs/components/radio.md +16 -13
- package/docs/components/select-faceted.md +58 -2
- package/docs/components/select.md +72 -59
- package/docs/components/steps.md +4 -4
- package/docs/components/switch.md +16 -10
- package/docs/components/tabs.md +21 -8
- package/docs/components/tag.md +5 -3
- package/docs/components/tooltip.md +6 -4
- package/docs/index.md +1 -0
- package/docs/install-config.md +23 -12
- package/docs/normalization.md +6 -4
- package/docs/theming.md +95 -17
- package/package.json +8 -4
- package/dist/components/InputDate.module.css +0 -1
- package/dist/components/Select.module.css +0 -1
- package/dist/components/SelectFaceted.module.css +0 -1
- package/dist/search-index.json +0 -0
- package/dist/theme-anta.css +0 -1
|
@@ -14,6 +14,12 @@ application-defined facet keys, not Anta terms. Each facet has one of four
|
|
|
14
14
|
Use `value` with `onValueChange` to control it, or use `defaultValue` for an
|
|
15
15
|
uncontrolled filter.
|
|
16
16
|
|
|
17
|
+
Without `searchable`, the trigger opens a menu of facets. With `searchable`, it
|
|
18
|
+
opens a dialog containing the search field and that menu. A filtered option
|
|
19
|
+
facet also opens a dialog containing its search field and options menu. Text and
|
|
20
|
+
custom facets use dialogs for their editable content. An unfiltered option facet
|
|
21
|
+
keeps the menu popup pattern.
|
|
22
|
+
|
|
17
23
|
Pass `placement` to control where the root facet menu opens relative to its
|
|
18
24
|
trigger. It uses the same values as `Menu` and still flips or clamps when space
|
|
19
25
|
is limited. `offset` sets the gap in pixels between the trigger and the menu:
|
|
@@ -22,11 +28,32 @@ is limited. `offset` sets the gap in pixels between the trigger and the menu:
|
|
|
22
28
|
<SelectFaceted placement="top-end" offset={8} facets={FACETS} />
|
|
23
29
|
```
|
|
24
30
|
|
|
31
|
+
Open **Metadata** in the first demo to choose key–value tags such as
|
|
32
|
+
**env production** or **region us-east**. Its `renderOption` callback reads
|
|
33
|
+
custom option fields and renders a `Tag` with `label` and `value`. Search
|
|
34
|
+
for **production** to see the same tag in global results.
|
|
35
|
+
|
|
25
36
|
```tsx
|
|
26
37
|
const FACETS = [
|
|
27
38
|
{ key: 'assignee', label: 'Assignee', kind: 'multiple', filter: true, options: people },
|
|
28
39
|
{ key: 'owner', label: 'Owner', kind: 'single', filter: true, options: people },
|
|
29
40
|
{ key: 'status', label: 'Status', kind: 'single', options: [{ value: 'open', label: 'Open' }, /* … */] },
|
|
41
|
+
{
|
|
42
|
+
key: 'metadata',
|
|
43
|
+
label: 'Metadata',
|
|
44
|
+
kind: 'multiple',
|
|
45
|
+
icon: 'tag',
|
|
46
|
+
filter: true,
|
|
47
|
+
options: [
|
|
48
|
+
{ value: 'env:production', label: 'env: production', dataKey: 'env', dataValue: 'production' },
|
|
49
|
+
{ value: 'env:staging', label: 'env: staging', dataKey: 'env', dataValue: 'staging' },
|
|
50
|
+
{ value: 'region:us-east', label: 'region: us-east', dataKey: 'region', dataValue: 'us-east' },
|
|
51
|
+
{ value: 'team:platform', label: 'team: platform', dataKey: 'team', dataValue: 'platform' },
|
|
52
|
+
],
|
|
53
|
+
renderOption: (option) => (
|
|
54
|
+
<Tag label={String(option.dataKey)} value={String(option.dataValue)} />
|
|
55
|
+
),
|
|
56
|
+
},
|
|
30
57
|
{ key: 'title', label: 'Title contains', kind: 'text' },
|
|
31
58
|
{ key: 'duration', label: 'Min duration', kind: 'custom', summary: (v) => `≥ ${v.min}s`, render: /* … */ },
|
|
32
59
|
]
|
|
@@ -68,6 +95,7 @@ function Demo() {
|
|
|
68
95
|
selection={facet.kind}
|
|
69
96
|
indicator={facet.kind === 'single' ? 'check' : undefined}
|
|
70
97
|
options={facet.options}
|
|
98
|
+
renderOption={facet.renderOption}
|
|
71
99
|
value={value[facet.key]}
|
|
72
100
|
onValueChange={(v) => setFacet(facet.key, v)}
|
|
73
101
|
leading={`${facet.label}:`}
|
|
@@ -120,6 +148,27 @@ The trigger opens the facet menu. The example renders one editable
|
|
|
120
148
|
[Select](./select.md) below it for each active facet. Each Select receives the
|
|
121
149
|
facet label through `leading`, which displays it as a prefix.
|
|
122
150
|
|
|
151
|
+
### Custom option content
|
|
152
|
+
|
|
153
|
+
Pass `renderOption(option, state)` on a `single` or `multiple` facet to replace
|
|
154
|
+
each option's label, hint, and icon layout. It runs in both the facet flyout and
|
|
155
|
+
global search results. `state` contains `value`, `selected`, and `disabled`.
|
|
156
|
+
Selection handling, indicators, and option styling remain on the row.
|
|
157
|
+
Return `null` to use the default layout for an option.
|
|
158
|
+
|
|
159
|
+
The first demo's **Metadata** facet stores the key and value in custom option
|
|
160
|
+
fields. Pass them to Tag's `label` and `value` props:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
renderOption: (option) => (
|
|
164
|
+
<Tag label={String(option.dataKey)} value={String(option.dataValue)} />
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Filtering still uses `value`, `label`, and `hint`, or the facet's custom `filter`
|
|
169
|
+
function. Keep searchable text in those fields. Single-facet summaries still
|
|
170
|
+
use the option label, and multiple-facet summaries show the selected count.
|
|
171
|
+
|
|
123
172
|
### Value and changes
|
|
124
173
|
|
|
125
174
|
The value is a record keyed by facet key: `{ [facetKey]: value }`. Its shape
|
|
@@ -373,11 +422,12 @@ const recency: SelectFacetCustom<Recency> = {
|
|
|
373
422
|
| `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
423
|
| `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. |
|
|
375
424
|
| `priority?` | 'primary' \| 'secondary' | secondary | Default trigger's button priority. |
|
|
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=
|
|
425
|
+
| `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={searchable ? 'dialog' : '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
426
|
| `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. |
|
|
378
427
|
| `searchPlaceholder?` | string | Filter… | Placeholder for the global search field. |
|
|
379
428
|
| `size?` | 'small' \| 'medium' \| 'large' | medium | Default trigger's button size. |
|
|
380
|
-
| `
|
|
429
|
+
| `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | — | Default option-row tone in facet flyouts. An option's own `tone` wins. |
|
|
430
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply the default row tone in every state, or only to selected rows. An option's own `toneScope` wins. |
|
|
381
431
|
| `value?` | SelectFacetedValue | — | Controlled value record, keyed by facet. When provided, update it through `onValueChange`. Leave it undefined for uncontrolled use. |
|
|
382
432
|
|
|
383
433
|
### The `SelectFacet` type
|
|
@@ -390,6 +440,12 @@ properties as [Select](./select.md). They use `kind` in place of Select's
|
|
|
390
440
|
`selection`. `text` and `custom` do not use Select options. A `single` facet
|
|
391
441
|
returns one option value; a `multiple` facet returns an array of option values.
|
|
392
442
|
|
|
443
|
+
When `selectAll` is enabled, Alt-clicking an option in a `multiple` facet clears
|
|
444
|
+
the other values and selects that option. Use Option-click on macOS. After a
|
|
445
|
+
700ms hover, a tooltip beside the row describes the shortcut. Moving to another
|
|
446
|
+
row restarts the delay. An option's `tooltip` replaces that hint; set it
|
|
447
|
+
to `''` to hide the hint.
|
|
448
|
+
|
|
393
449
|
| Field | Type | Description |
|
|
394
450
|
|---|---|---|
|
|
395
451
|
| `key` | `string` | The key for this facet's value in the record. `attrs.facet` returns it. It must be unique in `facets`. |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
field shows the selected value. Click the field to open the menu. The menu
|
|
5
5
|
closes when a user clicks outside it or presses Esc.
|
|
6
6
|
|
|
7
|
-
Select uses an [
|
|
7
|
+
Select uses an [Anta Button](./button.md) for its field and a [Menu](./menu.md) for its
|
|
8
8
|
dropdown. Pass `options` as an array of strings or objects. Use `value` with
|
|
9
9
|
**`onValueChange`** to control the selection, or use `defaultValue` for an
|
|
10
10
|
uncontrolled Select.
|
|
@@ -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"
|
|
44
|
-
<Select indicator="radio"
|
|
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
|
|
@@ -70,7 +70,8 @@ its box goes mixed when only some are on. Pass **`selectAll={false}`** to drop i
|
|
|
70
70
|
|
|
71
71
|
In a multi-select, **`Alt`+Click** a row to clear every other selection and
|
|
72
72
|
select that row. On macOS, use Option instead of Alt.
|
|
73
|
-
|
|
73
|
+
After hovering for 700ms, the standard tooltip describes this shortcut beside
|
|
74
|
+
the row. Moving to another row restarts the delay.
|
|
74
75
|
Set `SelectOption.tooltip` to replace it, or to `''` to hide it. The shortcut
|
|
75
76
|
is available only when `selectAll` is enabled, so `selectAll={false}` removes it.
|
|
76
77
|
|
|
@@ -78,9 +79,9 @@ Each checkable row is the control itself (`role="menuitemcheckbox"` /
|
|
|
78
79
|
`menuitemradio`, `aria-checked`); the checkbox / radio / check is a passive indicator
|
|
79
80
|
the row drives.
|
|
80
81
|
|
|
81
|
-
**`
|
|
82
|
-
label, icon, indicator, and tint. Pass a named tone or
|
|
83
|
-
keeps its hue, with lightness pinned to the brand text). It reads strongest with
|
|
82
|
+
Use **`tone`** with **`toneScope="selected"`** to tone only selected rows: the whole
|
|
83
|
+
row takes the tone, including label, icon, indicator, and tint. Pass a named tone or
|
|
84
|
+
any CSS color (a custom color keeps its hue, with lightness pinned to the brand text). It reads strongest with
|
|
84
85
|
`indicator` `none` / `check`, which show the row tint; `radio` / `checkbox` have no
|
|
85
86
|
row tint, so it tones the label and indicator only.
|
|
86
87
|
|
|
@@ -105,12 +106,14 @@ option's **value, label, or hint**. It's **whitespace-flexible** (a typed space
|
|
|
105
106
|
matches any run of whitespace) and **bolds the matched substring** in the results.
|
|
106
107
|
Pass a **function** `(option, query) => boolean` for custom matching (no highlight).
|
|
107
108
|
|
|
108
|
-
With `filter`,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
With `filter`, the trigger opens a dialog containing the search field and an
|
|
110
|
+
options menu. This keeps the textbox outside the menu in the accessibility tree.
|
|
111
|
+
Opening the dialog focuses the search field. ↑ and ↓ move
|
|
112
|
+
through matching options while focus stays in that field. Enter
|
|
113
|
+
selects the active option, and Esc closes the dialog. The search field
|
|
114
|
+
stays visible while the results scroll. A "No matches" row appears when nothing
|
|
115
|
+
matches, and the query resets when the dialog closes. In `multiple` mode,
|
|
116
|
+
`selectAll` affects only the visible matches.
|
|
114
117
|
|
|
115
118
|
## Value and changes
|
|
116
119
|
|
|
@@ -229,7 +232,7 @@ section marks the leaf everywhere it occurs (selection is value-keyed).
|
|
|
229
232
|
<Select status="info" statusIcon="sparkles" hint="Custom glyph" options={OPTIONS} defaultValue="stream" />
|
|
230
233
|
```
|
|
231
234
|
|
|
232
|
-
The trigger is an [
|
|
235
|
+
The trigger is an [Anta Button](./button.md) styled as a field.
|
|
233
236
|
**`size`** (`small` · `medium` · `large`) sets the height and type scale.
|
|
234
237
|
**`status`** paints a validation tone on the border, `hint`, and chevron, and
|
|
235
238
|
prefixes a glyph (`info` / `success` / `warning` / `critical`); **`statusIcon`**
|
|
@@ -245,7 +248,7 @@ the glyph and, for `critical`, validity. See the
|
|
|
245
248
|
## Customization
|
|
246
249
|
|
|
247
250
|
Select has no `<a-select>` element. The React and Preact wrapper coordinates an
|
|
248
|
-
|
|
251
|
+
Anta Button and a Menu. You can use the wrapper, render custom option content with
|
|
249
252
|
`renderOption`, replace its selection mark with `renderIndicator`, or build the
|
|
250
253
|
same interaction from the raw elements.
|
|
251
254
|
|
|
@@ -259,22 +262,21 @@ uses the same values as `Menu` and still flips or clamps when space is limited.
|
|
|
259
262
|
|
|
260
263
|
### Build it from elements
|
|
261
264
|
|
|
262
|
-
The wrapper renders a
|
|
265
|
+
The wrapper renders a `<Button>` immediately followed by a `<Menu>`, with a label
|
|
266
|
+
and hint inside an `<a-select-field>` layout wrapper. It updates the field
|
|
263
267
|
and each option's `selected` state from the value, and reports a pick through
|
|
264
268
|
`onValueChange`. Menu handles positioning, dismissal, and keyboard navigation.
|
|
265
269
|
|
|
266
270
|
The following example shows the equivalent markup without React or Preact. Place
|
|
267
|
-
the Menu directly after the
|
|
271
|
+
the Menu directly after the Button so it can use that Button as its trigger.
|
|
268
272
|
|
|
269
273
|
```html
|
|
270
274
|
<!-- `.select` scopes this example's CSS. Use an application selector instead. -->
|
|
271
275
|
<div class="select" style="width: 240px">
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
<a-icon slot="trailing" shape="chevron-down" style="transition: transform 150ms ease"></a-icon>
|
|
277
|
-
</a-input>
|
|
276
|
+
<a-button role="button" tabindex="0" aria-label="Field" aria-haspopup="menu" aria-expanded="false">
|
|
277
|
+
<a-button-label>stream</a-button-label>
|
|
278
|
+
<a-icon shape="chevron-down" aria-hidden="true" style="transition: transform 150ms ease"></a-icon>
|
|
279
|
+
</a-button>
|
|
278
280
|
<a-menu role="menu">
|
|
279
281
|
<a-menu-item role="menuitemradio" tabindex="0" aria-checked="false" value="output_text"><a-menu-item-label>output_text</a-menu-item-label></a-menu-item>
|
|
280
282
|
<a-menu-item role="menuitemradio" tabindex="0" aria-checked="true" value="stream" selected><a-menu-item-label>stream</a-menu-item-label></a-menu-item>
|
|
@@ -284,12 +286,14 @@ the Menu directly after the Input so it can use that Input as its trigger.
|
|
|
284
286
|
<script type="module">
|
|
285
287
|
import '@antadesign/anta/elements'
|
|
286
288
|
const root = document.querySelector('.select')
|
|
287
|
-
const field = root.querySelector('a-
|
|
289
|
+
const field = root.querySelector('a-button')
|
|
288
290
|
const menu = root.querySelector('a-menu')
|
|
289
291
|
const chevron = field.querySelector('a-icon')
|
|
290
292
|
// Flip the chevron with the menu's open state (as <Select> does).
|
|
291
293
|
menu.addEventListener('statechange', (e) => {
|
|
292
|
-
|
|
294
|
+
const open = e.detail.next === 'open'
|
|
295
|
+
field.setAttribute('aria-expanded', String(open))
|
|
296
|
+
chevron.style.transform = open ? 'rotate(180deg)' : ''
|
|
293
297
|
})
|
|
294
298
|
// On pick: mark the row selected + reflect its label into the field.
|
|
295
299
|
menu.addEventListener('click', (e) => {
|
|
@@ -300,12 +304,16 @@ the Menu directly after the Input so it can use that Input as its trigger.
|
|
|
300
304
|
el.toggleAttribute('selected', selected)
|
|
301
305
|
el.setAttribute('aria-checked', String(selected))
|
|
302
306
|
})
|
|
303
|
-
field.
|
|
307
|
+
field.querySelector('a-button-label').textContent = item.querySelector('a-menu-item-label').textContent
|
|
304
308
|
})
|
|
305
309
|
</script>
|
|
306
310
|
```
|
|
307
311
|
|
|
308
312
|
The React and Preact `Select` wrapper performs those updates for you.
|
|
313
|
+
Because the Menu directly follows the Anta Button, it associates the focused
|
|
314
|
+
field with the popup through a direct ARIA element reference. No popup ID is
|
|
315
|
+
required. If a custom composition supplies its own `aria-controls`, Anta keeps
|
|
316
|
+
that authored relationship.
|
|
309
317
|
|
|
310
318
|
### Custom option rendering
|
|
311
319
|
|
|
@@ -461,7 +469,7 @@ empty selection still shows the `placeholder` — and takes the resolved `select
|
|
|
461
469
|
options (`selected.length` is the count). Return `undefined` for any case you'd rather
|
|
462
470
|
leave to the default, as above for the single-label case.
|
|
463
471
|
|
|
464
|
-
Return a **string**: it flows into the same
|
|
472
|
+
Return a **string**: it flows into the same Button label the default uses, so a
|
|
465
473
|
long summary **ellipsizes at the field's width** the way a long value does
|
|
466
474
|
(`Engineering, Design, … `). For rich content — chips, several nodes — reach for
|
|
467
475
|
`renderTrigger` below, which replaces the whole field.
|
|
@@ -523,7 +531,8 @@ focusable element, such as the Anta `Button` in this example. Select positions
|
|
|
523
531
|
the menu relative to that element and opens it when it is clicked. A fragment,
|
|
524
532
|
multiple sibling elements, or a non-focusable wrapper prevents Select from finding
|
|
525
533
|
the trigger. It logs a console warning when that happens. Add
|
|
526
|
-
`aria-haspopup=
|
|
534
|
+
`aria-haspopup={filter ? 'dialog' : 'menu'}` and
|
|
535
|
+
`aria-expanded={state.open}` to the element.
|
|
527
536
|
|
|
528
537
|
`state` includes `open`, `value`, `selected`, `disabled`, and `icon`. `selected`
|
|
529
538
|
is the resolved option list, so `selected.length` is the multi-select count. The
|
|
@@ -633,11 +642,11 @@ scannable list instead of hiding matches behind flyouts.
|
|
|
633
642
|
| `defaultValue?` | V \| V[] | — | Initial selected option value for uncontrolled use. |
|
|
634
643
|
| `disabled?` | boolean | — | Disable the whole select. |
|
|
635
644
|
| `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). |
|
|
636
|
-
| `hint?` | string | — | Helper text under the field
|
|
637
|
-
| `icon?` | IconShape | — | Leading icon shown at the left of the field
|
|
645
|
+
| `hint?` | string | — | Helper text under the field. |
|
|
646
|
+
| `icon?` | IconShape | — | Leading icon shown at the left of the field. With a custom `renderTrigger`, it's passed through as `state.icon` instead — the consumer places it. |
|
|
638
647
|
| `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. |
|
|
639
|
-
| `label?` | string | — | Field label, above the trigger
|
|
640
|
-
| `leading?` | ReactNode | — | Content
|
|
648
|
+
| `label?` | string | — | Field label, above the trigger. |
|
|
649
|
+
| `leading?` | ReactNode | — | Content before the default trigger's value, 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`. |
|
|
641
650
|
| `offset?` | number | 4 | Gap in pixels between the trigger and the options menu. |
|
|
642
651
|
| `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). |
|
|
643
652
|
| `placeholder?` | string | — | Text shown when nothing is selected. |
|
|
@@ -645,18 +654,19 @@ scannable list instead of hiding matches behind flyouts.
|
|
|
645
654
|
| `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
655
|
| `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
656
|
| `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
|
|
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=
|
|
657
|
+
| `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 Button label, 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. |
|
|
658
|
+
| `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={filter ? 'dialog' : 'menu'}` and `aria-expanded={state.open}` to the returned button. An Anta `Button` already carries the correct role. 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. |
|
|
650
659
|
| `round?` | boolean \| number \| string | — | Round the field corners — `true` for fully round, or a number / CSS length. |
|
|
651
660
|
| `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. |
|
|
652
661
|
| `selectAllLabel?` | string | Select all | Label for the `selectAll` row. |
|
|
653
662
|
| `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. |
|
|
654
663
|
| `size?` | 'small' \| 'medium' \| 'large' | medium | Field size. |
|
|
655
|
-
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | neutral | Validation/feedback tone for the field
|
|
656
|
-
| `statusIcon?` | (string & {}) \| false \| IconShape | — | Glyph shown before the `hint` when `status` is set
|
|
657
|
-
| `
|
|
664
|
+
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | neutral | Validation/feedback tone for the field. |
|
|
665
|
+
| `statusIcon?` | (string & {}) \| false \| IconShape | — | Glyph shown before the `hint` when `status` is set. Each status has a default; pass a shape to override, or `false` to drop it. |
|
|
666
|
+
| `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. |
|
|
667
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply the default row tone in every state, or only to selected rows. An option's own `toneScope` wins. |
|
|
658
668
|
| `value?` | V \| V[] | — | Controlled value: the selected option's `value`. Update it through `onValueChange`. Leave it undefined for uncontrolled use. |
|
|
659
|
-
| `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
|
|
669
|
+
| `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 Button label, so it ellipsizes at the field's width when long (`3 selected: Engineering, Des… `). `renderSummary` overrides this. |
|
|
660
670
|
|
|
661
671
|
### The `SelectItem` type
|
|
662
672
|
|
|
@@ -756,16 +766,16 @@ inline `SelectGroup`, and a flyout `SelectSubmenu` (whose items are themselves
|
|
|
756
766
|
|
|
757
767
|
Use the web component directly when you are not using React or Preact and a native control does not fit.
|
|
758
768
|
|
|
759
|
-
`Select`
|
|
769
|
+
`Select` uses a layout wrapper. Compose an `<a-button>` trigger with an
|
|
760
770
|
`<a-menu>` of options. The menu owns opening and dismissal; the short controller
|
|
761
771
|
reflects a picked option into the field and selected row.
|
|
762
772
|
|
|
763
773
|
```html
|
|
764
774
|
<div data-anta-composition="select" style="display: grid; gap: 4px; width: 280px">
|
|
765
|
-
<a-
|
|
766
|
-
<
|
|
767
|
-
<
|
|
768
|
-
</a-
|
|
775
|
+
<a-button role="button" tabindex="0" aria-label="Output" aria-haspopup="menu" aria-expanded="false">
|
|
776
|
+
<a-button-label>stream</a-button-label>
|
|
777
|
+
<a-icon shape="chevron-down" aria-hidden="true"></a-icon>
|
|
778
|
+
</a-button>
|
|
769
779
|
<a-menu role="menu">
|
|
770
780
|
<a-menu-item role="menuitem" tabindex="0" value="output_text"><a-menu-item-label>output_text</a-menu-item-label></a-menu-item>
|
|
771
781
|
<a-menu-item role="menuitem" tabindex="0" value="stream" selected><a-menu-item-label>stream</a-menu-item-label></a-menu-item>
|
|
@@ -775,8 +785,11 @@ reflects a picked option into the field and selected row.
|
|
|
775
785
|
import '@antadesign/anta/elements'
|
|
776
786
|
|
|
777
787
|
const root = document.querySelector('[data-anta-composition="select"]')
|
|
778
|
-
const field = root.querySelector('a-
|
|
788
|
+
const field = root.querySelector('a-button')
|
|
779
789
|
const menu = root.querySelector('a-menu')
|
|
790
|
+
menu.addEventListener('statechange', (event) => {
|
|
791
|
+
field.setAttribute('aria-expanded', String(event.detail.next === 'open'))
|
|
792
|
+
})
|
|
780
793
|
|
|
781
794
|
menu.addEventListener('click', (event) => {
|
|
782
795
|
const item = event.target instanceof Element ? event.target.closest('a-menu-item') : null
|
|
@@ -785,7 +798,7 @@ reflects a picked option into the field and selected row.
|
|
|
785
798
|
const selected = option === item
|
|
786
799
|
option.toggleAttribute('selected', selected)
|
|
787
800
|
})
|
|
788
|
-
field.
|
|
801
|
+
field.querySelector('a-button-label').textContent = item.querySelector('a-menu-item-label').textContent.trim()
|
|
789
802
|
})
|
|
790
803
|
</script>
|
|
791
804
|
```
|
|
@@ -823,36 +836,36 @@ corners.
|
|
|
823
836
|
|
|
824
837
|
## Styling
|
|
825
838
|
|
|
826
|
-
Select
|
|
827
|
-
inherits both surfaces' hooks. Reach for props first, then plain CSS or `::part` for
|
|
839
|
+
Select composes an [Anta Button](./button.md) and a [Menu](./menu.md). Reach for props first, then plain CSS or `::part` for
|
|
828
840
|
the rest. Don't override an element's internal `--*` output tokens.
|
|
829
841
|
|
|
830
|
-
**Selection color** routes through
|
|
831
|
-
for
|
|
842
|
+
**Selection color** routes through `tone`: set it per option or on the Select as a
|
|
843
|
+
default, then use `toneScope="selected"` for chosen rows only. It takes a named tone or any CSS color (a custom color keeps
|
|
832
844
|
its hue, with lightness pinned to the brand text).
|
|
833
845
|
|
|
834
|
-
**The field**
|
|
835
|
-
|
|
836
|
-
|
|
846
|
+
**The field** takes `size`, `status`, and `round`. Set its width with `style` /
|
|
847
|
+
`className`, forwarded to the `<a-select-field>` wrapper. Style the trigger through
|
|
848
|
+
`a-select-field > a-button` and its `a-button-label`. The trigger uses
|
|
849
|
+
`:focus-visible` for its focus ring and ellipsizes long values. **The popover**
|
|
850
|
+
takes Menu's `::part(menu)`.
|
|
837
851
|
|
|
838
852
|
```tsx
|
|
839
853
|
// Tone the selection; give the trigger a width.
|
|
840
|
-
<Select
|
|
854
|
+
<Select tone="brand" toneScope="selected" style={{ width: '220px' }} options={OPTIONS} />
|
|
841
855
|
```
|
|
842
856
|
|
|
843
857
|
**Borderless trigger.** The field's border is an inset `box-shadow`, so you can drop
|
|
844
858
|
it *at rest* and let the standard hover / focus shadow return on its own; no need to
|
|
845
859
|
re-declare it. Pair that with hiding the chevron for a field that reads as plain text
|
|
846
|
-
until you reach for it. Hide the chevron by targeting
|
|
847
|
-
wrapper is inline-`display:contents`, so hit the icon itself).
|
|
860
|
+
until you reach for it. Hide the chevron by targeting `a-select-chevron`.
|
|
848
861
|
|
|
849
862
|
```css
|
|
850
863
|
/* Drop the resting border-shadow; the standard hover / focus shadow still shows. */
|
|
851
|
-
.ghost-select a-
|
|
864
|
+
.ghost-select a-select-field > a-button:not(:hover):not(:focus-visible) {
|
|
852
865
|
box-shadow: none;
|
|
853
866
|
}
|
|
854
867
|
/* Center the chosen label in the field. */
|
|
855
|
-
.ghost-select a-
|
|
856
|
-
/*
|
|
857
|
-
.ghost-select a-
|
|
868
|
+
.ghost-select a-select-field > a-button > a-button-label { text-align: center; }
|
|
869
|
+
/* Hide the chevron. */
|
|
870
|
+
.ghost-select a-select-chevron { display: none; }
|
|
858
871
|
```
|
package/docs/components/steps.md
CHANGED
|
@@ -260,10 +260,10 @@ Events match [`Tabs`](./tabs.md#events).
|
|
|
260
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
261
|
| `onValueChange?` | (event, attrs) => void | — | Like `onChange`, but with a `{ value }` snapshot as the 2nd argument. |
|
|
262
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?` |
|
|
263
|
+
| `priority?` | 'primary' \| 'secondary' \| 'tertiary' | '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
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
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?` |
|
|
266
|
+
| `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| '' | 'neutral' | Tone applied to every step without its own `tone`. Error steps stay critical and disabled steps stay neutral. |
|
|
267
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
268
|
|
|
269
269
|
## Step option props
|
|
@@ -271,14 +271,14 @@ Events match [`Tabs`](./tabs.md#events).
|
|
|
271
271
|
| Prop | Type | Default | Description |
|
|
272
272
|
|------|------|---------|-------------|
|
|
273
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` |
|
|
274
|
+
| `state` | 'incomplete' \| 'loading' \| 'completed' \| 'error' | — | Application-owned process state. Selection and availability are separate; `error` keeps a critical icon and outline, and selection adds the fill. |
|
|
275
275
|
| `value` | string | — | Stable phase identity. Values must be unique within the sequence. |
|
|
276
276
|
| `className?` | string | — | CSS class on the option's rendered row. |
|
|
277
277
|
| `disabled?` | boolean | — | Disables this phase. A custom `marker` or `renderMarker` result is kept; otherwise it uses the incomplete marker. |
|
|
278
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
279
|
| `marker?` | StepMarker | — | Replaces the marker derived from `state`. A number is shown directly; an Anta icon shape is rendered as an `<Icon>`. |
|
|
280
280
|
| `style?` | CSSProperties | — | Inline styles on the option's rendered row. |
|
|
281
|
-
| `tone?` |
|
|
281
|
+
| `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| '' | 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
282
|
|
|
283
283
|
## Web Component
|
|
284
284
|
|
|
@@ -6,6 +6,8 @@ The `Switch` wrapper renders a form-associated `<a-switch>` element. It works un
|
|
|
6
6
|
|
|
7
7
|
## Tone
|
|
8
8
|
|
|
9
|
+
Switch is neutral by default. Pass `tone="brand"` or another tone to color the control.
|
|
10
|
+
|
|
9
11
|
`tone` colors the whole control: the checked track, plus the unchecked track border and thumb. Six named tones are available, or pass any CSS color for a custom tone. The label and hint stay neutral.
|
|
10
12
|
|
|
11
13
|
```tsx
|
|
@@ -17,16 +19,16 @@ The `Switch` wrapper renders a form-associated `<a-switch>` element. It works un
|
|
|
17
19
|
|
|
18
20
|
## Selected-only tone
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
To apply a tone only while selected, pass `toneScope="selected"` together with `tone`, such as `tone="brand"`. Only the checked track is tinted; the unchecked track border and thumb stay neutral.
|
|
21
23
|
|
|
22
24
|
```tsx
|
|
23
|
-
<Switch
|
|
24
|
-
<Switch defaultChecked
|
|
25
|
+
<Switch tone="brand" toneScope="selected" label="Off stays neutral" />
|
|
26
|
+
<Switch defaultChecked tone="critical" toneScope="selected" label="Checked track tinted" />
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
## Coloring the text
|
|
28
30
|
|
|
29
|
-
There is no text-tone prop. To tint the label, set `color` on the switch with a theme-aware `--text-N-{tone}` token; to tint the hint, target `a-switch-hint`. Pair either with `tone`
|
|
31
|
+
There is no text-tone prop. To tint the label, set `color` on the switch with a theme-aware `--text-N-{tone}` token; to tint the hint, target `a-switch-hint`. Pair either with `tone` to color the whole control.
|
|
30
32
|
|
|
31
33
|
```css
|
|
32
34
|
/* The class is only for the demo — use your own selector. */
|
|
@@ -119,7 +121,10 @@ Use **`onStateChange`** to intercept a toggle or drive a controlled switch. Use
|
|
|
119
121
|
|
|
120
122
|
## Accessibility
|
|
121
123
|
|
|
122
|
-
The wrapper sets `role="switch"
|
|
124
|
+
The wrapper sets `role="switch"`, and the element keeps `aria-checked` in sync
|
|
125
|
+
with the current value. Its light-DOM label supplies the accessible name and its
|
|
126
|
+
hint supplies the accessible description through `ElementInternals`; no generated
|
|
127
|
+
IDs are needed. For a label-less switch, pass `aria-label`.
|
|
123
128
|
|
|
124
129
|
Space toggles the switch. It follows the [WAI-ARIA switch pattern](https://www.w3.org/WAI/ARIA/apg/patterns/switch/).
|
|
125
130
|
|
|
@@ -130,7 +135,7 @@ Space toggles the switch. It follows the [WAI-ARIA switch pattern](https://www.w
|
|
|
130
135
|
| `checked?` | boolean | — | Controlled checked value. In controlled mode, update this in `onStateChange`. |
|
|
131
136
|
| `defaultChecked?` | boolean | false | Initial checked value for an uncontrolled switch. |
|
|
132
137
|
| `disabled?` | boolean | — | Disables interaction and removes the switch from the tab order. |
|
|
133
|
-
| `hint?` | ReactNode | — | Secondary text rendered under the label. It does not become part of the accessible name. |
|
|
138
|
+
| `hint?` | ReactNode | — | Secondary text rendered under the label and exposed as the switch's accessible description. It does not become part of the accessible name. |
|
|
134
139
|
| `label?` | string | — | Visible, stable label for the setting. Use `children` for richer label content. |
|
|
135
140
|
| `labelPosition?` | 'start' \| 'end' | 'end' | Put the visible label before or after the control. Grid layout changes only the visual order, preserving DOM/source order for assistive technologies. |
|
|
136
141
|
| `name?` | string | — | Form field name. A checked switch submits `value` under this name. |
|
|
@@ -139,15 +144,16 @@ Space toggles the switch. It follows the [WAI-ARIA switch pattern](https://www.w
|
|
|
139
144
|
| `onValueChange?` | (event, attrs) => void | — | Post-apply callback with the new form-relevant value snapshot. |
|
|
140
145
|
| `round?` | boolean \| number \| string | — | Fully round the thumb and track. Pass a `number` (px) or CSS length string for a custom track radius; the thumb radius is 3px smaller. |
|
|
141
146
|
| `size?` | 'small' \| 'medium' \| 'large' | 'medium' | Size variant. small=26×16px, medium=30×18px, large=34×20px. |
|
|
142
|
-
| `tone?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | '
|
|
143
|
-
| `
|
|
147
|
+
| `tone?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the track and thumb. A tinted tone also colors the unchecked track border and thumb; use `toneScope="selected"` to color only the checked track. |
|
|
148
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply `tone` to every state, or only while checked so the unchecked track and thumb stay neutral. |
|
|
144
149
|
| `value?` | string | "on" | Value submitted while checked. |
|
|
145
150
|
|
|
146
151
|
## Web Component
|
|
147
152
|
|
|
148
153
|
Use the web component directly when you are not using React or Preact and a native control does not fit.
|
|
149
154
|
|
|
150
|
-
The focusable host carries the state. Label and hint are light-DOM children
|
|
155
|
+
The focusable host carries the state. Label and hint are light-DOM children that
|
|
156
|
+
the element exposes as its accessible name and description.
|
|
151
157
|
|
|
152
158
|
```html
|
|
153
159
|
<a-switch role="switch" tabindex="0" name="updates" default-state="checked">
|
|
@@ -158,7 +164,7 @@ The focusable host carries the state. Label and hint are light-DOM children.
|
|
|
158
164
|
|
|
159
165
|
## Styling
|
|
160
166
|
|
|
161
|
-
Reach for the props first: **`tone`**
|
|
167
|
+
Reach for the props first: **`tone`** chooses the control color, while **`toneScope`** chooses whether it colors all states or only the checked track. `tone` accepts any CSS color; **`size`** scales the control, label, and hint. The focus ring is the global [`--focus-ring`](../colors.md#focus-ring).
|
|
162
168
|
|
|
163
169
|
```tsx
|
|
164
170
|
<Switch tone="#e0457b" defaultChecked label="Custom color" />
|
package/docs/components/tabs.md
CHANGED
|
@@ -271,15 +271,17 @@ const [tab, setTab] = useState('overview')
|
|
|
271
271
|
|
|
272
272
|
## Keyboard & accessibility
|
|
273
273
|
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
The selected tab is in the page's tab order. Once focus enters the strip, the
|
|
275
|
+
arrow keys move between enabled tabs (wrapping at the ends), `Home` /
|
|
276
276
|
`End` jump to the first / last, and `Space` / `Enter` activate the focused tab;
|
|
277
277
|
arrow / `Home` / `End` navigation activates as it moves (selection follows focus).
|
|
278
278
|
Disabled tabs are skipped and dropped from the tab order.
|
|
279
279
|
|
|
280
280
|
Pass `label` for the tablist's accessible name. Each `<TabPanel>` names its tab as
|
|
281
281
|
its accessible label (`aria-labelledby`), set off-DOM so nothing writes the panel's
|
|
282
|
-
attributes.
|
|
282
|
+
attributes. Static panel content remains readable without making the panel a tab
|
|
283
|
+
stop. Set `tabIndex={0}` when you want a text-only panel itself to receive focus;
|
|
284
|
+
when the panel starts with a focusable control, Tab reaches that control directly.
|
|
283
285
|
|
|
284
286
|
## Routing
|
|
285
287
|
|
|
@@ -357,7 +359,7 @@ so those suit an uncontrolled strip reacting to its own pick. **`onFocus`** /
|
|
|
357
359
|
| `value` | string | — | This tab's identity — pairs it with the `<TabPanel value="…">` of the same value, and the value reported by `onStateChange` / `onChange`. Unique per strip. |
|
|
358
360
|
| `children?` | ReactNode | — | Tab content when you need more than a string — used if `label` is omitted. |
|
|
359
361
|
| `className?` | string | — | CSS class on the option's rendered row. |
|
|
360
|
-
| `disabled?` | boolean | — |
|
|
362
|
+
| `disabled?` | boolean | — | Prevent user activation of this tab. A disabled tab can still indicate the current selection. |
|
|
361
363
|
| `icon?` | IconShape | — | Leading icon shape, rendered before the label. |
|
|
362
364
|
| `iconTrailing?` | IconShape | — | Trailing icon shape, rendered after the label. |
|
|
363
365
|
| `label?` | ReactNode | — | Visible label. The string shorthand for the tab's content; for richer content pass `children` instead (`label` wins when both are set). |
|
|
@@ -371,17 +373,18 @@ so those suit an uncontrolled strip reacting to its own pick. **`onFocus`** /
|
|
|
371
373
|
| Prop | Type | Default | Description |
|
|
372
374
|
|------|------|---------|-------------|
|
|
373
375
|
| `value` | string | — | Pairs this panel with the tab (`options` entry) of the same `value`. |
|
|
374
|
-
| `children?` | ReactNode | — | Panel content — arbitrary React/Preact. |
|
|
375
|
-
| `className?` | string | — | CSS class on the rendered `<a-tabpanel>`. |
|
|
376
376
|
| `hideMode?` | 'display' \| 'visibility' | display | How this panel hides while inactive: `display` (default — removed from layout and the a11y tree) or `visibility` (keeps its layout box, to measure it or avoid reflow). Both stay mounted; to *not render* an inactive panel, render it conditionally off a controlled `value` (see the Tabs docs). |
|
|
377
|
-
| `style?` | CSSProperties | — | Inline style on the rendered `<a-tabpanel>`. |
|
|
378
377
|
|
|
379
378
|
## Web Component
|
|
380
379
|
|
|
381
380
|
Use the web component directly when you are not using React or Preact and a native control does not fit.
|
|
382
381
|
|
|
383
382
|
Keep the tab strip and panels as siblings under one parent. Panels read the active
|
|
384
|
-
value from `<a-tabs>`.
|
|
383
|
+
value from `<a-tabs>`. Give the selected tab `tabindex="0"` and the others
|
|
384
|
+
`tabindex="-1"`; `<a-tabs>` moves focus and selection with the arrow keys, while
|
|
385
|
+
your change handler updates those attributes for the next visit to the strip. Add
|
|
386
|
+
`tabindex="0"` to a text-only panel only when you want the panel itself in the page
|
|
387
|
+
Tab sequence.
|
|
385
388
|
|
|
386
389
|
Add `fill` to make horizontal tabs share the available width equally.
|
|
387
390
|
|
|
@@ -396,6 +399,16 @@ Add `fill` to make horizontal tabs share the available width equally.
|
|
|
396
399
|
</div>
|
|
397
400
|
```
|
|
398
401
|
|
|
402
|
+
```js title="Keep the raw DOM tab stop on the selected tab"
|
|
403
|
+
const tabs = document.querySelector('a-tabs')
|
|
404
|
+
|
|
405
|
+
tabs.addEventListener('change', () => {
|
|
406
|
+
for (const tab of tabs.querySelectorAll('a-tab')) {
|
|
407
|
+
tab.tabIndex = tab.getAttribute('value') === tabs.value ? 0 : -1
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
```
|
|
411
|
+
|
|
399
412
|
## Styling
|
|
400
413
|
|
|
401
414
|
Reach for the props first: **`tone`**, **`size`**, **`priority`**. The focus ring is
|