@antadesign/anta 0.3.28 → 0.3.30
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 +21 -0
- package/dist/anta_helpers.js +24 -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 +66 -29
- 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/Breadcrumbs.d.ts +1 -1
- package/dist/components/Button.d.ts +3 -3
- package/dist/components/ButtonCopy.d.ts +1 -1
- package/dist/components/Calendar.js +3 -5
- package/dist/components/Checkbox.d.ts +2 -2
- package/dist/components/Input.d.ts +8 -2
- package/dist/components/Input.js +4 -0
- package/dist/components/InputAutocomplete.js +3 -12
- package/dist/components/InputDate.css +1 -1
- package/dist/components/InputDate.js +2 -0
- package/dist/components/Menu.d.ts +4 -4
- package/dist/components/Menu.js +1 -1
- package/dist/components/Panel.d.ts +17 -0
- package/dist/components/Panel.js +22 -0
- package/dist/components/RadioGroup.d.ts +2 -1
- package/dist/components/Select.d.ts +14 -14
- package/dist/components/Select.js +47 -35
- package/dist/components/SelectFaceted.d.ts +17 -6
- package/dist/components/SelectFaceted.js +61 -41
- package/dist/components/Steps.css +1 -1
- package/dist/components/Switch.d.ts +3 -3
- 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 +2 -1
- 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 +76 -23
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +9 -1
- 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-icon.css +1 -1
- package/dist/elements/a-icon.shapes.css +1 -1
- package/dist/elements/a-icon.shapes.d.ts +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 +115 -8
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +27 -1
- package/dist/elements/a-input.js +176 -35
- 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 -3
- 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-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.js +30 -7
- 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 +48 -19
- package/dist/generate-icons.mjs +3 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/jsx-runtime.d.ts +20 -1
- package/dist/jsx-runtime.js +12 -0
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +1 -1
- package/dist/theme-antune.css +1 -1
- package/dist/toaster.d.ts +1 -1
- package/dist/tokens.css +1 -1
- package/docs/accessibility.md +4 -2
- package/docs/changelog.md +89 -4
- package/docs/colors.md +6 -6
- package/docs/components/box.md +98 -34
- package/docs/components/breadcrumbs.md +33 -0
- package/docs/components/button.md +2 -2
- package/docs/components/capture.md +8 -8
- package/docs/components/checkbox.md +9 -4
- 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 +3 -3
- package/docs/components/panel.md +189 -0
- package/docs/components/radio.md +4 -2
- package/docs/components/select-faceted.md +57 -2
- package/docs/components/select.md +63 -51
- package/docs/components/steps.md +4 -4
- package/docs/components/switch.md +12 -6
- package/docs/components/tabs.md +21 -8
- package/docs/components/tooltip.md +6 -4
- package/docs/index.md +2 -0
- package/docs/install-config.md +5 -4
- package/docs/normalization.md +3 -1
- package/docs/packages/plot.md +3771 -0
- package/docs/theming.md +1 -1
- package/package.json +16 -9
|
@@ -4,6 +4,9 @@ Hierarchy navigation assembled from Anta Buttons. Breadcrumb entries can be
|
|
|
4
4
|
links, actions, or copy controls. Set `maxItems` to fold one middle range into a
|
|
5
5
|
More menu without measuring the available width.
|
|
6
6
|
|
|
7
|
+
Breadcrumbs do not scroll horizontally by default. Use `maxItems` to limit
|
|
8
|
+
visible entries, or enable scrolling with the [scrolling recipe](#horizontal-scrolling).
|
|
9
|
+
|
|
7
10
|
## Items
|
|
8
11
|
|
|
9
12
|
Pass ordered `BreadcrumbItem` objects through `items`. Each item is a link,
|
|
@@ -212,3 +215,33 @@ with your own selector.
|
|
|
212
215
|
color: var(--text-2);
|
|
213
216
|
}
|
|
214
217
|
```
|
|
218
|
+
|
|
219
|
+
### Horizontal scrolling
|
|
220
|
+
|
|
221
|
+
Set `overflow-x: auto` on the trail to scroll when its contents exceed the
|
|
222
|
+
available width. `maxItems` limits the item count; long labels can still overflow.
|
|
223
|
+
|
|
224
|
+
Horizontal scrolling also makes vertical overflow compute to `auto`, which
|
|
225
|
+
clips the default button focus ring above and below the row. Set
|
|
226
|
+
`outline-offset: -1px` on the trail's focused controls to draw the ring inside
|
|
227
|
+
their bounds. The selector below covers breadcrumb links, action and copy
|
|
228
|
+
buttons, and the More control.
|
|
229
|
+
|
|
230
|
+
`scrolling-breadcrumbs` is an example class; replace it with your own selector.
|
|
231
|
+
Use Tab to move through the controls and see the focus ring.
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
<Box style={{ width: 280, maxWidth: '100%' }}>
|
|
235
|
+
<Breadcrumbs className="scrolling-breadcrumbs" maxItems={3} items={[
|
|
236
|
+
{ label: 'Anta', href: '/' },
|
|
237
|
+
{ label: 'Documentation', href: '/box/' },
|
|
238
|
+
{ label: 'Layout components', href: '/panel/' },
|
|
239
|
+
{ label: 'Breadcrumbs', current: true },
|
|
240
|
+
]} />
|
|
241
|
+
</Box>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```css
|
|
245
|
+
.scrolling-breadcrumbs { overflow-x: auto; }
|
|
246
|
+
.scrolling-breadcrumbs > :focus-visible { outline-offset: -1px; }
|
|
247
|
+
```
|
|
@@ -166,8 +166,8 @@ name "trash". Pass your own `aria-label` to override.
|
|
|
166
166
|
### Children
|
|
167
167
|
|
|
168
168
|
```tsx
|
|
169
|
-
<Button tone="brand" label="Save" icon="check">
|
|
170
|
-
<
|
|
169
|
+
<Button tone="brand" label="Save" icon="check" aria-keyshortcuts="Meta+s">
|
|
170
|
+
<kbd aria-hidden="true" style={{ font: 'inherit', fontVariationSettings: 'inherit', opacity: 0.7 }}>⌘S</kbd>
|
|
171
171
|
</Button>
|
|
172
172
|
```
|
|
173
173
|
|
|
@@ -214,9 +214,9 @@ native text selection or touch gestures.
|
|
|
214
214
|
| `onWheelInput?` | (event, detail) => void | — | Accepted wheel input, with a serialized original event, Capture-relative geometry, focus state, and activation reason. Cancellation is already complete. |
|
|
215
215
|
| `pan?` | boolean \| CapturePan | — | Emit custom pan motion. `true` enables touch panning on both axes without momentum. Options select devices, axes, bounds directions, and optional inertia. Captures the pointer internally; `pointerCapture` is not required. Sets CSS touch-action through attributes before the gesture starts. |
|
|
216
216
|
| `pointerCapture?` | boolean \| CapturePointerCapture | — | Emit raw data for a primary pointer until release or cancellation. An options object filters devices/buttons and configures activation. Nested interactive controls are excluded unless explicitly included. A listener alone enables nothing. |
|
|
217
|
-
| `wheelActivation?` |
|
|
217
|
+
| `wheelActivation?` | 'hover' \| 'settled' \| 'focus' \| 'settled-or-focus' | settled | Pointer or focus condition required before wheel input can be captured. Focus applies only to input targeted within this Capture. |
|
|
218
218
|
| `wheelCapture?` | CaptureInputDirections | — | Capture wheel input in the enabled directions and emit `onWheelInput`. `true` accepts all directions. Omit or pass `false` to leave wheel input alone. Nested native wheel controls and Anta menus are excluded. All-false direction bounds preserve pointer settling while declining input. A listener alone never enables capture. |
|
|
219
|
-
| `wheelModifier?` |
|
|
219
|
+
| `wheelModifier?` | 'none' \| 'any' \| 'alt' \| 'ctrl' \| 'meta' \| 'shift' | none | Required modifier for wheel capture. `none` preserves browser Ctrl/pinch zoom. |
|
|
220
220
|
| `wheelSettle?` | CaptureWheelSettle | { delay: 150, tolerance: 5, resetOnMove: false } | Dwell delay, movement tolerance, and whether movement resets eligibility. |
|
|
221
221
|
|
|
222
222
|
### CaptureWheelSettle
|
|
@@ -233,7 +233,7 @@ native text selection or touch gestures.
|
|
|
233
233
|
|------|------|---------|-------------|
|
|
234
234
|
| `buttons?` | readonly number[] | [0] | Accepted initiating buttons, using PointerEvent.button values. |
|
|
235
235
|
| `includeInteractive?` | boolean | false | Allow capture to start on nested native or ARIA controls, links, or editable regions. |
|
|
236
|
-
| `modifier?` |
|
|
236
|
+
| `modifier?` | 'none' \| 'any' \| 'alt' \| 'ctrl' \| 'meta' \| 'shift' | any | Modifier required to start a capture session. |
|
|
237
237
|
| `pointerTypes?` | readonly CapturePointerType[] | ['mouse', 'pen', 'touch'] | Accepted pointer devices. One primary pointer is tracked per Capture. |
|
|
238
238
|
| `threshold?` | number | 0 | Movement required before activation, in viewport CSS pixels. |
|
|
239
239
|
|
|
@@ -258,7 +258,7 @@ native text selection or touch gestures.
|
|
|
258
258
|
|
|
259
259
|
| Field | Type | Default | Description |
|
|
260
260
|
|------|------|---------|-------------|
|
|
261
|
-
| `activationReason` |
|
|
261
|
+
| `activationReason` | 'immediate' \| 'settled' \| 'focus' | — | |
|
|
262
262
|
| `boxHeight` | number | — | |
|
|
263
263
|
| `boxWidth` | number | — | Dimensions of the same viewport bounding rectangle, in CSS pixels. |
|
|
264
264
|
| `focusWithin` | boolean | — | |
|
|
@@ -271,7 +271,7 @@ native text selection or touch gestures.
|
|
|
271
271
|
|
|
272
272
|
| Field | Type | Default | Description |
|
|
273
273
|
|------|------|---------|-------------|
|
|
274
|
-
| `activationReason` |
|
|
274
|
+
| `activationReason` | 'pointer-down' \| 'drag-threshold' | — | |
|
|
275
275
|
| `boxHeight` | number | — | |
|
|
276
276
|
| `boxWidth` | number | — | Dimensions of the same viewport bounding rectangle, in CSS pixels. |
|
|
277
277
|
| `deltaX` | number | — | Movement since the previous delivered sample, in viewport CSS pixels. |
|
|
@@ -285,13 +285,13 @@ native text selection or touch gestures.
|
|
|
285
285
|
| `phase` | 'start' \| 'move' \| 'end' \| 'cancel' | — | |
|
|
286
286
|
| `pointerEvent` | SerializedPointerEvent \| null | — | Null when cancellation comes from lifecycle or configuration changes. |
|
|
287
287
|
| `start` | CapturePointerStart | — | |
|
|
288
|
-
| `cancelReason?` |
|
|
288
|
+
| `cancelReason?` | 'pointer-cancel' \| 'lost-capture' \| 'disabled' \| 'disconnected' \| 'blur' \| 'interrupted' | — | |
|
|
289
289
|
|
|
290
290
|
### CapturePanInput
|
|
291
291
|
|
|
292
292
|
| Field | Type | Default | Description |
|
|
293
293
|
|------|------|---------|-------------|
|
|
294
|
-
| `activationReason` |
|
|
294
|
+
| `activationReason` | 'pointer-down' \| 'drag-threshold' | — | |
|
|
295
295
|
| `boxHeight` | number | — | |
|
|
296
296
|
| `boxWidth` | number | — | Dimensions of the same viewport bounding rectangle, in CSS pixels. |
|
|
297
297
|
| `deltaX` | number | — | Incremental scroll motion in viewport CSS pixels. |
|
|
@@ -305,7 +305,7 @@ native text selection or touch gestures.
|
|
|
305
305
|
| `start` | CapturePointerStart | — | |
|
|
306
306
|
| `velocityX` | number | — | Scroll velocity in viewport CSS pixels/ms. |
|
|
307
307
|
| `velocityY` | number | — | |
|
|
308
|
-
| `cancelReason?` |
|
|
308
|
+
| `cancelReason?` | 'pointer-cancel' \| 'lost-capture' \| 'disabled' \| 'disconnected' \| 'blur' \| 'interrupted' | — | |
|
|
309
309
|
|
|
310
310
|
## Web component
|
|
311
311
|
|
|
@@ -163,7 +163,11 @@ function ParentChild() {
|
|
|
163
163
|
|
|
164
164
|
## Accessibility
|
|
165
165
|
|
|
166
|
-
The wrapper sets `role="checkbox"
|
|
166
|
+
The wrapper sets `role="checkbox"`, and the element keeps `aria-checked`
|
|
167
|
+
(`"true"` / `"false"` / `"mixed"`) in sync. Its light-DOM label supplies the
|
|
168
|
+
accessible name and its hint supplies the accessible description through
|
|
169
|
+
`ElementInternals`; no generated IDs are needed. For a label-less checkbox, pass
|
|
170
|
+
`aria-label`.
|
|
167
171
|
|
|
168
172
|
Space toggles the checkbox. Follows the [WAI-ARIA checkbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/).
|
|
169
173
|
|
|
@@ -174,7 +178,7 @@ Space toggles the checkbox. Follows the [WAI-ARIA checkbox pattern](https://www.
|
|
|
174
178
|
| `checked?` | CheckboxValue | — | Controlled checked state. When provided the checkbox is controlled — it renders exactly this and never self-applies; `onStateChange` is a *request* the consumer accepts by updating this prop. Use `defaultChecked` for an uncontrolled checkbox. `'indeterminate'` shows the minus glyph and takes visual precedence; clicking it requests `true`. |
|
|
175
179
|
| `defaultChecked?` | CheckboxValue | false | Initial checked state for an uncontrolled checkbox. Read once; later changes are ignored and the element updates its state after interaction. |
|
|
176
180
|
| `disabled?` | boolean | — | Disable the checkbox (no interaction, dropped from the tab order). |
|
|
177
|
-
| `hint?` | ReactNode | — | Secondary text rendered under the label
|
|
181
|
+
| `hint?` | ReactNode | — | Secondary text rendered under the label and exposed as the checkbox's accessible description. Not part of the accessible name. |
|
|
178
182
|
| `label?` | string | — | Visible label — the *value* of the checkbox (clicked along with the box). Convenience for the common single-string case; for richer content (markup, a link, an info icon) use `children`. When both are supplied, `label` renders first. Required unless `children` or `aria-label` is provided (a `role="checkbox"` takes its name from the author, not the markup). |
|
|
179
183
|
| `name?` | string | — | Form field name. Inside a `<form>` the checkbox submits under this name, contributing `value` when checked — like a native checkbox. |
|
|
180
184
|
| `onChange?` | (event) => void | — | Fired *after* the checked state changes — a native `change` event (the post-apply counterpart to `onStateChange`). Not cancelable. For a controlled checkbox this fires once you've updated `checked`. |
|
|
@@ -183,14 +187,15 @@ Space toggles the checkbox. Follows the [WAI-ARIA checkbox pattern](https://www.
|
|
|
183
187
|
| `round?` | boolean \| number \| string | — | Round the checkbox mark to a circle (`border-radius: 999px` on the box). Pass a `number` (px) or a CSS length string for a rounded-square mark instead. |
|
|
184
188
|
| `size?` | 'small' \| 'medium' \| 'large' | 'medium' | Size variant. small=14px, medium=16px, large=18px box. |
|
|
185
189
|
| `tone?` | 'brand' \| 'neutral' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | 'neutral' | Color of the **mark**. In the default `all` scope this colors the checked-box fill and unselected box border. A named tone or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`) for a one-off custom tone. Named tones track light/dark mode automatically; a custom color keeps its hue + chroma and pins lightness to the fill curve. Set `toneScope="selected"` to tone only the checked mark and leave the empty box neutral. The label + hint stay neutral — recolor them in plain CSS via the theme-aware `--text-N-{tone}` tokens. |
|
|
186
|
-
| `toneScope?` |
|
|
190
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply `tone` to every state, or only while checked so the empty box stays neutral. `selected` is useful when a tinted resting border would read as a validation state. |
|
|
187
191
|
| `value?` | string | "on" | Value submitted with the form when checked — like a native checkbox. |
|
|
188
192
|
|
|
189
193
|
## Web Component
|
|
190
194
|
|
|
191
195
|
Use the web component directly when you are not using React or Preact and a native control does not fit.
|
|
192
196
|
|
|
193
|
-
The focusable host carries the state. Label and hint are light-DOM children
|
|
197
|
+
The focusable host carries the state. Label and hint are light-DOM children that
|
|
198
|
+
the element exposes as its accessible name and description.
|
|
194
199
|
|
|
195
200
|
```html
|
|
196
201
|
<a-checkbox role="checkbox" tabindex="0" name="updates" default-state="checked">
|
|
@@ -23,6 +23,12 @@ the first suggestion (then ↑/↓ move through them), and
|
|
|
23
23
|
Enter on a highlighted row picks it. Esc or an outside click
|
|
24
24
|
closes the list; clicking the field to place the caret keeps it open.
|
|
25
25
|
|
|
26
|
+
The focused field is associated directly with the suggestion popup and its
|
|
27
|
+
active option through ARIA element reflection. These relationships do not
|
|
28
|
+
require generated popup or option IDs, so separate application roots cannot
|
|
29
|
+
collide. Explicit ARIA relationships authored on a raw Anta Input take
|
|
30
|
+
precedence.
|
|
31
|
+
|
|
26
32
|
## Filtering
|
|
27
33
|
|
|
28
34
|
`filter` decides how suggestions match the text:
|
|
@@ -212,9 +212,15 @@ the standard constraint-validation pipeline.
|
|
|
212
212
|
|
|
213
213
|
## Accessibility
|
|
214
214
|
|
|
215
|
+
The focused Input field is associated directly with its Calendar dialog through
|
|
216
|
+
ARIA element reflection. The relationship does not require a generated popup ID,
|
|
217
|
+
so separate application roots can render InputDate instances without ID
|
|
218
|
+
collisions. An explicitly authored relationship on a raw Anta Input takes
|
|
219
|
+
precedence.
|
|
220
|
+
|
|
215
221
|
The calendar is a labelled **group** of day buttons, a flat grid rather than a
|
|
216
|
-
nested `grid`/`row`/`gridcell` tree. The
|
|
217
|
-
|
|
222
|
+
nested `grid`/`row`/`gridcell` tree. The visible month names the group directly.
|
|
223
|
+
Each day is a `<button>` whose `aria-label` is its full date
|
|
218
224
|
including weekday ("Sunday, June 28, 2026"), with `aria-pressed` on the selected day
|
|
219
225
|
and `aria-current="date"` on today. The decorative weekday headers are `aria-hidden`,
|
|
220
226
|
since each day already names its weekday. A roving `tabindex` keeps a single tab
|
package/docs/components/input.md
CHANGED
|
@@ -9,9 +9,9 @@ for styling through `::part(input)`.
|
|
|
9
9
|
## Size
|
|
10
10
|
|
|
11
11
|
```tsx
|
|
12
|
-
<Input size="small" label="Small" placeholder="24px tall" />
|
|
13
|
-
<Input size="medium" label="Medium" placeholder="28px tall" /> {/* default */}
|
|
14
|
-
<Input size="large" label="Large" placeholder="32px tall" />
|
|
12
|
+
<Input size="small" label="Small" placeholder="24px tall" autoComplete="off" />
|
|
13
|
+
<Input size="medium" label="Medium" placeholder="28px tall" autoComplete="off" /> {/* default */}
|
|
14
|
+
<Input size="large" label="Large" placeholder="32px tall" autoComplete="off" />
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Three sizes (`medium` is the default). The field **height**, the **type scale**
|
|
@@ -27,8 +27,8 @@ Anta's text scale, so a field lines up with same-size `Text` / `Button`.
|
|
|
27
27
|
## Label and hint
|
|
28
28
|
|
|
29
29
|
```tsx
|
|
30
|
-
<Input label="Display name" defaultValue="Ada Lovelace" />
|
|
31
|
-
<Input label="API key" hint="Find this in Settings → Developers." placeholder="sk-…" />
|
|
30
|
+
<Input label="Display name" defaultValue="Ada Lovelace" autoComplete="name" />
|
|
31
|
+
<Input label="API key" hint="Find this in Settings → Developers." placeholder="sk-…" autoComplete="off" />
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
`label` sits above the field; `hint` is neutral helper text below it
|
|
@@ -40,12 +40,18 @@ mirrors the label text into `aria-label`, since a native `<label for>` can't
|
|
|
40
40
|
cross the shadow boundary. The `hint` (or error) is mirrored the same way into
|
|
41
41
|
`aria-description`, so a screen reader announces the message too.
|
|
42
42
|
|
|
43
|
+
Standard `role` and `aria-*` attributes on `<Input>` or raw `<a-input>` are
|
|
44
|
+
applied to the native input, textarea, or button inside its shadow root. This
|
|
45
|
+
keeps the focused native control as the single accessible control. If you query
|
|
46
|
+
the DOM directly, read those semantics from `a-input.control` rather than from
|
|
47
|
+
the custom-element host.
|
|
48
|
+
|
|
43
49
|
## Tooltip
|
|
44
50
|
|
|
45
51
|
```tsx
|
|
46
52
|
{/* Drop a <Tooltip> in as a child — it attaches to the field and shows on hover,
|
|
47
53
|
exactly like a tooltip on any other element. */}
|
|
48
|
-
<Input label="API key" placeholder="sk-…">
|
|
54
|
+
<Input label="API key" placeholder="sk-…" autoComplete="off">
|
|
49
55
|
<Tooltip>Find this in Settings → Developers.</Tooltip>
|
|
50
56
|
</Input>
|
|
51
57
|
```
|
|
@@ -60,12 +66,12 @@ content.)
|
|
|
60
66
|
|
|
61
67
|
```tsx
|
|
62
68
|
{/* No status = neutral helper text */}
|
|
63
|
-
<Input label="Display name" defaultValue="Ada Lovelace" hint="This is your public name." />
|
|
64
|
-
<Input label="Workspace" defaultValue="acme" status="info" hint="Lowercase letters and dashes only." />
|
|
65
|
-
<Input label="Username" defaultValue="ada" status="success" hint="Username is available." />
|
|
66
|
-
<Input label="Password" type="password" defaultValue="hunter2" status="warning" hint="Weak — add more characters." />
|
|
67
|
-
<Input label="Email" defaultValue="not-an-email" status="critical" hint="Enter a valid email address." />
|
|
68
|
-
<Input label="Plan" defaultValue="Pro" status="brand" hint="You're on the Pro plan." />
|
|
69
|
+
<Input label="Display name" defaultValue="Ada Lovelace" hint="This is your public name." autoComplete="name" />
|
|
70
|
+
<Input label="Workspace" defaultValue="acme" status="info" hint="Lowercase letters and dashes only." autoComplete="off" />
|
|
71
|
+
<Input label="Username" defaultValue="ada" status="success" hint="Username is available." autoComplete="username" />
|
|
72
|
+
<Input label="Password" type="password" defaultValue="hunter2" status="warning" hint="Weak — add more characters." autoComplete="new-password" />
|
|
73
|
+
<Input label="Email" type="email" defaultValue="not-an-email" status="critical" hint="Enter a valid email address." autoComplete="email" />
|
|
74
|
+
<Input label="Plan" defaultValue="Pro" status="brand" hint="You're on the Pro plan." autoComplete="off" />
|
|
69
75
|
```
|
|
70
76
|
|
|
71
77
|
`status` tints the border and the `hint`, and prefixes a glyph — `critical`,
|
|
@@ -92,15 +98,16 @@ with `statusIcon={false}`.
|
|
|
92
98
|
```tsx
|
|
93
99
|
{/* clearable — the clear button shows once there's a value */}
|
|
94
100
|
{/* dimActions — adornments rest quiet, brighten when the field is hovered/focused */}
|
|
95
|
-
<Input label="Search" placeholder="Search…" clearable dimActions defaultValue="design tokens" />
|
|
101
|
+
<Input label="Search" placeholder="Search…" clearable dimActions defaultValue="design tokens" autoComplete="off" />
|
|
96
102
|
|
|
97
103
|
{/* type="search" is a shorthand for the leading search icon + clearable below */}
|
|
98
|
-
<Input label="Search" type="search" placeholder="Search…" />
|
|
104
|
+
<Input label="Search" type="search" placeholder="Search…" autoComplete="off" />
|
|
99
105
|
|
|
100
106
|
{/* leading / trailing take any node — see the live playground above */}
|
|
101
|
-
<Input label="Search" leading={<Icon shape="search" />} clearable dimActions />
|
|
107
|
+
<Input label="Search" leading={<Icon shape="search" />} clearable dimActions autoComplete="off" />
|
|
102
108
|
<Input
|
|
103
109
|
label="Date"
|
|
110
|
+
autoComplete="off"
|
|
104
111
|
leading={<Icon shape="calendar" />}
|
|
105
112
|
trailing={<Button priority="quaternary" size="small" icon="eye" aria-label="Pick" />}
|
|
106
113
|
dimActions
|
|
@@ -149,6 +156,7 @@ const [reveal, setReveal] = useState(false)
|
|
|
149
156
|
|
|
150
157
|
<Input
|
|
151
158
|
label="Password"
|
|
159
|
+
autoComplete="current-password"
|
|
152
160
|
type={reveal ? 'text' : 'password'}
|
|
153
161
|
defaultValue="hunter2"
|
|
154
162
|
dimActions
|
|
@@ -176,10 +184,10 @@ Firefox. So Anta keeps the native field.
|
|
|
176
184
|
|
|
177
185
|
```tsx
|
|
178
186
|
{/* Grows with content, capped at 6 rows, then scrolls */}
|
|
179
|
-
<Input multiline maxRows={6} label="Bio (autogrows)" placeholder="Tell us…" />
|
|
187
|
+
<Input multiline maxRows={6} label="Bio (autogrows)" placeholder="Tell us…" autoComplete="off" />
|
|
180
188
|
|
|
181
189
|
{/* Constant height of 3 rows */}
|
|
182
|
-
<Input multiline rows={3} label="Notes (fixed 3 rows)" placeholder="…" />
|
|
190
|
+
<Input multiline rows={3} label="Notes (fixed 3 rows)" placeholder="…" autoComplete="off" />
|
|
183
191
|
```
|
|
184
192
|
|
|
185
193
|
`multiline` renders a `<textarea>` under the same API. With **no `rows`** it
|
|
@@ -195,11 +203,11 @@ browser.
|
|
|
195
203
|
|
|
196
204
|
```tsx
|
|
197
205
|
// Uncontrolled: the element updates its value after input.
|
|
198
|
-
<Input label="Name" defaultValue="Ada" onChange={(e) => log(e.target.value)} />
|
|
206
|
+
<Input label="Name" defaultValue="Ada" autoComplete="name" onChange={(e) => log(e.target.value)} />
|
|
199
207
|
|
|
200
208
|
// Controlled: application state supplies the value.
|
|
201
209
|
const [v, setV] = useState('')
|
|
202
|
-
<Input label="Name" value={v} onInput={(e) => setV(e.target.value)} />
|
|
210
|
+
<Input label="Name" value={v} autoComplete="name" onInput={(e) => setV(e.target.value)} />
|
|
203
211
|
```
|
|
204
212
|
|
|
205
213
|
Like a native input: pass `defaultValue` for **uncontrolled**, or `value` +
|
|
@@ -240,7 +248,7 @@ value-based, also has only `onValueChange`.)
|
|
|
240
248
|
|
|
241
249
|
```tsx
|
|
242
250
|
<form onSubmit={handle}>
|
|
243
|
-
<Input name="email" label="Email" type="email" required clearable />
|
|
251
|
+
<Input name="email" label="Email" type="email" autoComplete="email" required clearable />
|
|
244
252
|
<Button tone="brand" type="submit" label="Sign up" />
|
|
245
253
|
<Button priority="tertiary" type="reset" label="Reset" />
|
|
246
254
|
</form>
|
|
@@ -254,12 +262,12 @@ restores the field to its `defaultValue` via `formResetCallback`.
|
|
|
254
262
|
## Types and validation
|
|
255
263
|
|
|
256
264
|
```tsx
|
|
257
|
-
<Input type="text" label="Text" />
|
|
258
|
-
<Input type="email" label="Email" />
|
|
259
|
-
<Input type="password" label="Password" />
|
|
260
|
-
<Input type="tel" label="Tel" />
|
|
261
|
-
<Input type="url" label="URL" />
|
|
262
|
-
<Input type="number" label="Number" min={0} max={100} />
|
|
265
|
+
<Input type="text" label="Text" autoComplete="off" />
|
|
266
|
+
<Input type="email" label="Email" autoComplete="email" />
|
|
267
|
+
<Input type="password" label="Password" autoComplete="current-password" />
|
|
268
|
+
<Input type="tel" label="Tel" autoComplete="tel" />
|
|
269
|
+
<Input type="url" label="URL" autoComplete="url" />
|
|
270
|
+
<Input type="number" label="Number" autoComplete="off" min={0} max={100} />
|
|
263
271
|
```
|
|
264
272
|
|
|
265
273
|
`type` accepts `text` (default), `email`, `password`, `tel`, `url`, and
|
|
@@ -267,6 +275,12 @@ restores the field to its `defaultValue` via `formResetCallback`.
|
|
|
267
275
|
constraint validation. (`search` is omitted on purpose — see above.)
|
|
268
276
|
`number` also takes `min` / `max` / `step`.
|
|
269
277
|
|
|
278
|
+
Set `autoComplete` to describe the field's purpose. `email`, `tel`, and `url`
|
|
279
|
+
derive their matching token from `type`. Other purposes need an explicit token,
|
|
280
|
+
such as `name`, `username`, `current-password`, `new-password`, or
|
|
281
|
+
`one-time-code`. Use `autoComplete="off"` for examples and application fields
|
|
282
|
+
that do not represent autofill data.
|
|
283
|
+
|
|
270
284
|
For a **controlled** numeric field — one whose `value` you hold in state — prefer
|
|
271
285
|
`type="text"` with `inputMode="decimal"` (or `"numeric"`) over `type="number"`. A
|
|
272
286
|
number input runs value sanitization, so a mid-typing `"1."` or `"1.0"` reports an
|
|
@@ -296,10 +310,10 @@ function onSubmit(e) {
|
|
|
296
310
|
}
|
|
297
311
|
|
|
298
312
|
<form noValidate onSubmit={onSubmit}>
|
|
299
|
-
<Input name="email" type="email" required hint={errors.email}
|
|
313
|
+
<Input name="email" type="email" autoComplete="email" required hint={errors.email}
|
|
300
314
|
status={errors.email ? 'critical' : undefined}
|
|
301
315
|
onInput={() => setErrors(p => ({ ...p, email: undefined }))} />
|
|
302
|
-
<Input name="age" type="number" min="18" max="120" hint={errors.age}
|
|
316
|
+
<Input name="age" type="number" autoComplete="off" min="18" max="120" hint={errors.age}
|
|
303
317
|
status={errors.age ? 'critical' : undefined}
|
|
304
318
|
onInput={() => setErrors(p => ({ ...p, age: undefined }))} />
|
|
305
319
|
<Button type="submit" label="Submit" />
|
|
@@ -345,7 +359,7 @@ Re-template the host to two columns and drop each part into one. The hint stays
|
|
|
345
359
|
under the field by landing in the same column.
|
|
346
360
|
|
|
347
361
|
```tsx
|
|
348
|
-
<Input className="label-side" label="Display name" hint="Shown on your profile" />
|
|
362
|
+
<Input className="label-side" label="Display name" hint="Shown on your profile" autoComplete="name" />
|
|
349
363
|
|
|
350
364
|
{/* .label-side is just for the demo — use your own selector */}
|
|
351
365
|
<style>{`
|
|
@@ -369,9 +383,9 @@ left-edge lines up. Each hint still tucks under its own field.
|
|
|
369
383
|
|
|
370
384
|
```tsx
|
|
371
385
|
<div className="aligned-form">
|
|
372
|
-
<Input label="Email" type="email" hint="We'll never share it." />
|
|
373
|
-
<Input label="Confirm password" type="password" />
|
|
374
|
-
<Input label="PIN" />
|
|
386
|
+
<Input label="Email" type="email" autoComplete="email" hint="We'll never share it." />
|
|
387
|
+
<Input label="Confirm password" type="password" autoComplete="new-password" />
|
|
388
|
+
<Input label="PIN" autoComplete="one-time-code" />
|
|
375
389
|
</div>
|
|
376
390
|
|
|
377
391
|
<style>{`
|
|
@@ -391,7 +405,7 @@ unit. Two columns (field, then hint); the label spans the top, and the hint
|
|
|
391
405
|
centers against the field.
|
|
392
406
|
|
|
393
407
|
```tsx
|
|
394
|
-
<Input className="hint-right" label="Username" hint="3–20 characters" placeholder="ada" />
|
|
408
|
+
<Input className="hint-right" label="Username" hint="3–20 characters" placeholder="ada" autoComplete="username" />
|
|
395
409
|
|
|
396
410
|
<style>{`
|
|
397
411
|
a-input.hint-right {
|
|
@@ -412,10 +426,10 @@ wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
|
412
426
|
|
|
413
427
|
```tsx
|
|
414
428
|
<div className="wrap-fields">
|
|
415
|
-
<Input label="First name" />
|
|
416
|
-
<Input label="Last name" />
|
|
417
|
-
<Input label="Email" type="email" />
|
|
418
|
-
<Input label="Phone" type="tel" />
|
|
429
|
+
<Input label="First name" autoComplete="given-name" />
|
|
430
|
+
<Input label="Last name" autoComplete="family-name" />
|
|
431
|
+
<Input label="Email" type="email" autoComplete="email" />
|
|
432
|
+
<Input label="Phone" type="tel" autoComplete="tel" />
|
|
419
433
|
</div>
|
|
420
434
|
|
|
421
435
|
<style>{`
|
|
@@ -430,6 +444,7 @@ wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
|
430
444
|
|------|------|---------|-------------|
|
|
431
445
|
| `autoComplete?` | 'off' \| 'on' \| 'name' \| 'username' \| 'email' \| 'current-password' \| 'new-password' \| 'one-time-code' \| 'tel' \| 'url' \| (string & {}) | — | Native autocomplete token. Overrides the value derived from `type` (`email` / `tel` / `url`) — set it for the cases `type` can't express, e.g. `username`, `current-password`, `new-password`, `one-time-code`, or `off`. |
|
|
432
446
|
| `autoFocus?` | boolean | — | Focus this field when its containing `Dialog` opens. |
|
|
447
|
+
| `button?` | boolean | — | Render the field surface with a native button as its focus target. This is available for Input-styled popup triggers; the value becomes the button text and the placeholder is shown while it is empty. |
|
|
433
448
|
| `children?` | ReactNode | — | Extra content rendered directly under the field, above the hint/error (it pushes the message down). A no-box child like an Anta `<Tooltip>` takes no space and anchors to the field — consistent with how tooltips attach to any other element. Use the named `leading` / `trailing` props for in-field content. |
|
|
434
449
|
| `clearable?` | boolean | — | Show a clear button as the first trailing item once the field has a value. |
|
|
435
450
|
| `defaultValue?` | string | — | Initial value for the uncontrolled case. |
|
|
@@ -457,7 +472,7 @@ wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
|
457
472
|
| `placeholder?` | string | — | Placeholder shown when empty. |
|
|
458
473
|
| `readOnly?` | boolean | — | Make the field read-only. |
|
|
459
474
|
| `required?` | boolean | — | Mark the field required (drives native validity). |
|
|
460
|
-
| `role?` | string | — | ARIA `role` for the field — e.g. `combobox` when the input drives a suggestion `listbox` (see `InputAutocomplete`). Left unset by default. |
|
|
475
|
+
| `role?` | string | — | ARIA `role` for the field — e.g. `combobox` when the input drives a suggestion `listbox` (see `InputAutocomplete`). The custom element delegates it, together with standard `aria-*` props, to the focused native shadow control. Left unset by default. |
|
|
461
476
|
| `round?` | boolean \| number \| string | — | Fully-round the field (`border-radius: 999px`). Pass a `number` (px) or a CSS length string for a custom radius. The `clearable` × button always rounds to a circle to match (it isn't sized by a custom field value). |
|
|
462
477
|
| `rows?` | number | — | Fixed visible row count — a constant-height `<textarea>` (implies `multiline`). |
|
|
463
478
|
| `size?` | 'small' \| 'medium' \| 'large' | medium | Size variant. small=24px, medium=28px, large=32px tall; the type scale and icon track the size (small 13/16 + 14px icon · medium 15/20 + 16px · large 17/22 + 18px). |
|
|
@@ -478,7 +493,7 @@ Use the web component directly when you are not using React or Preact and a nati
|
|
|
478
493
|
Slots hold the label, hint, and controls around the native field.
|
|
479
494
|
|
|
480
495
|
```html
|
|
481
|
-
<a-input name="email" placeholder="you@example.com">
|
|
496
|
+
<a-input name="email" type="email" autocomplete="email" placeholder="you@example.com">
|
|
482
497
|
<span slot="label">Email</span>
|
|
483
498
|
<span slot="hint">We only use it for account notices.</span>
|
|
484
499
|
</a-input>
|
|
@@ -524,7 +539,7 @@ Reach for the props first: **`status`** sets a validation tone (border + message
|
|
|
524
539
|
dimensions. The focus ring is the global [`--focus-ring`](../colors.md#focus-ring).
|
|
525
540
|
|
|
526
541
|
```tsx
|
|
527
|
-
<Input tone="#e0457b" label="Custom accent" />
|
|
542
|
+
<Input tone="#e0457b" label="Custom accent" autoComplete="off" />
|
|
528
543
|
```
|
|
529
544
|
|
|
530
545
|
For everything else, `<a-input>` is shadow-DOM — style its **parts** with plain
|
|
@@ -563,5 +578,49 @@ a-input.fancy::part(field) {
|
|
|
563
578
|
padding-inline: 20px; /* roomier */
|
|
564
579
|
}
|
|
565
580
|
a-input.fancy::part(input) { color: light-dark(#ffffff, #1a1a1a); }
|
|
581
|
+
a-input.fancy::part(input)::placeholder {
|
|
582
|
+
color: light-dark(#b8b8b8, #666666);
|
|
583
|
+
opacity: 1;
|
|
584
|
+
}
|
|
566
585
|
a-input.fancy:focus-within::part(field) { background: light-dark(#161616, #ffffff); }
|
|
567
586
|
```
|
|
587
|
+
|
|
588
|
+
### Placeholder contrast
|
|
589
|
+
|
|
590
|
+
If the label, marking, context, or hint leaves the field's purpose unclear,
|
|
591
|
+
a stronger placeholder can help. Keep an accessible name and put essential
|
|
592
|
+
instructions in a persistent label or hint.
|
|
593
|
+
|
|
594
|
+
Antune uses `--text-4` for placeholders. These ratios compare the default neutral
|
|
595
|
+
Input backgrounds with the example's literal color:
|
|
596
|
+
|
|
597
|
+
| Style | Placeholder | Background | Contrast |
|
|
598
|
+
| --- | --- | --- | --- |
|
|
599
|
+
| Antune light theme | `#7a737c` | `#ffffff` | 4.59:1 |
|
|
600
|
+
| Antune dark theme | `#7c737c` | `#000000` | 4.60:1 |
|
|
601
|
+
| Example | `#767676` | `#ffffff` | 4.54:1 |
|
|
602
|
+
|
|
603
|
+
`#767676` is the lightest opaque 8-bit neutral gray that passes 4.5:1 on white.
|
|
604
|
+
W3C recommends [sufficient placeholder contrast](https://www.w3.org/WAI/tutorials/forms/instructions/#styling).
|
|
605
|
+
Redundant placeholders remain debated in the
|
|
606
|
+
[meeting discussion](https://www.w3.org/2025/04/16-matf-minutes.html) and
|
|
607
|
+
[open W3C issue](https://github.com/w3c/wcag/issues/4343); there is no agreed exemption.
|
|
608
|
+
|
|
609
|
+
This demo uses `#767676` on white in every state and theme.
|
|
610
|
+
Replace `.placeholder-contrast` with your own class.
|
|
611
|
+
|
|
612
|
+
```tsx
|
|
613
|
+
<Input className="placeholder-contrast" label="Email" type="email" autoComplete="email" placeholder="you@example.com" />
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
```css
|
|
617
|
+
a-input.placeholder-contrast::part(field) { background: #ffffff; }
|
|
618
|
+
a-input.placeholder-contrast::part(input) { color: #161616; }
|
|
619
|
+
a-input.placeholder-contrast::part(input)::placeholder {
|
|
620
|
+
color: #767676;
|
|
621
|
+
opacity: 1;
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
Check contrast separately if you use a different background.
|
|
626
|
+
Native inputs and textareas use `::placeholder` without `::part(input)`.
|
package/docs/components/menu.md
CHANGED
|
@@ -415,7 +415,7 @@ navigating links.
|
|
|
415
415
|
| `selectionIndicator?` | 'checkbox' \| 'radio' \| 'check' | — | Turn the row into a checkable item, driven by `selected` (the row stays the control and carries `aria-checked`): - `'checkbox'` → `role="menuitemcheckbox"`, a leading passive `<a-checkbox>` (before `icon`); the tint is dropped (the box carries state). - `'radio'` → `role="menuitemradio"`, a leading passive `<a-radio>`; tint dropped. - `'check'` → `role="menuitemradio"`, a trailing check glyph on the selected row *and* the background tint (the canonical single-select look). Omit for a plain row (the default). |
|
|
416
416
|
| `submenu?` | boolean | — | Marks this item as a submenu parent: adds the trailing chevron and `aria-haspopup="menu"`. Nest the flyout as a `<Menu>` child. |
|
|
417
417
|
| `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | neutral | Semantic tone — colors the label, icon, and hover/selected tint (and the `checkbox`/`radio` indicator, which adopts it). A named tone, or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`) for a one-off custom tone whose hue + chroma are kept while the lightness is pinned to match the brand text. `critical` is the destructive action; `neutral` (the default) is the standard gray. |
|
|
418
|
-
| `toneScope?` |
|
|
418
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply `tone` to every row state, or only while the row is selected. In `selected` scope, an unselected row and its checkbox/radio indicator stay neutral. |
|
|
419
419
|
| `value?` | string \| number | — | An opaque value identifying this item, handed back in `onSelect`'s detail so a shared handler can tell which row was chosen without a per-item closure. |
|
|
420
420
|
|
|
421
421
|
## Keyboard
|
|
@@ -461,7 +461,7 @@ or do nothing to reject. (Submenus are always uncontrolled, regardless of `open`
|
|
|
461
461
|
| `inset?` | number \| string | 4 | Inner inset for the scroll body and named header/footer content. A number is pixels; a CSS length string is used as written. |
|
|
462
462
|
| `nohover?` | boolean | — | Submenu-only (a `<Menu>` nested inside a `MenuItem`); ignored on a root menu. Submenus open on hover by default (with intent timing) as well as on click — set `nohover` to make this submenu click-only. Hover-intent is mouse-only regardless: on touch (and pen) a submenu always opens on tap and stays open until dismissed. |
|
|
463
463
|
| `offset?` | number | 4 | Gap in pixels between the trigger and the menu. |
|
|
464
|
-
| `onactivedescendant?` | (e) => void | — | Combobox-mode cursor report (raw element event). Fires when the active option changes as arrow keys move the cursor while focus stays in a `[data-menu-search]` filter field; `detail.id` is
|
|
464
|
+
| `onactivedescendant?` | (e) => void | — | Combobox-mode cursor report (raw element event). Fires when the active option changes as arrow keys move the cursor while focus stays in a `[data-menu-search]` filter field; `detail.id` is an authored option `id`, or `null`. Built-in Anta Inputs receive the active option through a direct ARIA element relationship; this remains available to custom fields and observers. Passed straight through to the element. |
|
|
465
465
|
| `onStateChange?` | (event, detail) => void | — | Fired before the open state changes — on open, and on every dismiss (Esc, outside-click, scroll, selecting an item). `event` is the cancelable `statechange`; `detail.next`/`detail.prev` are the requested/previous open state (booleans). It's the declarative way to observe a menu, and the handler you pair with `open` to drive a controlled menu (apply `detail.next` to `open`). Uncontrolled, `event.preventDefault()` vetoes the transition (e.g. keep the menu open). |
|
|
466
466
|
| `open?` | boolean | — | Controlled open state. Omit for the default **uncontrolled** menu (it opens/closes itself via its triggers). Pass a boolean to **control** it: the menu's visibility follows `open`, and user dismiss (Esc, outside-click, select) fires `onStateChange` *without* self-closing — you update `open` in response. Submenus are always uncontrolled regardless of this. See STATEFUL-COMPONENTS.md. |
|
|
467
467
|
| `placement?` | 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'bottom' \| 'top' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' \| 'right' \| 'left' | bottom-start | Preferred placement relative to the trigger. `bottom` / `top` place the menu below / above; `right` / `left` place it beside (like a submenu flyout). The cross-axis suffix (`-start` / `-end`) aligns the near / far edges, and no suffix centers on the trigger. The menu flips to the opposite side when the preferred one lacks room, and clamps to the viewport. |
|
|
@@ -494,7 +494,7 @@ or do nothing to reject. (Submenus are always uncontrolled, regardless of `open`
|
|
|
494
494
|
| `submenu?` | boolean | — | Marks this item as a submenu parent: adds the trailing chevron and `aria-haspopup="menu"`. Nest the flyout as a `<Menu>` child. |
|
|
495
495
|
| `target?` | string | — | Anchor target, e.g. `'_blank'`. |
|
|
496
496
|
| `tone?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' \| (string & {}) | neutral | Semantic tone — colors the label, icon, and hover/selected tint (and the `checkbox`/`radio` indicator, which adopts it). A named tone, or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`) for a one-off custom tone whose hue + chroma are kept while the lightness is pinned to match the brand text. `critical` is the destructive action; `neutral` (the default) is the standard gray. |
|
|
497
|
-
| `toneScope?` |
|
|
497
|
+
| `toneScope?` | 'all' \| 'selected' | 'all' | Apply `tone` to every row state, or only while the row is selected. In `selected` scope, an unselected row and its checkbox/radio indicator stay neutral. |
|
|
498
498
|
| `value?` | string \| number | — | An opaque value identifying this item, handed back in `onSelect`'s detail so a shared handler can tell which row was chosen without a per-item closure. |
|
|
499
499
|
|
|
500
500
|
## Web Component
|