@antadesign/anta 0.3.33 → 0.3.35
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/LICENSE.md +14 -1
- package/README.md +9 -0
- package/dist/anta_helpers.d.ts +46 -30
- package/dist/anta_helpers.js +66 -25
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +2 -1353
- package/dist/components/Banner.d.ts +25 -40
- package/dist/components/Banner.js +15 -17
- package/dist/components/Breadcrumbs.d.ts +0 -1
- package/dist/components/Breadcrumbs.js +0 -1
- package/dist/components/Button.d.ts +2 -3
- package/dist/components/Button.js +1 -0
- package/dist/components/ButtonCopy.js +3 -2
- package/dist/components/Calendar.js +13 -13
- package/dist/components/Card.d.ts +9 -17
- package/dist/components/Card.js +50 -46
- package/dist/components/Dialog.d.ts +1 -0
- package/dist/components/Dialog.js +16 -10
- package/dist/components/Expander.d.ts +6 -21
- package/dist/components/Expander.js +24 -23
- package/dist/components/Icon.d.ts +8 -14
- package/dist/components/Input.d.ts +77 -96
- package/dist/components/Input.js +23 -27
- package/dist/components/InputAutocomplete.d.ts +29 -10
- package/dist/components/InputAutocomplete.js +25 -8
- package/dist/components/InputDate.d.ts +0 -1
- package/dist/components/InputDate.js +2 -3
- package/dist/components/InputTime.d.ts +10 -4
- package/dist/components/InputTime.js +20 -16
- package/dist/components/Loader.d.ts +2 -2
- package/dist/components/Menu.d.ts +5 -4
- package/dist/components/Menu.js +13 -8
- package/dist/components/MenuItem.js +1 -14
- package/dist/components/MenuItemCopy.js +2 -2
- package/dist/components/Panel.d.ts +3 -1
- package/dist/components/Panel.js +17 -11
- package/dist/components/Progress.d.ts +21 -23
- package/dist/components/Progress.js +13 -9
- package/dist/components/RadioGroup.js +6 -8
- package/dist/components/{select-parts.css → Select.css} +1 -1
- package/dist/components/Select.d.ts +53 -36
- package/dist/components/Select.js +53 -98
- package/dist/components/SelectFaceted.d.ts +7 -4
- package/dist/components/SelectFaceted.js +21 -10
- package/dist/components/Slider.d.ts +28 -11
- package/dist/components/Slider.js +20 -20
- package/dist/components/Steps.css +1 -1
- package/dist/components/Steps.d.ts +0 -1
- package/dist/components/Steps.js +1 -12
- package/dist/components/Tabs.d.ts +17 -20
- package/dist/components/Tabs.js +7 -9
- package/dist/components/Text.d.ts +55 -36
- package/dist/components/Text.js +35 -22
- package/dist/components/Title.d.ts +19 -27
- package/dist/components/Title.js +2 -1
- package/dist/components/Toaster.js +9 -2
- package/dist/components/Tooltip.d.ts +10 -15
- package/dist/components/copy-props.d.ts +14 -3
- package/dist/components/copy-props.js +14 -3
- package/dist/components/select-tree.d.ts +24 -0
- package/dist/components/select-tree.js +35 -0
- package/dist/element-base.d.ts +10 -0
- package/dist/element-base.js +15 -0
- package/dist/elements/a-avatar.css +1 -1
- package/dist/elements/a-avatar.js +2 -28
- package/dist/elements/a-banner.css +1 -1
- package/dist/elements/a-banner.d.ts +4 -1
- package/dist/elements/a-banner.js +22 -112
- package/dist/elements/a-breadcrumbs.d.ts +1 -0
- package/dist/elements/a-breadcrumbs.js +1 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +10 -7
- package/dist/elements/a-button.js +18 -1
- package/dist/elements/a-calendar.d.ts +14 -13
- package/dist/elements/a-calendar.js +29 -24
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-card.d.ts +0 -9
- package/dist/elements/a-card.js +0 -184
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-copy.css +1 -1
- package/dist/elements/a-copy.d.ts +1 -5
- package/dist/elements/a-copy.js +129 -108
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-dialog.d.ts +1 -1
- package/dist/elements/a-dialog.js +68 -194
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +4 -30
- package/dist/elements/a-expander.js +85 -344
- package/dist/elements/a-icon.d.ts +5 -23
- package/dist/elements/a-icon.js +1 -2
- package/dist/elements/a-input-date.d.ts +1 -0
- package/dist/elements/a-input-date.js +1 -0
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.d.ts +2 -1
- package/dist/elements/a-input-time.js +101 -168
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +10 -8
- package/dist/elements/a-input.js +155 -230
- package/dist/elements/a-loader.d.ts +5 -8
- package/dist/elements/a-loader.js +1 -2
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.d.ts +5 -3
- package/dist/elements/a-menu-item.js +5 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +5 -7
- package/dist/elements/a-menu.js +383 -299
- package/dist/elements/a-panel.css +1 -1
- package/dist/elements/a-panel.js +19 -37
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-progress.d.ts +0 -22
- package/dist/elements/a-progress.js +0 -100
- package/dist/elements/a-radio-group.d.ts +1 -1
- package/dist/elements/a-radio-group.js +6 -4
- package/dist/elements/a-select-faceted.d.ts +1 -0
- package/dist/elements/a-select-faceted.js +1 -0
- package/dist/elements/a-select.d.ts +1 -0
- package/dist/elements/a-select.js +1 -0
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-slider.d.ts +11 -3
- package/dist/elements/a-slider.js +244 -242
- package/dist/elements/a-steps.d.ts +1 -0
- package/dist/elements/a-steps.js +1 -0
- package/dist/elements/a-switch.css +1 -1
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tabpanel.d.ts +2 -2
- package/dist/elements/a-tabpanel.js +13 -3
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tabs.d.ts +1 -1
- package/dist/elements/a-tabs.js +6 -4
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-tag.d.ts +1 -0
- package/dist/elements/a-tag.js +1 -0
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.d.ts +6 -43
- package/dist/elements/a-text.js +110 -193
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-title.d.ts +1 -0
- package/dist/elements/a-title.js +1 -0
- package/dist/elements/a-toast.css +1 -1
- package/dist/elements/a-toast.d.ts +10 -45
- package/dist/elements/a-toast.js +80 -66
- package/dist/elements/a-toaster.css +1 -1
- package/dist/elements/a-toaster.js +9 -44
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +1 -1
- package/dist/elements/a-tooltip.js +142 -136
- package/dist/elements/copy-behavior.d.ts +1 -1
- package/dist/elements/copy-behavior.js +21 -21
- package/dist/elements/index.d.ts +9 -3
- package/dist/elements/index.js +6 -6
- package/dist/elements/input-focus-modality.d.ts +15 -0
- package/dist/elements/input-focus-modality.js +44 -0
- package/dist/elements/input-trailing-actions.d.ts +5 -0
- package/dist/elements/input-trailing-actions.js +38 -0
- package/dist/elements/shadow-aria.d.ts +2 -0
- package/dist/elements/shadow-aria.js +2 -1
- package/dist/elements/value-input.d.ts +3 -0
- package/dist/elements/value-input.js +12 -0
- package/dist/general_types.d.ts +103 -96
- package/dist/index.d.ts +1 -1
- package/dist/input-events.d.ts +4 -0
- package/dist/input-events.js +15 -0
- package/dist/jsx-runtime.d.ts +70 -23
- package/dist/jsx-runtime.js +26 -19
- package/dist/native-event-props.d.ts +2 -0
- package/dist/native-event-props.js +10 -0
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +10 -1
- package/dist/theme-antune.css +1 -1
- package/docs/accessibility.md +17 -3
- package/docs/changelog.md +384 -2
- package/docs/comparison.md +2 -2
- package/docs/components/avatar.md +5 -0
- package/docs/components/banner.md +117 -187
- package/docs/components/breadcrumbs.md +9 -6
- package/docs/components/button.md +22 -0
- package/docs/components/card.md +74 -28
- package/docs/components/checkbox.md +9 -10
- package/docs/components/dialog.md +83 -32
- package/docs/components/expander.md +198 -435
- package/docs/components/icon.md +11 -17
- package/docs/components/input-autocomplete.md +152 -52
- package/docs/components/input-date.md +175 -148
- package/docs/components/input-time.md +81 -38
- package/docs/components/input.md +343 -349
- package/docs/components/loader.md +2 -1
- package/docs/components/menu.md +35 -6
- package/docs/components/panel.md +18 -0
- package/docs/components/progress.md +83 -49
- package/docs/components/radio.md +39 -43
- package/docs/components/select-faceted.md +54 -7
- package/docs/components/select.md +390 -386
- package/docs/components/slider.md +136 -19
- package/docs/components/steps.md +6 -3
- package/docs/components/switch.md +8 -9
- package/docs/components/tabs.md +110 -104
- package/docs/components/text.md +110 -86
- package/docs/components/title.md +47 -33
- package/docs/components/toaster.md +242 -84
- package/docs/components/tooltip.md +204 -113
- package/docs/install-config.md +461 -96
- package/docs/packages/plot.md +228 -143
- package/docs/theming.md +29 -13
- package/package.json +43 -4
- package/theme-antithesis-license.md +66 -0
package/docs/components/input.md
CHANGED
|
@@ -1,45 +1,33 @@
|
|
|
1
1
|
# Input
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
focus, IME, autofill, and form submission all work, and the control is reachable
|
|
7
|
-
for styling through `::part(input)`.
|
|
3
|
+
Use Input for forms, search, passwords, and longer text. Add a label to explain
|
|
4
|
+
what to enter, a hint for guidance, and actions such as clearing or revealing a
|
|
5
|
+
password.
|
|
8
6
|
|
|
9
7
|
## Size
|
|
10
8
|
|
|
11
9
|
```tsx
|
|
12
|
-
<Input size="small" label="Small" placeholder="
|
|
13
|
-
<Input size="medium" label="Medium" placeholder="
|
|
14
|
-
<Input size="large" label="Large" placeholder="
|
|
10
|
+
<Input size="small" label="Small" placeholder="Enter text…" autoComplete="off" />
|
|
11
|
+
<Input size="medium" label="Medium" placeholder="Enter text…" autoComplete="off" /> {/* default */}
|
|
12
|
+
<Input size="large" label="Large" placeholder="Enter text…" autoComplete="off" />
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Anta's text scale, so a field lines up with same-size `Text` / `Button`.
|
|
20
|
-
|
|
21
|
-
| size | height | font / line | icon |
|
|
22
|
-
|---|---|---|---|
|
|
23
|
-
| `small` | 24px | 13 / 16 | 14px |
|
|
24
|
-
| `medium` | 28px | 15 / 20 | 16px |
|
|
25
|
-
| `large` | 32px | 17 / 22 | 18px |
|
|
15
|
+
Choose `small`, `medium`, or `large` to suit the surrounding interface.
|
|
16
|
+
Text, icons, and action buttons adjust together. The default is `medium`.
|
|
26
17
|
|
|
27
18
|
## Priority
|
|
28
19
|
|
|
29
|
-
`priority` changes the field surface without changing its size or behavior.
|
|
30
|
-
`primary` (the default) has a fill and border. `secondary` has a transparent
|
|
31
|
-
background and visible border. `tertiary` keeps both transparent at rest, then
|
|
32
|
-
uses secondary's border on hover or focus. Use it where the label or surrounding
|
|
33
|
-
content makes the field easy to find. All three show the same focus ring.
|
|
34
|
-
On an enabled field, a non-neutral `status` keeps its tinted fill and border
|
|
35
|
-
visible at rest.
|
|
36
|
-
|
|
37
20
|
```tsx
|
|
38
21
|
<Input label="Primary" placeholder="Filled field" autoComplete="off" />
|
|
39
22
|
<Input priority="secondary" label="Secondary" placeholder="Outlined field" autoComplete="off" />
|
|
40
23
|
<Input priority="tertiary" label="Tertiary" placeholder="Field on hover or focus" autoComplete="off" />
|
|
41
24
|
```
|
|
42
25
|
|
|
26
|
+
Use `priority` to choose how much the field stands out. `primary` has a filled
|
|
27
|
+
background, `secondary` has an outline, and `tertiary` stays subtle until someone
|
|
28
|
+
interacts with it. Use tertiary where the label or context makes the field easy
|
|
29
|
+
to find. Status feedback and focus remain visible with every priority.
|
|
30
|
+
|
|
43
31
|
## Label and hint
|
|
44
32
|
|
|
45
33
|
```tsx
|
|
@@ -47,36 +35,23 @@ visible at rest.
|
|
|
47
35
|
<Input label="API key" hint="Find this in Settings → Developers." placeholder="sk-…" autoComplete="off" />
|
|
48
36
|
```
|
|
49
37
|
|
|
50
|
-
`label`
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
`label` names the field and appears above it. `hint` provides persistent help
|
|
39
|
+
below it. Both accept text or JSX, including links and emphasis. Keep essential
|
|
40
|
+
instructions here so they remain available while someone types.
|
|
53
41
|
|
|
54
|
-
The label
|
|
55
|
-
|
|
56
|
-
cross the shadow boundary. The `hint` (or error) is mirrored the same way into
|
|
57
|
-
`aria-description`, so a screen reader announces the message too.
|
|
58
|
-
|
|
59
|
-
Standard `role` and `aria-*` attributes on `<Input>` or raw `<a-input>` are
|
|
60
|
-
applied to the native input, textarea, or button inside its shadow root. This
|
|
61
|
-
keeps the focused native control as the single accessible control. If you query
|
|
62
|
-
the DOM directly, read those semantics from `a-input.control` rather than from
|
|
63
|
-
the custom-element host.
|
|
42
|
+
The label also names the field for screen readers, and the hint provides its
|
|
43
|
+
description.
|
|
64
44
|
|
|
65
45
|
## Tooltip
|
|
66
46
|
|
|
67
47
|
```tsx
|
|
68
|
-
{/* Drop a <Tooltip> in as a child — it attaches to the field and shows on hover,
|
|
69
|
-
exactly like a tooltip on any other element. */}
|
|
70
48
|
<Input label="API key" placeholder="sk-…" autoComplete="off">
|
|
71
49
|
<Tooltip>Find this in Settings → Developers.</Tooltip>
|
|
72
50
|
</Input>
|
|
73
51
|
```
|
|
74
52
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
tooltips attach to a `<Button>` or any other element. (Children with no `slot`
|
|
78
|
-
are projected into a default slot; use `leading` / `trailing` for *in-field*
|
|
79
|
-
content.)
|
|
53
|
+
Place a `Tooltip` inside `Input` to anchor it to the field. It appears on hover
|
|
54
|
+
or keyboard focus. Use `leading` and `trailing` for content inside the field itself.
|
|
80
55
|
|
|
81
56
|
## Status
|
|
82
57
|
|
|
@@ -90,84 +65,74 @@ content.)
|
|
|
90
65
|
<Input label="Plan" defaultValue="Pro" status="brand" hint="You're on the Pro plan." autoComplete="off" />
|
|
91
66
|
```
|
|
92
67
|
|
|
93
|
-
`status`
|
|
94
|
-
`warning`, `success`, `info`, or `brand
|
|
95
|
-
|
|
96
|
-
recolors it.
|
|
97
|
-
|
|
98
|
-
It reuses the tone palette but isn't `tone`: **`status` is a validation *state*** (it
|
|
99
|
-
also carries the glyph and, for `critical`, validity), whereas `tone` — elsewhere in
|
|
100
|
-
Anta — is decorative color. On `Input` the named tones live on `status`; `tone` is
|
|
101
|
-
reserved for a one-off custom border color.
|
|
68
|
+
`status` colors the field and hint and adds a status icon. Choose `critical`,
|
|
69
|
+
`warning`, `success`, `info`, or `brand`; each adapts to the active theme.
|
|
70
|
+
Put the message in `hint`.
|
|
102
71
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
72
|
+
Use `critical` for an error that must be fixed before submitting the form.
|
|
73
|
+
Other statuses provide feedback without marking the field invalid. Required
|
|
74
|
+
fields and email fields still need valid values.
|
|
106
75
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
`circle-small-solid`). Override it with **`statusIcon`** (any shape), or drop it
|
|
110
|
-
with `statusIcon={false}`.
|
|
76
|
+
Use `statusIcon` to replace the default icon, or `statusIcon={false}` to hide it.
|
|
77
|
+
For a custom border color without status feedback, use `tone`.
|
|
111
78
|
|
|
112
79
|
## Leading, trailing, and clear
|
|
113
80
|
|
|
114
81
|
```tsx
|
|
115
|
-
{
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
82
|
+
import { useState } from 'preact/hooks'
|
|
83
|
+
import { Input, Icon, Button } from '@antadesign/anta'
|
|
84
|
+
|
|
85
|
+
function SearchActions() {
|
|
86
|
+
const [caseSensitive, setCaseSensitive] = useState(false)
|
|
87
|
+
const [regex, setRegex] = useState(false)
|
|
88
|
+
return (
|
|
89
|
+
<>
|
|
90
|
+
<Button priority="tertiary" icon="case-sensitive"
|
|
91
|
+
aria-label="Case sensitive" title="Case sensitive"
|
|
92
|
+
selected={caseSensitive} aria-pressed={caseSensitive}
|
|
93
|
+
onClick={() => setCaseSensitive(value => !value)} />
|
|
94
|
+
<Button priority="tertiary" icon="regex"
|
|
95
|
+
aria-label="Regular expression" title="Regular expression"
|
|
96
|
+
selected={regex} aria-pressed={regex}
|
|
97
|
+
onClick={() => setRegex(value => !value)} />
|
|
98
|
+
</>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
121
101
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
102
|
+
function Demo() {
|
|
103
|
+
return (
|
|
104
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', width: '100%', maxWidth: '320px' }}>
|
|
105
|
+
<Input label="Leading icon" placeholder="Search…" leading={<Icon shape="search" />} autoComplete="off" />
|
|
106
|
+
<Input label="Trailing actions" placeholder="Search…" trailing={<SearchActions />} dimActions autoComplete="off" />
|
|
107
|
+
<Input label="Clear action" placeholder="Search…" clearable dimActions defaultValue="design tokens" autoComplete="off" />
|
|
108
|
+
<Input label="All adornments" leading={<Icon shape="search" />} trailing={<SearchActions />} clearable dimActions defaultValue="design tokens" autoComplete="off" />
|
|
109
|
+
<Input label="Text adornments" leading="from" trailing="each" defaultValue="$20" autoComplete="off" />
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
131
113
|
```
|
|
132
114
|
|
|
133
|
-
`leading` and `trailing`
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
playground at the top of this page shows a live leading icon alongside the clear
|
|
137
|
-
button.
|
|
115
|
+
Use `leading` and `trailing` to place icons, buttons, or short text inside the
|
|
116
|
+
field. Use either on its own or combine them with a clear button. The preview
|
|
117
|
+
shows search options and text such as “from” and “each.”
|
|
138
118
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
element turns into the lifecycle below.
|
|
153
|
-
|
|
154
|
-
Two hooks bracket the clear. **`onClearClick`** fires first and is **cancelable** —
|
|
155
|
-
`e.preventDefault()` keeps the value (e.g. a "discard unsaved text?" confirm). If
|
|
156
|
-
it isn't prevented, the field clears: it empties, fires `input` / `change` (a
|
|
157
|
-
controlled `onChange` runs with the empty value), refocuses, then fires
|
|
158
|
-
**`onClearInput`**. On a raw `<a-input>`, bind both lowercase (`onclearclick` /
|
|
159
|
-
`onclearinput`) — that form binds in React and Preact alike.
|
|
160
|
-
|
|
161
|
-
Note: there's no `type="search"` — that type makes browsers inject their own
|
|
162
|
-
clear button and magnifier (and style them inconsistently). Anta owns every
|
|
163
|
-
in-field control, and the element resets the native search/number/reveal
|
|
164
|
-
decorations across browsers.
|
|
119
|
+
Trailing icon buttons adjust to the field size, with space around them to keep them
|
|
120
|
+
inside the border. You don't need to size them separately.
|
|
121
|
+
|
|
122
|
+
Use `dimActions` to keep these extras subtle until someone hovers over or
|
|
123
|
+
focuses the field.
|
|
124
|
+
|
|
125
|
+
`clearable` shows a clear button when an editable field has a value. After
|
|
126
|
+
clearing, focus returns to the field so typing can continue. See
|
|
127
|
+
[Events](#events) to cancel a clear or respond after it completes.
|
|
128
|
+
|
|
129
|
+
For a search field, use `type="search"` to add a search icon and clear button.
|
|
130
|
+
You can replace the icon with `leading` or hide the button with
|
|
131
|
+
`clearable={false}`.
|
|
165
132
|
|
|
166
133
|
### Password reveal
|
|
167
134
|
|
|
168
135
|
```tsx
|
|
169
|
-
// Reveal toggle = flip `type` between password and text. Native masking when
|
|
170
|
-
// hidden, plain text when shown; password managers keep working.
|
|
171
136
|
const [reveal, setReveal] = useState(false)
|
|
172
137
|
|
|
173
138
|
<Input
|
|
@@ -187,93 +152,112 @@ const [reveal, setReveal] = useState(false)
|
|
|
187
152
|
/>
|
|
188
153
|
```
|
|
189
154
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
working, and the uncontrolled value is preserved across the toggle.
|
|
194
|
-
|
|
195
|
-
The mask glyph stays the browser default — restyling it means dropping
|
|
196
|
-
`type="password"`, which loses password-manager support and isn't masked in
|
|
197
|
-
Firefox. So Anta keeps the native field.
|
|
155
|
+
Use a trailing button to toggle `type` between `password` and `text` without
|
|
156
|
+
changing the value. The browser masks the password while it is hidden.
|
|
157
|
+
`autoComplete="current-password"` identifies an existing password for autofill.
|
|
198
158
|
|
|
199
159
|
## Multiline
|
|
200
160
|
|
|
201
161
|
```tsx
|
|
202
|
-
{/* Grows with content,
|
|
162
|
+
{/* Grows with content, then scrolls */}
|
|
203
163
|
<Input multiline maxRows={6} label="Bio (autogrows)" placeholder="Tell us…" autoComplete="off" />
|
|
204
164
|
|
|
205
|
-
{/*
|
|
206
|
-
<Input multiline rows={3} label="Notes (fixed
|
|
165
|
+
{/* Keeps a fixed height */}
|
|
166
|
+
<Input multiline rows={3} label="Notes (fixed height)" placeholder="…" autoComplete="off" />
|
|
207
167
|
```
|
|
208
168
|
|
|
209
|
-
`multiline`
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
fixed **`rows`** count for a constant-height box instead.
|
|
213
|
-
|
|
214
|
-
Autogrow uses CSS `field-sizing` where supported (Chromium, Safari ≥ 26.2) and a
|
|
215
|
-
built-in JS resize everywhere else (Firefox, older Safari), so it grows in every
|
|
216
|
-
browser.
|
|
169
|
+
Use `multiline` for longer text. The field grows as someone types.
|
|
170
|
+
Set `maxRows` to limit its growth, or `rows` to keep a fixed height and scroll
|
|
171
|
+
longer content.
|
|
217
172
|
|
|
218
173
|
## Controlled and uncontrolled
|
|
219
174
|
|
|
220
175
|
```tsx
|
|
221
176
|
// Uncontrolled: the element updates its value after input.
|
|
222
|
-
<Input label="Name" defaultValue="Ada" autoComplete="name" onChange={(e) => log(e.target.value)} />
|
|
177
|
+
<Input label="Name" defaultValue="Ada" autoComplete="name" onChange={(e) => console.log(e.target.value)} />
|
|
223
178
|
|
|
224
179
|
// Controlled: application state supplies the value.
|
|
225
|
-
const [
|
|
226
|
-
<Input label="Name" value={
|
|
180
|
+
const [value, setValue] = useState('')
|
|
181
|
+
<Input label="Name" value={value} autoComplete="name" onInput={(e) => setValue(e.target.value)} />
|
|
227
182
|
```
|
|
228
183
|
|
|
229
|
-
|
|
230
|
-
`onInput`
|
|
231
|
-
|
|
232
|
-
jumps mid-edit.
|
|
184
|
+
Use `defaultValue` when the field can manage its own value. Use `value` with
|
|
185
|
+
`onInput` or `onValueChange` when your application needs to keep track of every
|
|
186
|
+
edit, such as updating a search or showing a character count.
|
|
233
187
|
|
|
234
|
-
Read the
|
|
235
|
-
|
|
188
|
+
Read the current text from `e.target.value`, or use the value provided by
|
|
189
|
+
`onValueChange`. Use `onChange` for edits that are committed, such as when the
|
|
190
|
+
field loses focus.
|
|
236
191
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
since the framework skips the re-render. Constrain hard with `maxLength` /
|
|
241
|
-
`pattern` / `type`, or transform in the handler.
|
|
192
|
+
Changing the value in state updates the field. Setting state to the same value
|
|
193
|
+
may not undo a typed edit. Use `maxLength` for a length limit, and apply any text
|
|
194
|
+
formatting in your change handler.
|
|
242
195
|
|
|
243
196
|
## Events
|
|
244
197
|
|
|
245
|
-
|
|
|
198
|
+
| Handler | When it fires | Value or action |
|
|
246
199
|
|---|---|---|
|
|
247
|
-
| `onInput(e)` |
|
|
248
|
-
| `onChange(e)` |
|
|
249
|
-
| `onValueChange(e, attrs)` |
|
|
250
|
-
| `onClearClick(e)` |
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
200
|
+
| `onInput(e)` | When editing changes the value, or the field is cleared | Read `e.target.value` |
|
|
201
|
+
| `onChange(e)` | On commit, such as blur or Enter, or when cleared | Read `e.target.value` |
|
|
202
|
+
| `onValueChange(e, attrs)` | On both `input` and `change` | `{ value, name, empty, valid, validationMessage }` |
|
|
203
|
+
| `onClearClick(e)` | Before clearing | Call `e.preventDefault()` synchronously to cancel |
|
|
204
|
+
| `onClearInput(e)` | After clearing | The value is empty |
|
|
205
|
+
|
|
206
|
+
Use `onValueChange` to receive the current text and validation result together.
|
|
207
|
+
It runs while editing and when an edit is committed, so it can run more than
|
|
208
|
+
once for the same value.
|
|
209
|
+
|
|
210
|
+
Use `onClearClick` to keep a draft from being cleared. Try **Clear** with
|
|
211
|
+
**Protect draft** enabled, then turn protection off and try again.
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { useState } from 'preact/hooks'
|
|
215
|
+
import { Input, Checkbox, Button } from '@antadesign/anta'
|
|
216
|
+
|
|
217
|
+
function Demo() {
|
|
218
|
+
const [value, setValue] = useState('Keep this draft')
|
|
219
|
+
const [protect, setProtect] = useState(true)
|
|
220
|
+
const [event, setEvent] = useState('Edit the field or select Clear.')
|
|
221
|
+
return (
|
|
222
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', width: '320px', maxWidth: '100%' }}>
|
|
223
|
+
<Input
|
|
224
|
+
label="Draft"
|
|
225
|
+
value={value}
|
|
226
|
+
clearable
|
|
227
|
+
hint={event}
|
|
228
|
+
onValueChange={(event, { value }) => {
|
|
229
|
+
setValue(value)
|
|
230
|
+
setEvent(event.type === 'input' ? 'Draft updated.' : 'Draft committed.')
|
|
231
|
+
}}
|
|
232
|
+
onClearClick={event => {
|
|
233
|
+
if (protect) {
|
|
234
|
+
event.preventDefault()
|
|
235
|
+
setEvent('Clear cancelled. Turn off Protect draft to clear it.')
|
|
236
|
+
}
|
|
237
|
+
}}
|
|
238
|
+
onClearInput={() => setEvent('Draft cleared.')}
|
|
239
|
+
/>
|
|
240
|
+
<Checkbox label="Protect draft" checked={protect}
|
|
241
|
+
onStateChange={(_, { next }) => setProtect(next)} />
|
|
242
|
+
<Button label="Restore draft" onClick={() => setValue('Keep this draft')} />
|
|
243
|
+
</div>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
```
|
|
262
247
|
|
|
263
248
|
## Forms
|
|
264
249
|
|
|
265
250
|
```tsx
|
|
266
|
-
<form
|
|
251
|
+
<form>
|
|
267
252
|
<Input name="email" label="Email" type="email" autoComplete="email" required clearable />
|
|
268
253
|
<Button tone="brand" type="submit" label="Sign up" />
|
|
269
254
|
<Button priority="tertiary" type="reset" label="Reset" />
|
|
270
255
|
</form>
|
|
271
256
|
```
|
|
272
257
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
restores the field to its `defaultValue` via `formResetCallback`.
|
|
258
|
+
Input submits its value under `name` with the surrounding form, and
|
|
259
|
+
`new FormData(form)` includes it. Native constraints such as `required` block
|
|
260
|
+
normal submission while invalid. A reset button restores `defaultValue`.
|
|
277
261
|
|
|
278
262
|
## Types and validation
|
|
279
263
|
|
|
@@ -286,98 +270,92 @@ restores the field to its `defaultValue` via `formResetCallback`.
|
|
|
286
270
|
<Input type="number" label="Number" autoComplete="off" min={0} max={100} />
|
|
287
271
|
```
|
|
288
272
|
|
|
289
|
-
`type`
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
`
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
`
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
`
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
back drops the decimal for the same reason. Keep the raw string in state and parse
|
|
305
|
-
to a number where you use it — `inputMode` still brings up the numeric keypad. An
|
|
306
|
-
**uncontrolled** `type="number"` (no bound `value`) has neither problem.
|
|
307
|
-
|
|
308
|
-
Every type carries its native constraints (`required`, the `type` itself,
|
|
309
|
-
`pattern`, `min`/`max`, `min`/`maxLength`). The field reports them to the
|
|
310
|
-
surrounding `<form>` automatically (via `ElementInternals`), so submission is
|
|
311
|
-
blocked while invalid — no extra wiring.
|
|
273
|
+
Choose `type` to match what someone will enter: text, an email address,
|
|
274
|
+
a password, a phone number, a URL, or a number. Use `search` for a search field.
|
|
275
|
+
|
|
276
|
+
Set `autoComplete` to help the browser fill in familiar information, such as a
|
|
277
|
+
name or saved password. Email, telephone, and URL fields already use matching
|
|
278
|
+
autocomplete hints. Use `autoComplete="off"` where autofill isn't useful.
|
|
279
|
+
|
|
280
|
+
For numeric text that needs to keep partial entries or trailing zeros, use
|
|
281
|
+
`type="text"` with `inputMode="decimal"` or `"numeric"`. Keep the text as entered
|
|
282
|
+
and convert it to a number when needed. `inputMode` suggests a keyboard without
|
|
283
|
+
restricting what can be entered.
|
|
284
|
+
|
|
285
|
+
Use `required`, length limits, a `pattern`, or numeric limits to check values
|
|
286
|
+
before submission. Available checks depend on the field type. A `pattern`
|
|
287
|
+
checks the finished value without blocking typing.
|
|
312
288
|
|
|
313
289
|
### Native validation
|
|
314
290
|
|
|
315
291
|
```tsx
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
function
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
e
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
292
|
+
import { useState } from 'preact/hooks'
|
|
293
|
+
import { Input, Button } from '@antadesign/anta'
|
|
294
|
+
|
|
295
|
+
function Demo() {
|
|
296
|
+
const [errors, setErrors] = useState<Record<string, string | undefined>>({})
|
|
297
|
+
|
|
298
|
+
function onSubmit(e: SubmitEvent) {
|
|
299
|
+
e.preventDefault()
|
|
300
|
+
const next: Record<string, string | undefined> = {}
|
|
301
|
+
const form = e.currentTarget as HTMLFormElement
|
|
302
|
+
form.querySelectorAll('a-input').forEach((el: any) => {
|
|
303
|
+
if (!el.checkValidity()) next[el.name] = el.validationMessage
|
|
304
|
+
})
|
|
305
|
+
setErrors(next)
|
|
306
|
+
}
|
|
307
|
+
const clearError = (name: string) => setErrors(previous => ({ ...previous, [name]: undefined }))
|
|
308
|
+
|
|
309
|
+
return (
|
|
310
|
+
<form noValidate onSubmit={onSubmit}
|
|
311
|
+
style={{ display: 'flex', flexDirection: 'column', gap: '14px', width: '300px' }}>
|
|
312
|
+
<Input name="email" label="Email" type="email" autoComplete="email"
|
|
313
|
+
placeholder="you@example.com" required hint={errors.email}
|
|
314
|
+
status={errors.email ? 'critical' : undefined}
|
|
315
|
+
onInput={() => clearError('email')} />
|
|
316
|
+
<Input name="site" label="Website" type="url" autoComplete="url"
|
|
317
|
+
placeholder="https://…" hint={errors.site}
|
|
318
|
+
status={errors.site ? 'critical' : undefined}
|
|
319
|
+
onInput={() => clearError('site')} />
|
|
320
|
+
<Input name="age" label="Age" type="number" autoComplete="off"
|
|
321
|
+
placeholder="18 – 120" min="18" max="120" hint={errors.age}
|
|
322
|
+
status={errors.age ? 'critical' : undefined}
|
|
323
|
+
onInput={() => clearError('age')} />
|
|
324
|
+
<div style={{ display: 'flex', gap: '8px' }}>
|
|
325
|
+
<Button type="submit" tone="brand" label="Submit" />
|
|
326
|
+
<Button type="reset" priority="tertiary" label="Reset" onClick={() => setErrors({})} />
|
|
327
|
+
</div>
|
|
328
|
+
</form>
|
|
329
|
+
)
|
|
326
330
|
}
|
|
327
|
-
|
|
328
|
-
<form noValidate onSubmit={onSubmit}>
|
|
329
|
-
<Input name="email" type="email" autoComplete="email" required hint={errors.email}
|
|
330
|
-
status={errors.email ? 'critical' : undefined}
|
|
331
|
-
onInput={() => setErrors(p => ({ ...p, email: undefined }))} />
|
|
332
|
-
<Input name="age" type="number" autoComplete="off" min="18" max="120" hint={errors.age}
|
|
333
|
-
status={errors.age ? 'critical' : undefined}
|
|
334
|
-
onInput={() => setErrors(p => ({ ...p, age: undefined }))} />
|
|
335
|
-
<Button type="submit" label="Submit" />
|
|
336
|
-
</form>
|
|
337
331
|
```
|
|
338
332
|
|
|
339
|
-
|
|
340
|
-
`validationMessage`
|
|
333
|
+
You can show the browser's validation messages as hints. Check each field
|
|
334
|
+
with `checkValidity()`, put its `validationMessage` in `hint`, and use
|
|
335
|
+
`status="critical"` for errors. Add `noValidate` to the form when your handler
|
|
336
|
+
will display the messages instead of the browser's popup.
|
|
341
337
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
the form `noValidate` so the browser's default bubbles step aside for Anta's
|
|
345
|
-
styling. Try submitting empty, or with a bad email / out-of-range age.
|
|
346
|
-
|
|
347
|
-
**Enter doesn't submit the form.** The real `<input>` lives in shadow DOM, so
|
|
348
|
-
it isn't a light-DOM member of the `<form>`, and pressing Enter won't trigger
|
|
349
|
-
native implicit submission — a deliberate choice, since auto-submitting a
|
|
350
|
-
half-filled multi-field form is usually more annoyance than help. To submit on
|
|
351
|
-
Enter, handle it yourself (`onKeyDown` → `form.requestSubmit()`), or reach for
|
|
352
|
-
Anta's upcoming `<Form>` component. Everything else — value submission under
|
|
353
|
-
`name`, `checkValidity()`, `formReset` — works natively.
|
|
338
|
+
Try submitting an empty email, an invalid address, or an age outside the range.
|
|
339
|
+
Use **Submit** to send the form. Input does not submit automatically on Enter.
|
|
354
340
|
|
|
355
341
|
## Layout
|
|
356
342
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
Rearrange them from your own CSS: re-template the grid on `a-input`, then place
|
|
361
|
-
the parts. No layout prop to learn — your rule wins because the element's
|
|
362
|
-
defaults live in `@layer anta`.
|
|
343
|
+
Labels appear above their fields and hints below. Use CSS to move a label
|
|
344
|
+
beside its field, align labels across a form, or place a hint alongside a field.
|
|
345
|
+
The examples show the selectors to use.
|
|
363
346
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
wrapping container and they reflow by available width — the field's internal
|
|
367
|
-
grid is independent of how the fields themselves flow.
|
|
347
|
+
You can also arrange whole fields in columns or let them wrap as the available
|
|
348
|
+
space changes.
|
|
368
349
|
|
|
369
|
-
The
|
|
370
|
-
scope each demo — swap your own selector.
|
|
350
|
+
The classes below scope each example. Replace them with your own selectors.
|
|
371
351
|
|
|
372
352
|
### Label on the left
|
|
373
353
|
|
|
374
|
-
|
|
375
|
-
under the field by landing in the same column.
|
|
354
|
+
Use two columns for the label and field. Place the hint in the field's column.
|
|
376
355
|
|
|
377
356
|
```tsx
|
|
378
357
|
<Input className="label-side" label="Display name" hint="Shown on your profile" autoComplete="name" />
|
|
379
358
|
|
|
380
|
-
{/* .label-side is just for the demo — use your own selector */}
|
|
381
359
|
<style>{`
|
|
382
360
|
a-input.label-side {
|
|
383
361
|
grid-template-columns: max-content minmax(0, 1fr);
|
|
@@ -392,10 +370,8 @@ under the field by landing in the same column.
|
|
|
392
370
|
|
|
393
371
|
### Label column
|
|
394
372
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
so every label shares one column sized to the longest label, and every field
|
|
398
|
-
left-edge lines up. Each hint still tucks under its own field.
|
|
373
|
+
Keep labels in a shared column so fields line up even when their labels have
|
|
374
|
+
different lengths. Each hint stays with its field.
|
|
399
375
|
|
|
400
376
|
```tsx
|
|
401
377
|
<div className="aligned-form">
|
|
@@ -405,7 +381,6 @@ left-edge lines up. Each hint still tucks under its own field.
|
|
|
405
381
|
</div>
|
|
406
382
|
|
|
407
383
|
<style>{`
|
|
408
|
-
/* one shared label column; subgrid lets each field adopt the form's tracks */
|
|
409
384
|
.aligned-form { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 16px 12px; }
|
|
410
385
|
.aligned-form > a-input { grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; }
|
|
411
386
|
.aligned-form > a-input::part(label) { grid-column: 1; }
|
|
@@ -416,9 +391,8 @@ left-edge lines up. Each hint still tucks under its own field.
|
|
|
416
391
|
|
|
417
392
|
### Hint on the right
|
|
418
393
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
centers against the field.
|
|
394
|
+
Place a short hint or counter beside the field. The label spans both columns,
|
|
395
|
+
and the hint aligns vertically with the field.
|
|
422
396
|
|
|
423
397
|
```tsx
|
|
424
398
|
<Input className="hint-right" label="Username" hint="3–20 characters" placeholder="ada" autoComplete="username" />
|
|
@@ -436,9 +410,8 @@ centers against the field.
|
|
|
436
410
|
|
|
437
411
|
### Wrap by field width
|
|
438
412
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
413
|
+
Let fields share a row when there is room and wrap when space is limited.
|
|
414
|
+
Narrow the preview to see the layout adjust.
|
|
442
415
|
|
|
443
416
|
```tsx
|
|
444
417
|
<div className="wrap-fields">
|
|
@@ -449,7 +422,6 @@ wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
|
449
422
|
</div>
|
|
450
423
|
|
|
451
424
|
<style>{`
|
|
452
|
-
/* fields stay stacked; the grid wraps them by available width */
|
|
453
425
|
.wrap-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; }
|
|
454
426
|
`}</style>
|
|
455
427
|
```
|
|
@@ -458,56 +430,87 @@ wraps to fewer columns as it narrows. Resize the preview to see it reflow.
|
|
|
458
430
|
|
|
459
431
|
| Prop | Type | Default | Description |
|
|
460
432
|
|------|------|---------|-------------|
|
|
461
|
-
| `autoComplete?` | 'off' \| 'on' \| 'name' \| 'username' \| 'email' \| 'current-password' \| 'new-password' \| 'one-time-code' \| 'tel' \| 'url' \| (string & {}) | — | Native autocomplete token. Overrides the
|
|
433
|
+
| `autoComplete?` | 'off' \| 'on' \| 'name' \| 'username' \| 'email' \| 'current-password' \| 'new-password' \| 'one-time-code' \| 'tel' \| 'url' \| (string & {}) | — | Native autocomplete token describing the field purpose. Overrides the token derived from the email, tel, or url type. Set an explicit token for other purposes, such as `username`, `current-password`, or `one-time-code`. |
|
|
462
434
|
| `autoFocus?` | boolean | — | Focus this field when its containing `Dialog` opens. |
|
|
463
435
|
| `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. |
|
|
464
|
-
| `children?` | ReactNode | — | Extra content
|
|
465
|
-
| `clearable?` | boolean | — | Show a clear button
|
|
466
|
-
| `defaultValue?` | string | — | Initial value for
|
|
467
|
-
| `dimActions?` | boolean | — |
|
|
436
|
+
| `children?` | ReactNode | — | Extra content between the field and hint. A `Tooltip` child anchors to the field. Use `leading` and `trailing` for content inside the field. |
|
|
437
|
+
| `clearable?` | boolean | — | Show a clear button before trailing content when an editable field has a value. |
|
|
438
|
+
| `defaultValue?` | string | — | Initial value for an uncontrolled field, restored on form reset. |
|
|
439
|
+
| `dimActions?` | boolean | — | Keep leading, trailing, and clear content subtle until someone hovers over or focuses the field. |
|
|
468
440
|
| `disabled?` | boolean | — | Disable the field. |
|
|
469
|
-
| `hint?` | ReactNode | — |
|
|
470
|
-
| `inputMode?` | 'none' \| 'text' \| 'decimal' \| 'numeric' \| 'tel' \| 'search' \| 'email' \| 'url' | — | Virtual
|
|
471
|
-
| `label?` | ReactNode | — |
|
|
472
|
-
| `leading?` | ReactNode | — | Content
|
|
473
|
-
| `max?` | number \| string | — |
|
|
474
|
-
| `maxLength?` | number | — |
|
|
475
|
-
| `maxRows?` | number | — |
|
|
476
|
-
| `min?` | number \| string | — |
|
|
477
|
-
| `minLength?` | number | — |
|
|
478
|
-
| `multiline?` | boolean | — |
|
|
479
|
-
| `name?` | string | — | Form field name
|
|
441
|
+
| `hint?` | ReactNode | — | Persistent help or feedback below the field. `status` colors the message and adds a status icon. |
|
|
442
|
+
| `inputMode?` | 'none' \| 'text' \| 'decimal' \| 'numeric' \| 'tel' \| 'search' \| 'email' \| 'url' | — | Virtual keyboard hint. Overrides the value derived from `type` without changing validation. |
|
|
443
|
+
| `label?` | ReactNode | — | Explain what to enter. Accepts text or JSX and also names the field for screen readers. |
|
|
444
|
+
| `leading?` | ReactNode | — | Content at the start of the field, such as an icon or text. |
|
|
445
|
+
| `max?` | number \| string | — | Maximum value for `type="number"`. |
|
|
446
|
+
| `maxLength?` | number | — | Maximum text length for native types that support it. |
|
|
447
|
+
| `maxRows?` | number | — | Maximum row count for autogrow when `rows` is unset. Omit for unlimited growth. |
|
|
448
|
+
| `min?` | number \| string | — | Minimum value for `type="number"`. |
|
|
449
|
+
| `minLength?` | number | — | Minimum text length for native types that support it. |
|
|
450
|
+
| `multiline?` | boolean | — | Allow longer text and grow the field as someone types. Use `maxRows` to limit growth or `rows` to keep a fixed height. |
|
|
451
|
+
| `name?` | string | — | Form field name for submission, named form lookup, and attribute selectors. |
|
|
480
452
|
| `onBlur?` | (e) => void | — | Fires when the field loses focus. |
|
|
481
|
-
| `onChange?` | (e) => void | — | Fires on
|
|
482
|
-
| `onClearClick?` | (e) => void | — | Fires
|
|
483
|
-
| `onClearInput?` | (e) => void | — | Fires after
|
|
453
|
+
| `onChange?` | (e) => void | — | Fires on native commit, such as blur or Enter, and on clear. Use `onInput` or `onValueChange` for live edits. Read `e.target.value`. |
|
|
454
|
+
| `onClearClick?` | (e) => void | — | Fires before the built-in clear action. Call `e.preventDefault()` synchronously to keep the value and cancel `onClearInput`. Corresponds to the cancelable, bubbling `clearclick` event. |
|
|
455
|
+
| `onClearInput?` | (e) => void | — | Fires after clearing, following `onInput` and `onChange`. Does not fire when clearing is canceled. Corresponds to the bubbling `clearinput` event. |
|
|
484
456
|
| `onFocus?` | (e) => void | — | Fires when the field gains focus. |
|
|
485
|
-
| `onInput?` | (e) => void | — | Fires
|
|
486
|
-
| `onValueChange?` | (event, attrs) => void | — |
|
|
487
|
-
| `pattern?` | string | — | Validation pattern
|
|
457
|
+
| `onInput?` | (e) => void | — | Fires when editing changes the value or the field is cleared. Read `e.target.value`. |
|
|
458
|
+
| `onValueChange?` | (event, attrs) => void | — | Receive the current text, field name, and validation result while editing and when an edit is committed, including clear. Can run more than once for the same value. Use `event.type` to distinguish the events. |
|
|
459
|
+
| `pattern?` | string | — | Validation pattern for supported single-line types. Checks validity without preventing typing. |
|
|
488
460
|
| `placeholder?` | string | — | Placeholder shown when empty. |
|
|
489
461
|
| `priority?` | 'primary' \| 'secondary' \| 'tertiary' | primary | Field emphasis. `primary` has a fill and border, `secondary` keeps the border without a fill, and `tertiary` makes the border transparent until hover or focus. Status borders remain visible at rest. |
|
|
490
462
|
| `readOnly?` | boolean | — | Make the field read-only. |
|
|
491
463
|
| `required?` | boolean | — | Mark the field required (drives native validity). |
|
|
492
|
-
| `role?` | string | — | ARIA
|
|
493
|
-
| `round?` | boolean \| number \| string | — |
|
|
494
|
-
| `rows?` | number | — | Fixed visible row count
|
|
495
|
-
| `size?` | 'small' \| 'medium' \| 'large' | medium |
|
|
464
|
+
| `role?` | string | — | ARIA role for the native control, such as `combobox` for an InputAutocomplete trigger. The element delegates this and standard `aria-*` props to its native shadow control. |
|
|
465
|
+
| `round?` | boolean \| number \| string | — | Give the field fully rounded corners. Pass a number in pixels or a CSS length for a custom radius. The clear button stays circular. |
|
|
466
|
+
| `rows?` | number | — | Fixed visible row count. Also enables `multiline`. |
|
|
467
|
+
| `size?` | 'small' \| 'medium' \| 'large' | medium | Adjust the field, text, icons, and action buttons together to suit the surrounding interface. |
|
|
496
468
|
| `spellCheck?` | boolean | — | Toggle native spell-checking. |
|
|
497
|
-
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | — |
|
|
498
|
-
| `statusIcon?` | (string & {}) \| false \| IconShape | — |
|
|
499
|
-
| `step?` | number \| string | — |
|
|
500
|
-
| `tone?` | string | — | Custom
|
|
501
|
-
| `trailing?` | ReactNode | — | Content
|
|
469
|
+
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | — | Feedback for the field and hint. Use `critical` for an error that must be fixed before submission. Other statuses provide feedback without adding a validation error. Required fields and other validation rules still apply. |
|
|
470
|
+
| `statusIcon?` | (string & {}) \| false \| IconShape | — | Icon before the hint. The defaults are `warning-diamond` for critical, `warning-triangle` for warning, `circle-check` for success, `info` for info, and `circle-small-solid` for brand. Pass a shape to replace it or `false` to hide it. Neutral has no default icon. |
|
|
471
|
+
| `step?` | number \| string | — | Allowed increment for `type="number"`. |
|
|
472
|
+
| `tone?` | string | — | Custom CSS border color. A non-neutral `status` takes precedence. The focus ring uses the global `--focus-ring`. |
|
|
473
|
+
| `trailing?` | ReactNode | — | Content at the end of the field, after the clear button. Anta buttons fit the field height and keep their padding. Icon-only Buttons are square; text buttons keep their natural width. Pass buttons directly or in a fragment for compact spacing. Other wrapping elements keep the text inset. Override either inset with the `--input-trailing-inset` CSS property. |
|
|
502
474
|
| `truncate?` | boolean | true | Ellipsize an overflowing single-line value. Read-only inputs already do this; pass `false` when an editable field should show the full value. |
|
|
503
|
-
| `type?` | 'text' \| 'search' \| 'email' \| 'password' \| 'tel' \| 'url' \| 'number' | text |
|
|
504
|
-
| `value?` | string | — | Controlled value.
|
|
475
|
+
| `type?` | 'text' \| 'search' \| 'email' \| 'password' \| 'tel' \| 'url' \| 'number' | text | Choose the kind of information to enter. Ignored for multiline fields. `search` adds a search icon and clear button. Replace the icon with `leading` or hide the button with `clearable={false}`. |
|
|
476
|
+
| `value?` | string | — | Controlled value. Update it with `onInput` or `onValueChange` for live editing. |
|
|
505
477
|
|
|
506
478
|
## Web Component
|
|
507
479
|
|
|
508
|
-
Use
|
|
480
|
+
Use `<a-input>` directly outside React or Preact.
|
|
481
|
+
|
|
482
|
+
Slots accept content; shadow parts expose regions for CSS. The `label`,
|
|
483
|
+
`leading`, `clear`, `trailing`, and `hint` slots are independent of the parts
|
|
484
|
+
with matching names. Unslotted children appear after the field and before the hint.
|
|
485
|
+
|
|
486
|
+
Group trailing buttons in `<a-input-trailing slot="trailing">` to use compact
|
|
487
|
+
action spacing. Mixed content keeps the text inset. The grouping tag needs no
|
|
488
|
+
JavaScript registration.
|
|
489
|
+
|
|
490
|
+
Anta buttons fit the field height and keep their own padding. Add
|
|
491
|
+
`data-anta-icon-only` to a raw icon-only button for a square box. Text buttons
|
|
492
|
+
keep their natural width. The JSX Button and ButtonCopy wrappers mark their
|
|
493
|
+
icon-only actions automatically.
|
|
494
|
+
|
|
495
|
+
Set `role` and `aria-*` on `<a-input>` to describe the field to assistive
|
|
496
|
+
technology. Input applies them to the control that receives focus. Explicit
|
|
497
|
+
names and descriptions take precedence over its label and hint.
|
|
509
498
|
|
|
510
|
-
|
|
499
|
+
The JSX `type="search"` shorthand uses a native text input. On a raw `<a-input>`,
|
|
500
|
+
`type="search"` uses a native search input. Listen for `clearclick` and
|
|
501
|
+
`clearinput` with `addEventListener()` to handle clearing without a JSX wrapper.
|
|
502
|
+
|
|
503
|
+
The `name` property and attribute stay in sync. Updating either changes the
|
|
504
|
+
submitted field name, `form.elements.namedItem()` lookup, and attribute selectors.
|
|
505
|
+
Removing the name excludes the field from form submission.
|
|
506
|
+
|
|
507
|
+
`checkValidity()`, `reportValidity()`, `validity`, `validationMessage`, and
|
|
508
|
+
`willValidate` expose form validation. `status="critical"` adds a custom error;
|
|
509
|
+
other statuses remain advisory. There is no public `setCustomValidity()` method.
|
|
510
|
+
|
|
511
|
+
Use `rows` for a fixed height or `maxrows` to limit growth. Some browsers
|
|
512
|
+
recalculate a growing field's height on the next value change after its width
|
|
513
|
+
or font changes.
|
|
511
514
|
|
|
512
515
|
```html
|
|
513
516
|
<a-input name="email" type="email" autocomplete="email" placeholder="you@example.com">
|
|
@@ -518,32 +521,27 @@ Slots hold the label, hint, and controls around the native field.
|
|
|
518
521
|
|
|
519
522
|
### Native HTML inputs
|
|
520
523
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
file name, with an Anta-styled chooser button. `submit` and `reset` inputs use the
|
|
526
|
-
matching Anta button chrome; set `priority="primary"` on a submit control when it
|
|
527
|
-
is the form's main action.
|
|
524
|
+
Add `data-anta` to an HTML input to give it Anta styling while keeping its
|
|
525
|
+
usual browser behavior. Search and file inputs keep their built-in controls.
|
|
526
|
+
Submit and reset inputs look like Anta buttons. Use `priority="primary"` for
|
|
527
|
+
the form's main action.
|
|
528
528
|
|
|
529
|
-
`<textarea data-anta>`
|
|
530
|
-
|
|
531
|
-
autogrow; use Input's [`multiline`](#multiline) instead.
|
|
529
|
+
Use `<textarea data-anta>` for longer text with a manually resizable height.
|
|
530
|
+
For a field that grows as someone types, use [multiline Input](#multiline).
|
|
532
531
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
`tone` work the same way as Input.
|
|
532
|
+
Choose a size with `data-anta-size="small"` or `"large"`.
|
|
533
|
+
Use `round` for rounded corners and `tone` for a custom border color.
|
|
536
534
|
|
|
537
535
|
```html
|
|
538
|
-
<input data-anta data-anta-size="small" type="text" name="name" placeholder="Small text">
|
|
539
|
-
<input data-anta type="search" name="search" placeholder="Search">
|
|
540
|
-
<input data-anta type="email" name="email" placeholder="Email">
|
|
541
|
-
<input data-anta type="tel" name="phone" placeholder="Telephone">
|
|
542
|
-
<input data-anta round type="url" name="site" placeholder="Rounded URL">
|
|
543
|
-
<input data-anta type="password" name="password" value="password">
|
|
544
|
-
<input data-anta tone="rebeccapurple" type="number" name="seats" value="3" min="1">
|
|
545
|
-
<textarea data-anta rows="3" name="notes" placeholder="Notes"></textarea>
|
|
546
|
-
<input data-anta type="file" name="attachment" accept=".pdf,.docx">
|
|
536
|
+
<input data-anta data-anta-size="small" type="text" name="name" aria-label="Name" placeholder="Small text">
|
|
537
|
+
<input data-anta type="search" name="search" aria-label="Search" placeholder="Search">
|
|
538
|
+
<input data-anta type="email" name="email" aria-label="Email" placeholder="Email">
|
|
539
|
+
<input data-anta type="tel" name="phone" aria-label="Telephone" placeholder="Telephone">
|
|
540
|
+
<input data-anta round type="url" name="site" aria-label="Website" placeholder="Rounded URL">
|
|
541
|
+
<input data-anta type="password" name="password" aria-label="Password" value="password">
|
|
542
|
+
<input data-anta tone="rebeccapurple" type="number" name="seats" aria-label="Seats" value="3" min="1">
|
|
543
|
+
<textarea data-anta rows="3" name="notes" aria-label="Notes" placeholder="Notes"></textarea>
|
|
544
|
+
<input data-anta type="file" name="attachment" aria-label="Attachment" accept=".pdf,.docx">
|
|
547
545
|
|
|
548
546
|
<input data-anta type="submit" value="Submit" priority="primary">
|
|
549
547
|
<input data-anta type="reset" value="Reset">
|
|
@@ -551,82 +549,78 @@ their `size` attribute, so Anta does not reuse it. `round` and a custom-color
|
|
|
551
549
|
|
|
552
550
|
## Styling
|
|
553
551
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
ring is the global [`--focus-ring`](../colors.md#focus-ring).
|
|
552
|
+
Use `priority` for the field surface, `status` for feedback, `tone` for a custom
|
|
553
|
+
border color, and `size` for dimensions. The focus ring uses the global
|
|
554
|
+
[`--focus-ring`](../colors.md#focus-ring).
|
|
558
555
|
|
|
559
556
|
```tsx
|
|
560
557
|
<Input tone="#e0457b" label="Custom accent" autoComplete="off" />
|
|
561
558
|
```
|
|
562
559
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
theme
|
|
560
|
+
Style shadow regions with `::part(field)`, `::part(input)`, `::part(input-label)`,
|
|
561
|
+
`::part(label)`, `::part(leading)`, `::part(trailing)`, `::part(clear)`, and
|
|
562
|
+
`::part(hint)`. Use `:state(filled)` for a nonempty value,
|
|
563
|
+
`:state(invalid)` for critical status, and `:focus::part(field)` when the
|
|
564
|
+
editable control is focused. Focus on a slotted action does not match this rule. The clear button lives in the light DOM, so target it
|
|
565
|
+
with a regular selector. Use `light-dark()` for theme-specific colors.
|
|
566
|
+
|
|
567
|
+
Set `--input-trailing-inset` to override the ending space for any trailing
|
|
568
|
+
content. Text and mixed content use the field's text inset by default;
|
|
569
|
+
buttons-only groups use compact spacing.
|
|
570
|
+
|
|
571
|
+
In button fields, `::part(input)` targets the native button, and
|
|
572
|
+
`::part(input-label)` targets its value or placeholder text. `::part(label)`
|
|
573
|
+
targets the separate visible field label.
|
|
574
|
+
|
|
575
|
+
Select uses the same field styling. See [Select styling](./select.md#styling) for
|
|
576
|
+
trigger customization.
|
|
569
577
|
|
|
570
578
|
```css
|
|
571
579
|
a-input::part(field) { border-radius: 999px; }
|
|
572
580
|
a-input::part(input) { font-variant-numeric: tabular-nums; }
|
|
573
581
|
a-input::part(label) { text-transform: uppercase; }
|
|
582
|
+
a-input.custom-inset { --input-trailing-inset: 4px; }
|
|
574
583
|
```
|
|
575
584
|
|
|
576
|
-
|
|
577
|
-
including tertiary's transparent border, and `1px` on hover, focus, or
|
|
578
|
-
non-neutral status)
|
|
579
|
-
never changes the box size. The field height stays aligned with `Button`.
|
|
580
|
-
Drop the leading `inset` to draw the border as an outset ring instead. You can
|
|
581
|
-
also re-point an `--input-*` color token on one instance
|
|
582
|
-
(`style={{ '--input-border': 'var(--border-1)' }}`)
|
|
583
|
-
or a wrapping selector; the resolver lives in `@layer anta`, so any un-layered rule
|
|
584
|
-
of yours wins.
|
|
585
|
+
To remove the field's border, use `box-shadow: none` as shown in the example.
|
|
585
586
|
|
|
586
|
-
|
|
587
|
-
|
|
587
|
+
If your policy blocks inline styles, set custom colors and dimensions in an
|
|
588
|
+
external stylesheet. See [Content Security Policy](../install-config.md#content-security-policy)
|
|
589
|
+
for customization props that emit inline styles.
|
|
590
|
+
|
|
591
|
+
Some browsers may show native number steppers or controls on a raw
|
|
592
|
+
`<a-input type="search">`. These keep their browser behavior. The JSX
|
|
593
|
+
`<Input type="search">` uses a text input with Anta's own search icon and clear
|
|
594
|
+
button.
|
|
595
|
+
|
|
596
|
+
This example creates a borderless pill with a dark fill in light mode and a
|
|
597
|
+
light fill in dark mode. The fill changes on focus.
|
|
588
598
|
|
|
589
599
|
```css
|
|
590
|
-
/* a borderless pill — the resting border is a box-shadow, so clear it. Dark-grey
|
|
591
|
-
fill that darkens on focus, white text; the inverse in dark mode via light-dark()
|
|
592
|
-
(Anta drives color-scheme from its theme toggle). */
|
|
593
600
|
a-input.fancy::part(field) {
|
|
594
601
|
border-radius: 999px;
|
|
595
|
-
box-shadow: none;
|
|
602
|
+
box-shadow: none;
|
|
596
603
|
background: light-dark(#3a3a3a, #ececec);
|
|
597
604
|
padding-block: 10px;
|
|
598
|
-
padding-inline: 20px;
|
|
605
|
+
padding-inline: 20px;
|
|
599
606
|
}
|
|
600
607
|
a-input.fancy::part(input) { color: light-dark(#ffffff, #1a1a1a); }
|
|
601
608
|
a-input.fancy::part(input)::placeholder {
|
|
602
609
|
color: light-dark(#b8b8b8, #666666);
|
|
603
610
|
opacity: 1;
|
|
604
611
|
}
|
|
605
|
-
a-input.fancy:focus
|
|
612
|
+
a-input.fancy:focus::part(field) { background: light-dark(#161616, #ffffff); }
|
|
606
613
|
```
|
|
607
614
|
|
|
608
615
|
### Placeholder contrast
|
|
609
616
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
instructions in a persistent label or hint.
|
|
613
|
-
|
|
614
|
-
Antune uses `--text-4` for placeholders. These ratios compare the default neutral
|
|
615
|
-
Input backgrounds with the example's literal color:
|
|
616
|
-
|
|
617
|
-
| Style | Placeholder | Background | Contrast |
|
|
618
|
-
| --- | --- | --- | --- |
|
|
619
|
-
| Antune light theme | `#7a737c` | `#ffffff` | 4.59:1 |
|
|
620
|
-
| Antune dark theme | `#7c737c` | `#000000` | 4.60:1 |
|
|
621
|
-
| Example | `#767676` | `#ffffff` | 4.54:1 |
|
|
617
|
+
Use placeholders for example values or formatting cues. Keep an accessible
|
|
618
|
+
name and put essential instructions in a persistent label or hint.
|
|
622
619
|
|
|
623
|
-
|
|
624
|
-
W3C
|
|
625
|
-
Redundant placeholders remain debated in the
|
|
626
|
-
[meeting discussion](https://www.w3.org/2025/04/16-matf-minutes.html) and
|
|
627
|
-
[open W3C issue](https://github.com/w3c/wcag/issues/4343); there is no agreed exemption.
|
|
620
|
+
Keep placeholder text readable against the field background in both light and
|
|
621
|
+
dark themes. See W3C's [placeholder contrast guidance](https://www.w3.org/WAI/tutorials/forms/instructions/#styling).
|
|
628
622
|
|
|
629
|
-
This
|
|
623
|
+
This example uses a darker placeholder on a fixed light background.
|
|
630
624
|
Replace `.placeholder-contrast` with your own class.
|
|
631
625
|
|
|
632
626
|
```tsx
|