@antadesign/anta 0.3.18 → 0.3.20
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/README.md +38 -242
- package/dist/anta_helpers.d.ts +2 -2
- package/dist/components/Banner.d.ts +3 -3
- package/dist/components/Button.d.ts +1 -1
- package/dist/components/Calendar.d.ts +11 -12
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/Card.js +1 -1
- package/dist/components/Checkbox.d.ts +8 -9
- package/dist/components/Dialog.d.ts +1 -1
- package/dist/components/Expander.d.ts +5 -6
- package/dist/components/Input.d.ts +6 -3
- package/dist/components/Input.js +3 -1
- package/dist/components/InputAutocomplete.d.ts +8 -8
- package/dist/components/InputDate.css +1 -0
- package/dist/components/InputDate.d.ts +1 -0
- package/dist/components/InputDate.js +5 -5
- package/dist/components/InputTime.d.ts +3 -3
- package/dist/components/InputTime.js +1 -1
- package/dist/components/Menu.d.ts +7 -3
- package/dist/components/Menu.js +3 -2
- package/dist/components/MenuItem.d.ts +1 -1
- package/dist/components/MenuItem.js +1 -1
- package/dist/components/Progress.d.ts +1 -1
- package/dist/components/RadioGroup.d.ts +12 -13
- package/dist/components/Select.d.ts +32 -38
- package/dist/components/Select.js +9 -13
- package/dist/components/SelectFaceted.d.ts +28 -33
- package/dist/components/SelectFaceted.js +29 -23
- package/dist/components/Slider.d.ts +5 -5
- package/dist/components/Switch.d.ts +4 -4
- package/dist/components/Tabs.d.ts +7 -7
- package/dist/components/Title.d.ts +1 -1
- package/dist/components/Toaster.d.ts +1 -1
- package/dist/components/Tooltip.d.ts +1 -1
- package/dist/components/select-parts.css +1 -0
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +1 -0
- package/dist/elements/a-expander.js +12 -2
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-menu.js +12 -0
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tabs.d.ts +3 -0
- package/dist/elements/a-tabs.js +40 -1
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +1 -1
- package/dist/elements/a-tooltip.js +1 -1
- package/dist/elements/index.d.ts +1 -1
- package/dist/general_types.d.ts +24 -22
- package/dist/index.d.ts +3 -3
- package/dist/jsx-runtime.d.ts +9 -0
- package/docs/accessibility.md +34 -0
- package/docs/changelog.md +561 -0
- package/docs/colors.md +42 -0
- package/docs/comparison.md +28 -0
- package/docs/components/banner.md +267 -0
- package/docs/components/button.md +603 -0
- package/docs/components/card.md +321 -0
- package/docs/components/checkbox.md +296 -0
- package/docs/components/dialog.md +314 -0
- package/docs/components/expander.md +526 -0
- package/docs/components/icon.md +155 -0
- package/docs/components/input-autocomplete.md +100 -0
- package/docs/components/input-date.md +401 -0
- package/docs/components/input-time.md +174 -0
- package/docs/components/input.md +610 -0
- package/docs/components/loader.md +139 -0
- package/docs/components/menu.md +511 -0
- package/docs/components/progress.md +182 -0
- package/docs/components/radio.md +368 -0
- package/docs/components/select-faceted.md +451 -0
- package/docs/components/select.md +926 -0
- package/docs/components/slider.md +147 -0
- package/docs/components/switch.md +198 -0
- package/docs/components/tabs.md +471 -0
- package/docs/components/tag.md +185 -0
- package/docs/components/text.md +148 -0
- package/docs/components/title.md +146 -0
- package/docs/components/toaster.md +313 -0
- package/docs/components/tooltip.md +177 -0
- package/docs/credits.md +18 -0
- package/docs/index.md +52 -0
- package/docs/install-config.md +240 -0
- package/docs/normalization.md +102 -0
- package/docs/overview.md +10 -0
- package/docs/packages/stickers.md +187 -0
- package/docs/packages/table.md +153 -0
- package/docs/theming.md +13 -0
- package/package.json +10 -6
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# InputAutocomplete
|
|
2
|
+
|
|
3
|
+
`InputAutocomplete` is a text field with a suggestion list. Its value remains a
|
|
4
|
+
free-form string: text that is not in the list stays in the field, and selecting
|
|
5
|
+
a suggestion fills the field. Use [Select](./select.md) with `filter` when the
|
|
6
|
+
value must be one of the options.
|
|
7
|
+
|
|
8
|
+
InputAutocomplete uses an [Input](./input.md) for the field and a [Menu](./menu.md)
|
|
9
|
+
for suggestions. **`onValueChange`** reports field text. `onSelect` runs only
|
|
10
|
+
after someone chooses a suggestion. Use `value` to control it, or `defaultValue`
|
|
11
|
+
for uncontrolled use.
|
|
12
|
+
|
|
13
|
+
## Free text is the point
|
|
14
|
+
|
|
15
|
+
The value is always the text in the field. That's what separates this from a
|
|
16
|
+
[Select](./select.md): a Select constrains the value to one of its options, so a Select
|
|
17
|
+
with `filter` already covers "search a fixed list". `InputAutocomplete` is for when
|
|
18
|
+
the list only *suggests* and the user may commit something you didn't list.
|
|
19
|
+
|
|
20
|
+
The keyboard follows that intent. No suggestion is highlighted as you type, so
|
|
21
|
+
Enter commits the typed text and closes the list. ↓ highlights
|
|
22
|
+
the first suggestion (then ↑/↓ move through them), and
|
|
23
|
+
Enter on a highlighted row picks it. Esc or an outside click
|
|
24
|
+
closes the list; clicking the field to place the caret keeps it open.
|
|
25
|
+
|
|
26
|
+
## Filtering
|
|
27
|
+
|
|
28
|
+
`filter` decides how suggestions match the text:
|
|
29
|
+
|
|
30
|
+
- **`true`** (default): built-in case-insensitive substring match on each option's
|
|
31
|
+
`value` / `label` / `hint`.
|
|
32
|
+
- **a function** `(option, query) => boolean`: a custom matcher, called for each option.
|
|
33
|
+
- **`false`**: show `suggestions` as-is, doing no local filtering. Use this when you
|
|
34
|
+
fetch or filter results yourself (async / remote) and feed the current set through
|
|
35
|
+
`suggestions`.
|
|
36
|
+
|
|
37
|
+
Suggestions are bare strings or `SelectOption`s, the same option shape
|
|
38
|
+
[Select](./select.md) uses: `value`, `label`, `hint`, `icon`, `tone`, `disabled`.
|
|
39
|
+
|
|
40
|
+
### Props
|
|
41
|
+
|
|
42
|
+
| Prop | Type | Default | Description |
|
|
43
|
+
|------|------|---------|-------------|
|
|
44
|
+
| `suggestions` | string \| SelectOption[] | — | The suggestions: bare strings or `SelectOption`s (`value` / `label` / `hint` /
|
|
45
|
+
`icon` / `tone` / `disabled`). A flat list; picking one fills the field. |
|
|
46
|
+
| `clearable?` | boolean | — | Show a clear button while the field has text. |
|
|
47
|
+
| `defaultValue?` | string | — | Initial value for uncontrolled use. |
|
|
48
|
+
| `disabled?` | boolean | — | Disable the field. |
|
|
49
|
+
| `filter?` | boolean \| (option, query) => boolean | true | How suggestions match the text. `true` uses the built-in case-insensitive
|
|
50
|
+
substring match on `value` / `label` / `hint`; a function `(option, query) =>
|
|
51
|
+
boolean` uses a custom matcher; `false` shows `suggestions` unchanged for
|
|
52
|
+
application-provided async or remote filtering. |
|
|
53
|
+
| `hint?` | ReactNode | — | Hint under the field. |
|
|
54
|
+
| `label?` | ReactNode | — | Field label. |
|
|
55
|
+
| `leading?` | ReactNode | — | Leading adornment inside the field. |
|
|
56
|
+
| `name?` | string | — | Form field name. |
|
|
57
|
+
| `onSelect?` | (option) => void | — | Fires only when a suggestion is chosen, with that option. |
|
|
58
|
+
| `onValueChange?` | (value) => void | — | Fires as the text changes (typing, picking a suggestion, or clearing) with
|
|
59
|
+
the new field text. |
|
|
60
|
+
| `placeholder?` | string | — | Placeholder text. |
|
|
61
|
+
| `size?` | 'small' \| 'medium' \| 'large' | medium | Field size. |
|
|
62
|
+
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | — | Validation status. |
|
|
63
|
+
| `statusIcon?` | (string & {}) \| false \| IconShape | — | Status icon override, or `false` to drop it. |
|
|
64
|
+
| `tone?` | string | — | Custom accent color — a named tone or any CSS color. |
|
|
65
|
+
| `trailing?` | ReactNode | — | Trailing adornment inside the field. |
|
|
66
|
+
| `value?` | string | — | Controlled value: the field's text, a **free** string not constrained to a
|
|
67
|
+
suggestion. Leave undefined for uncontrolled. |
|
|
68
|
+
|
|
69
|
+
`InputAutocomplete` combines an input with a Menu. Reproducing its filtering,
|
|
70
|
+
selection, focus, and popup coordination without the React or Preact wrapper is
|
|
71
|
+
a substantial amount of code.
|
|
72
|
+
|
|
73
|
+
### Native HTML input with autocomplete
|
|
74
|
+
|
|
75
|
+
For browser-native suggestions, pair a native input with a `<datalist>`. It
|
|
76
|
+
keeps free-form entry and lets the browser filter and fill matching options,
|
|
77
|
+
while `data-anta` supplies the field appearance.
|
|
78
|
+
|
|
79
|
+
The browser renders the suggestions popup. Use `InputAutocomplete` for custom
|
|
80
|
+
option content, popup styling, or consistent behavior across browsers.
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<input data-anta type="text" list="people" placeholder="Search people">
|
|
84
|
+
|
|
85
|
+
<datalist id="people">
|
|
86
|
+
<option value="Maya Chen">
|
|
87
|
+
<option value="Noah Williams">
|
|
88
|
+
<option value="Olivia Martinez">
|
|
89
|
+
<option value="Liam Johnson">
|
|
90
|
+
</datalist>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**The field** is styled through Input's props (`size`, `status`, `tone`, `round`,
|
|
94
|
+
`leading` / `trailing`) and its `::part`s; set its width with `style` / `className`
|
|
95
|
+
(forwarded to the field). **The suggestion popover** takes Menu's `::part(menu)`.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// Give the field a width; tint it with a custom tone.
|
|
99
|
+
<InputAutocomplete tone="info" style={{ width: '260px' }} suggestions={frameworks} />
|
|
100
|
+
```
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# InputDate
|
|
2
|
+
|
|
3
|
+
**`InputDate`** is a date field that replaces the native `type="date"` (and, with
|
|
4
|
+
`time`, `type="datetime-local"`): a text field you can type into, backed by a
|
|
5
|
+
`Calendar` that opens when you click the field (or press ↓), marked by a
|
|
6
|
+
leading calendar icon. `Calendar`, the month grid it builds on, is documented lower
|
|
7
|
+
down.
|
|
8
|
+
|
|
9
|
+
The field accepts free text and resolves it on commit (blur / Enter): a lenient
|
|
10
|
+
parser reads the locale's order (`06/07/2026` is June 7 in en-US, July 6 in de-DE),
|
|
11
|
+
month names, and run-together digits, then rewrites the entry to the canonical
|
|
12
|
+
format. An unrecognized entry marks the field until you fix it. The value is an ISO
|
|
13
|
+
`YYYY-MM-DD` string, never a `Date`; it works controlled (`value` + `onValueChange`)
|
|
14
|
+
or uncontrolled (`defaultValue`), and submits under `name`.
|
|
15
|
+
|
|
16
|
+
## The date field
|
|
17
|
+
|
|
18
|
+
Type a date and it resolves on blur or Enter, or click the field to open
|
|
19
|
+
the calendar and pick a day. Either way the field settles on the locale's canonical
|
|
20
|
+
format and the value is ISO `YYYY-MM-DD`. A click keeps focus in the field, so you
|
|
21
|
+
can keep typing or click a day; ↓ opens the calendar and moves focus into
|
|
22
|
+
the grid, and Esc closes it back to the field. While you type, the calendar
|
|
23
|
+
previews the entry — it jumps to that month and highlights the day — and commits it on
|
|
24
|
+
Enter (which also closes the calendar); an unrecognized entry keeps the
|
|
25
|
+
calendar open and marks the field.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<InputDate label="Due date" defaultValue="2026-06-15" onValueChange={(v) => save(v)} />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The placeholder shows the locale's format, and parsing follows the same order, so
|
|
32
|
+
`de-DE` reads and writes `TT.MM.JJJJ` while `en-US` uses `MM/DD/YYYY`. `min` / `max`
|
|
33
|
+
bound both the calendar and what a typed date will accept.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<InputDate label="US English" locale="en-US" defaultValue="2026-06-15" />
|
|
37
|
+
<InputDate label="German" locale="de-DE" defaultValue="2026-06-15" />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`time` turns it into a date-time field (value `YYYY-MM-DDTHH:mm`). The menu grows a
|
|
41
|
+
time row under the calendar: an [`InputTime`](./input-time.md) (segmented hour / minute,
|
|
42
|
+
plus AM/PM in 12-hour locales) and a confirm (✓) button. Picking a day keeps the menu
|
|
43
|
+
open so you can set the time. The clock follows the locale (`en-US` is 12-hour, most
|
|
44
|
+
others 24), overridable with `hour12`. The field parses a trailing time after a space
|
|
45
|
+
(`06/15/2026 2:30pm` or `… 14:30`), and typing a 24-hour hour into the 12-hour time
|
|
46
|
+
field converts it (18 → 6 PM).
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
{/* `size` scales the calendar, the time inputs, the AM/PM toggle, and the buttons together. */}
|
|
50
|
+
<InputDate size="small" label="Small" time defaultValue="2026-06-15T09:00" />
|
|
51
|
+
<InputDate size="medium" label="Medium" time defaultValue="2026-06-15T09:00" />
|
|
52
|
+
<InputDate size="large" label="Large" time defaultValue="2026-06-15T09:00" />
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Prop | Type | Default | Description |
|
|
56
|
+
|------|------|---------|-------------|
|
|
57
|
+
| `clearable?` | boolean | — | Show a clear button once the field has a value. |
|
|
58
|
+
| `defaultValue?` | string | — | Initial value for the uncontrolled case. |
|
|
59
|
+
| `disabled?` | boolean | — | Disable the field and the calendar. |
|
|
60
|
+
| `hint?` | ReactNode | — | Helper text under the field. Replaced by a format hint while the entry is
|
|
61
|
+
unrecognized. |
|
|
62
|
+
| `hour12?` | boolean | — | Force the time cycle when `time` is on: `true` for 12-hour (AM/PM), `false`
|
|
63
|
+
for 24-hour. Omit to follow the locale (`en-US` → 12-hour, most others → 24). |
|
|
64
|
+
| `icon?` | false \| IconShape | calendar-days | Leading icon at the start of the field — the calendar affordance. Pass
|
|
65
|
+
another shape to change it, or `false` to drop it. |
|
|
66
|
+
| `label?` | ReactNode | — | Field label, above the control. |
|
|
67
|
+
| `locale?` | string | navigator.language | BCP-47 locale driving the display format, the placeholder mask, parsing order,
|
|
68
|
+
and the calendar. |
|
|
69
|
+
| `max?` | string | — | Latest selectable date (ISO). |
|
|
70
|
+
| `min?` | string | — | Earliest selectable date (ISO). Earlier days disable, and a typed date before
|
|
71
|
+
it stays uncommitted. |
|
|
72
|
+
| `name?` | string | — | Form field name — the ISO value submits under this key. |
|
|
73
|
+
| `offset?` | number | 4 | Gap in pixels between the field and the calendar menu. |
|
|
74
|
+
| `onValueChange?` | (value, attrs) => void | — | Fired after the value resolves (a recognized entry, a calendar pick, a time
|
|
75
|
+
change, or a clear), with the new ISO value (`''` when cleared) and a
|
|
76
|
+
`{ value, name }` snapshot. An unrecognized entry does not fire it. |
|
|
77
|
+
| `placeholder?` | string | the locale's format mask (e.g. `MM/DD/YYYY`, `MM/DD/YYYY HH:MM` with `time`) | Placeholder shown when empty. |
|
|
78
|
+
| `placement?` | 'left' \| 'right' \| 'bottom' \| 'top' \| 'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end' \| 'right-start' \| 'right-end' \| 'left-start' \| 'left-end' | bottom-start | Preferred placement of the calendar menu relative to the field. Same values as
|
|
79
|
+
`Menu`; it auto-flips and clamps when space runs out. |
|
|
80
|
+
| `round?` | boolean \| number \| string | — | Round the field corners — `true` for fully round, or a number / CSS length. |
|
|
81
|
+
| `size?` | 'small' \| 'medium' \| 'large' | medium | Field size. Also sizes the calendar and the time row. |
|
|
82
|
+
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | neutral | Validation/feedback tone. An unrecognized entry forces `critical` until fixed. |
|
|
83
|
+
| `time?` | boolean | — | Include a time. The value becomes ISO `YYYY-MM-DDTHH:mm`, the field parses a
|
|
84
|
+
trailing time after a space (`06/15/2026 14:30`, `… 2:30pm`), and the menu
|
|
85
|
+
shows a time row (hours : minutes, an AM/PM toggle in 12-hour locales, then a
|
|
86
|
+
Done button) under the calendar. Picking a day keeps the menu open so you can
|
|
87
|
+
set the time. |
|
|
88
|
+
| `value?` | string | — | Controlled value — ISO `YYYY-MM-DD` (or `YYYY-MM-DDTHH:mm` with `time`), `''`
|
|
89
|
+
for empty. Pair with `onValueChange`; the field and calendar follow it and a
|
|
90
|
+
pick only *requests* a change. |
|
|
91
|
+
|
|
92
|
+
## Calendar
|
|
93
|
+
|
|
94
|
+
The sections below document `Calendar`, the month grid `InputDate` opens. Reach for
|
|
95
|
+
it directly when you want the grid inline, without a field.
|
|
96
|
+
|
|
97
|
+
`Calendar` uses Anta components in light DOM; it has no hidden shadow-root UI.
|
|
98
|
+
The day cells and previous/next chevrons are `<Button>`s inside a
|
|
99
|
+
form-associated `<a-calendar>` grid. Date calculations use the
|
|
100
|
+
[Temporal API](https://tc39.es/proposal-temporal/docs/) through
|
|
101
|
+
`temporal-polyfill`.
|
|
102
|
+
|
|
103
|
+
For a raw grid, import `buildMonth` from `@antadesign/anta`. It returns
|
|
104
|
+
localized weekday headers and day records with ISO values, accessible labels,
|
|
105
|
+
and selected, disabled, today, and outside-month state. It does not manage
|
|
106
|
+
navigation, roving focus, selection, or rendering. The value is an ISO
|
|
107
|
+
`YYYY-MM-DD` string, never a `Date`. Use `value` with `onStateChange` to
|
|
108
|
+
control it, or `defaultValue` for uncontrolled use. It participates in forms
|
|
109
|
+
under `name`.
|
|
110
|
+
|
|
111
|
+
**Not SSR-safe.** `Calendar` (and `InputDate`, which embeds it) reads the current
|
|
112
|
+
date (`Temporal.Now`) and locale (`navigator.language`) at render, so a server
|
|
113
|
+
render disagrees with the client on the highlighted "today" and on localized
|
|
114
|
+
labels, and the page hydrates with a mismatch. Render it client-side only: Astro
|
|
115
|
+
`client:only`, or a dynamic import inside `useEffect`. Every demo on this page uses
|
|
116
|
+
`client:only` for that reason.
|
|
117
|
+
|
|
118
|
+
## Selecting a date
|
|
119
|
+
|
|
120
|
+
Click a day, or focus the grid and press Enter / Space. The
|
|
121
|
+
selected day takes the tertiary-button selected look toned brand — a brand-tinted
|
|
122
|
+
filled cell with a ring. Today shows as a secondary Button, a resting fill.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<Calendar defaultValue="2026-06-12" />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Size
|
|
129
|
+
|
|
130
|
+
`size` scales the whole calendar: the day cells, the prev/next chevrons, and the
|
|
131
|
+
weekday and month-heading type. It follows Button's `small` / `medium` (default) /
|
|
132
|
+
`large` scale, with day-cell heights of 24 / 28 / 32px.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<Calendar size="small" defaultValue="2026-06-28" />
|
|
136
|
+
<Calendar defaultValue="2026-06-28" /> {/* medium (default) */}
|
|
137
|
+
<Calendar size="large" defaultValue="2026-06-28" />
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Range
|
|
141
|
+
|
|
142
|
+
`min` and `max` (ISO strings) bound the selectable range. Days outside it render
|
|
143
|
+
disabled and skip keyboard focus, and the prev/next arrows stop at the range edge.
|
|
144
|
+
The jump menu adapts to how far the range reaches.
|
|
145
|
+
|
|
146
|
+
No `min` / `max`: the jump menu lists today ±3 years, each a submenu of its months.
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Calendar size="small" defaultValue="2026-06-15" />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
A range across years lists each year (here 2026 and 2027) as a submenu of months.
|
|
153
|
+
June 2026 disables days 1–7, and the back arrow stops at the range's start.
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
<Calendar size="small" defaultValue="2026-06-15" min="2026-06-08" max="2027-06-24" />
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
A range inside one year skips the year level and lists months directly, March
|
|
160
|
+
through November enabled and the rest disabled.
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<Calendar size="small" defaultValue="2026-06-15" min="2026-03-01" max="2026-11-30" />
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A range inside one month leaves nowhere to jump. Both arrows and the month/year
|
|
167
|
+
button are disabled, and only the in-range days stay selectable.
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
<Calendar size="small" defaultValue="2026-06-15" min="2026-06-08" max="2026-06-24" />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Locale
|
|
174
|
+
|
|
175
|
+
`Calendar` respects the browser locale by default (`navigator.language`). Pass a
|
|
176
|
+
BCP-47 `locale` to override it: the first day of week comes from the locale's week
|
|
177
|
+
info (never hard-coded to Sunday), and the weekday and month names are localized.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
<Calendar defaultValue="2026-06-28" locale="en-US" /> {/* week starts Sunday */}
|
|
181
|
+
<Calendar defaultValue="2026-06-28" locale="fr-FR" /> {/* week starts Monday */}
|
|
182
|
+
<Calendar defaultValue="2026-06-28" locale="ja-JP" />
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Controlled
|
|
186
|
+
|
|
187
|
+
Uncontrolled by default: pass `defaultValue` and read the date from `onValueChange`
|
|
188
|
+
or at form submit. Make it controlled with `value` + `onStateChange` to drive it
|
|
189
|
+
from your store. The grid then follows `value`, and a pick only *requests* a change:
|
|
190
|
+
answer by updating `value`, reject by doing nothing.
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
const [date, setDate] = useState('2026-06-28')
|
|
194
|
+
|
|
195
|
+
<Calendar
|
|
196
|
+
value={date}
|
|
197
|
+
onStateChange={(_e, { next }) => setDate(next ?? '')}
|
|
198
|
+
/>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`onStateChange` fires before the element applies, with `(event, { next, prev, reason })`
|
|
202
|
+
where `next` / `prev` are ISO strings. For a `'user'` pick, `event.preventDefault()`
|
|
203
|
+
vetoes it (uncontrolled). A controlled calendar with no `onStateChange` is read-only.
|
|
204
|
+
|
|
205
|
+
## Disabled
|
|
206
|
+
|
|
207
|
+
`disabled` dims the whole calendar and removes it from interaction.
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
<Calendar defaultValue="2026-06-28" disabled />
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Forms
|
|
214
|
+
|
|
215
|
+
`Calendar` is form-associated. Give it a `name` and it submits the selected ISO
|
|
216
|
+
date under that key, resets to `defaultValue` on form reset, and reports through
|
|
217
|
+
the standard constraint-validation pipeline.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
<form>
|
|
221
|
+
<Calendar name="due-date" defaultValue="2026-06-28" />
|
|
222
|
+
</form>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Accessibility
|
|
226
|
+
|
|
227
|
+
The calendar is a labelled **group** of day buttons, a flat grid rather than a
|
|
228
|
+
nested `grid`/`row`/`gridcell` tree. The group is named by the visible month
|
|
229
|
+
(`aria-labelledby`). Each day is a `<button>` whose `aria-label` is its full date
|
|
230
|
+
including weekday ("Sunday, June 28, 2026"), with `aria-pressed` on the selected day
|
|
231
|
+
and `aria-current="date"` on today. The decorative weekday headers are `aria-hidden`,
|
|
232
|
+
since each day already names its weekday. A roving `tabindex` keeps a single tab
|
|
233
|
+
stop, and an `aria-live` region announces the month when it changes.
|
|
234
|
+
|
|
235
|
+
| Key | Moves focus |
|
|
236
|
+
|---|---|
|
|
237
|
+
| ← / → | by one day |
|
|
238
|
+
| ↑ / ↓ | by one week |
|
|
239
|
+
| Home / End | to the start / end of the week |
|
|
240
|
+
| PageUp / PageDown | by one month |
|
|
241
|
+
| Shift + PageUp / PageDown | by one year |
|
|
242
|
+
| Enter / Space | select the focused day |
|
|
243
|
+
|
|
244
|
+
## Customization
|
|
245
|
+
|
|
246
|
+
`InputDate` uses Input, Menu, and Calendar. Calendar uses an `<a-calendar>`
|
|
247
|
+
element for the day grid and a JSX wrapper for navigation. The sections below
|
|
248
|
+
describe which layer provides each behavior and how to recreate the interface
|
|
249
|
+
without React.
|
|
250
|
+
|
|
251
|
+
### Build it from elements
|
|
252
|
+
|
|
253
|
+
`InputDate` has no `a-inputdate` element. Its wrapper renders an editable
|
|
254
|
+
`<Input>` and a `<Menu>` containing a `<Calendar>`. When `time` is set, the
|
|
255
|
+
hour/minute fields and AM/PM `Tabs` appear below the grid. The wrapper manages
|
|
256
|
+
draft text, parsing on commit, and the ISO value.
|
|
257
|
+
|
|
258
|
+
Clicking the field opens the menu while keeping focus in the field. Pressing
|
|
259
|
+
↓ opens the menu and moves focus to the grid. The wrapper passes a
|
|
260
|
+
`focusSignal` to Calendar, which renders `data-focus`; `<a-calendar>` then
|
|
261
|
+
focuses the active day. Calendar and Tabs emit their own `statechange` events,
|
|
262
|
+
but Menu responds only to changes in its own open state.
|
|
263
|
+
|
|
264
|
+
The `<a-calendar>` element provides grid behavior. It connects the supplied day
|
|
265
|
+
`<button>`s to click and keyboard navigation, including arrows, Home,
|
|
266
|
+
End, PageUp, and PageDown. It stores the form
|
|
267
|
+
value through `ElementInternals` and emits `statechange` / `change` on selection
|
|
268
|
+
and `navigate` when keyboard navigation leaves the displayed month. It is
|
|
269
|
+
framework-agnostic and does not track a current month, `min`, or `max`.
|
|
270
|
+
|
|
271
|
+
The JSX wrapper renders the controls above the grid as siblings of
|
|
272
|
+
`<a-calendar>`. The previous/next arrows are `<Button>`s. The month/year picker
|
|
273
|
+
is a `<Button>` that opens a `<Menu>` of year `MenuItem`s, each with a month
|
|
274
|
+
submenu. The wrapper stores the displayed-month cursor in state and derives day
|
|
275
|
+
cells and the arrows' `disabled` states from `min` and `max`. A click on an
|
|
276
|
+
arrow, a menu selection, or a `navigate` event updates the cursor and re-renders
|
|
277
|
+
the grid. The wrapper enforces the range. The element only ignores a day that
|
|
278
|
+
was rendered with `disabled`.
|
|
279
|
+
|
|
280
|
+
The element has no `min` or `max` because the wrapper provides the surrounding
|
|
281
|
+
controls. Without React, render the grid with `buildMonth` and add the
|
|
282
|
+
navigation behavior shown below:
|
|
283
|
+
|
|
284
|
+
```html
|
|
285
|
+
<!-- `.calendar` scopes this example. Use an application selector instead. -->
|
|
286
|
+
<div class="calendar" style="display: inline-flex; flex-direction: column; gap: 6px">
|
|
287
|
+
<div style="display: flex; align-items: center">
|
|
288
|
+
<a-button priority="tertiary" data-prev aria-label="Previous month"><a-icon shape="chevron-left"></a-icon></a-button>
|
|
289
|
+
<a-button priority="tertiary" data-heading style="flex: 1; justify-content: center" aria-haspopup="menu"></a-button>
|
|
290
|
+
<a-button priority="tertiary" data-next aria-label="Next month"><a-icon shape="chevron-right"></a-icon></a-button>
|
|
291
|
+
</div>
|
|
292
|
+
<!-- The element provides selection, keyboard behavior, form value, and events. -->
|
|
293
|
+
<a-calendar role="group" name="date"></a-calendar>
|
|
294
|
+
</div>
|
|
295
|
+
<script type="module">
|
|
296
|
+
import '@antadesign/anta/elements'
|
|
297
|
+
import { buildMonth, parseISODate } from '@antadesign/anta'
|
|
298
|
+
import { Temporal } from 'temporal-polyfill'
|
|
299
|
+
|
|
300
|
+
const root = document.querySelector('.calendar')
|
|
301
|
+
const grid = root.querySelector('a-calendar')
|
|
302
|
+
const heading = root.querySelector('[data-heading]')
|
|
303
|
+
let cursor = Temporal.Now.plainDateISO()
|
|
304
|
+
|
|
305
|
+
function render() {
|
|
306
|
+
const m = buildMonth({ anchor: cursor, locale: navigator.language })
|
|
307
|
+
heading.textContent = m.heading
|
|
308
|
+
grid.replaceChildren()
|
|
309
|
+
for (const w of m.weekdays) {
|
|
310
|
+
const s = Object.assign(document.createElement('span'), { textContent: w.narrow })
|
|
311
|
+
s.setAttribute('data-part', 'weekday')
|
|
312
|
+
s.setAttribute('aria-hidden', 'true')
|
|
313
|
+
grid.append(s)
|
|
314
|
+
}
|
|
315
|
+
for (const d of m.weeks.flat()) {
|
|
316
|
+
const b = Object.assign(document.createElement('a-button'), { textContent: String(d.day) })
|
|
317
|
+
b.setAttribute('priority', 'tertiary')
|
|
318
|
+
b.setAttribute('data-part', 'day-cell')
|
|
319
|
+
b.setAttribute('data-date', d.iso) // the element keys off this
|
|
320
|
+
b.tabIndex = d.iso === cursor.toString() ? 0 : -1
|
|
321
|
+
if (d.selected) b.setAttribute('selected', '')
|
|
322
|
+
if (d.disabled) b.setAttribute('disabled', '')
|
|
323
|
+
grid.append(b)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
root.querySelector('[data-prev]').addEventListener('click', () => { cursor = cursor.subtract({ months: 1 }); render() })
|
|
328
|
+
root.querySelector('[data-next]').addEventListener('click', () => { cursor = cursor.add({ months: 1 }); render() })
|
|
329
|
+
// Keyboard paging past the rendered grid: the element asks for a month flip.
|
|
330
|
+
grid.addEventListener('navigate', (e) => { cursor = parseISODate(e.detail.date) ?? cursor; render() })
|
|
331
|
+
render()
|
|
332
|
+
</script>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Tracking the cursor, painting the grid from `buildMonth`, and re-rendering on
|
|
336
|
+
`navigate` is what the React `Calendar` packages, plus the year/month jump menu,
|
|
337
|
+
which uses the same `Menu` composition shown on the [Menu](./menu.md) page.
|
|
338
|
+
|
|
339
|
+
`InputDate` has no host element. Rebuilding its text parsing, dropdown calendar,
|
|
340
|
+
localized day grid, month navigation, keyboard navigation, and focus management
|
|
341
|
+
in vanilla JavaScript is significant work, even with Anta's `buildMonth` and
|
|
342
|
+
`parseISODate` helpers. Use the `InputDate` wrapper when React or Preact is an
|
|
343
|
+
option. Otherwise, a native HTML date input is the practical baseline.
|
|
344
|
+
|
|
345
|
+
### Native HTML date input
|
|
346
|
+
|
|
347
|
+
Add `data-anta` to a `date`, `datetime-local`, `month`, `time`, or `week` input.
|
|
348
|
+
Nothing else is required: Anta styles the field while the browser keeps its picker,
|
|
349
|
+
icon, validation, and keyboard model. The picker itself and its date/time
|
|
350
|
+
formatting remain browser- and OS-owned.
|
|
351
|
+
|
|
352
|
+
`data-anta-size`, `round`, and a custom-color `tone` use the matching Input
|
|
353
|
+
field treatments.
|
|
354
|
+
|
|
355
|
+
```html
|
|
356
|
+
<!-- `data-anta` styles the field, not the native picker. -->
|
|
357
|
+
<input data-anta type="date" name="due-date" value="2026-06-15">
|
|
358
|
+
<input data-anta type="datetime-local" name="starts-at" value="2026-06-15T09:00">
|
|
359
|
+
<input data-anta type="month" name="billing-month" value="2026-06">
|
|
360
|
+
<input data-anta type="time" name="reminder-at" value="09:00">
|
|
361
|
+
<input data-anta type="week" name="sprint-week" value="2026-W25">
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
The calendar is **light DOM**, so everything is plain CSS, with no shadow parts or
|
|
365
|
+
hidden internals. The days and chevrons are real `<a-button>`s, so their colors,
|
|
366
|
+
hover, focus ring, and selected look come from the Button styles and theme
|
|
367
|
+
themselves; they sit inside the `<a-calendar>` grid, and the switcher header sits in
|
|
368
|
+
the `.anta-calendar` shell. An un-layered consumer rule beats `@layer anta` without
|
|
369
|
+
`!important`. The class below is for the demo.
|
|
370
|
+
|
|
371
|
+
```css
|
|
372
|
+
/* Bigger, circular day cells. `className` lands on the outer .anta-calendar
|
|
373
|
+
shell; `--calendar-cell-width` / `--calendar-cell-height` drive the grid track
|
|
374
|
+
and the cell box (inherited down), and you target the day Buttons directly. */
|
|
375
|
+
.anta-calendar.roomy { --calendar-cell-width: 40px; --calendar-cell-height: 40px; }
|
|
376
|
+
.anta-calendar.roomy a-button[data-part="day-cell"] { border-radius: 50%; }
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Each day is a `<a-button data-part="day-cell" data-date="YYYY-MM-DD">`, so a
|
|
380
|
+
specific date is addressable by its `data-date`: tint it, or hang an event marker
|
|
381
|
+
off a `::after` (give the cell `position: relative` first). Below, three days carry a
|
|
382
|
+
brand dot and one is flagged in the critical color.
|
|
383
|
+
|
|
384
|
+
```css
|
|
385
|
+
/* Day cells are `<a-button data-part="day-cell" data-date="YYYY-MM-DD">`. Give them a
|
|
386
|
+
positioning context, dot event days with a `::after`, and tint a date's text. */
|
|
387
|
+
.anta-calendar.events a-button[data-part="day-cell"] { position: relative; }
|
|
388
|
+
.anta-calendar.events a-button[data-part="day-cell"]:is(
|
|
389
|
+
[data-date="2026-06-05"], [data-date="2026-06-12"], [data-date="2026-06-20"]
|
|
390
|
+
)::after {
|
|
391
|
+
content: ""; position: absolute; inset-block-end: 3px; inset-inline-start: 50%;
|
|
392
|
+
inline-size: 4px; block-size: 4px; transform: translateX(-50%);
|
|
393
|
+
border-radius: 999px; background: var(--text-2-brand);
|
|
394
|
+
}
|
|
395
|
+
.anta-calendar.events a-button[data-part="day-cell"][data-date="2026-06-25"] {
|
|
396
|
+
color: var(--text-2-critical); font-weight: 600;
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
The engine (`buildMonth`, `firstDayOfWeek`, …) is exported, so you can render a
|
|
401
|
+
fully custom grid and keep only the `<a-calendar>` form plumbing.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# InputTime
|
|
2
|
+
|
|
3
|
+
**`InputTime`** is a segmented wall-clock field: one boxed input, like the others,
|
|
4
|
+
holding separate **hour** and **minute** sections — plus an **AM/PM** section in
|
|
5
|
+
12-hour locales — that behave as a single control. Each section is a native text
|
|
6
|
+
input:
|
|
7
|
+
↑/↓ steps its value (wrapping 59 → 00), ←/→
|
|
8
|
+
moves between sections at the caret boundary, and typing a digit fills the section
|
|
9
|
+
and advances to the next once it can't hold more. AM/PM accepts its locale text or
|
|
10
|
+
`a` / `p`.
|
|
11
|
+
|
|
12
|
+
A leading clock icon marks the affordance (change it with `icon`). Unlike a text
|
|
13
|
+
`Input` (which fills its container), the field **sizes to its content** — a time
|
|
14
|
+
is a small, fixed control — so set a `width` (e.g. `style={{ width: '100%' }}`) if
|
|
15
|
+
you want it to fill. The value is a 24-hour `"HH:mm"` string (`''` until both hour
|
|
16
|
+
and minute are set), never a `Date`. It works controlled (`value` + `onValueChange`)
|
|
17
|
+
or uncontrolled (`defaultValue`), and submits under `name` via the native form APIs.
|
|
18
|
+
|
|
19
|
+
## The field
|
|
20
|
+
|
|
21
|
+
Focus a section and edit it with the keyboard: ↑/↓ to step (it
|
|
22
|
+
wraps), PageUp/PageDown for a larger jump on minutes,
|
|
23
|
+
or enter the digits. Home/End, selection, deletion, and
|
|
24
|
+
paste behave as they do in a native text input. Typing
|
|
25
|
+
`9` then `3` `0` lands `09:30` and moves across the sections on its own; an
|
|
26
|
+
out-of-range digit (a `6` in the minutes) commits and advances immediately.
|
|
27
|
+
Backspace on an empty section selects the previous one. The whole thing
|
|
28
|
+
reads as one field while preserving native caret behavior. In a
|
|
29
|
+
12-hour field, typing a 24-hour hour converts it and flips AM/PM — `18` becomes
|
|
30
|
+
`6 PM`, so pasted 24-hour times work.
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<InputTime label="Start time" defaultValue="09:30" onValueChange={(_, { value }) => save(value)} />
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Locale
|
|
37
|
+
|
|
38
|
+
The clock follows the locale: `en-US` shows 12-hour with an AM/PM section, most
|
|
39
|
+
others show 24-hour with none. It's derived from `Intl` (the resolved `hourCycle`),
|
|
40
|
+
and the section **order**, the **separator**, and the **AM/PM text** all come from
|
|
41
|
+
the locale too — Japanese renders the period first (`午後2:05`), Finnish separates
|
|
42
|
+
with a dot (`14.05`), and 24-hour locales drop the AM/PM section entirely. Set
|
|
43
|
+
`hour12` to force one clock regardless of locale.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<InputTime label="US English" locale="en-US" defaultValue="14:05" /> {/* 12-hour: 02 : 05 PM */}
|
|
47
|
+
<InputTime label="German" locale="de-DE" defaultValue="14:05" /> {/* 24-hour: 14 : 05 */}
|
|
48
|
+
<InputTime label="Japanese" locale="ja-JP" hour12 defaultValue="14:05" /> {/* 午後 02:05 — period first */}
|
|
49
|
+
<InputTime label="Force 24h" hour12={false} defaultValue="14:05" />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Size, status, and clearing
|
|
53
|
+
|
|
54
|
+
`size` (`small` / `medium` / `large`) matches the other inputs' scale; `status`
|
|
55
|
+
recolors the box and hint (only `critical` marks it invalid); `clearable` adds a
|
|
56
|
+
clear button once a value is set — clearing empties every section back to the
|
|
57
|
+
placeholder dashes. `disabled` behaves as it does on `Input`.
|
|
58
|
+
|
|
59
|
+
`min` and `max` (24-hour `"HH:mm"`) bound the value: a complete time outside the
|
|
60
|
+
range is clamped to the nearest bound as you step or leave the field, and flags
|
|
61
|
+
`rangeUnderflow` / `rangeOverflow` for form validity in the meantime.
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<InputTime label="Meeting" size="small" defaultValue="10:00" clearable />
|
|
65
|
+
<InputTime label="Deadline" status="critical" hint="Pick a time in the future." />
|
|
66
|
+
<InputTime label="Office hours" size="large" min="09:00" max="17:00" defaultValue="09:30" />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
| Prop | Type | Default | Description |
|
|
70
|
+
|------|------|---------|-------------|
|
|
71
|
+
| `children?` | ReactNode | — | Extra content rendered under the field, above the hint (a no-box child like
|
|
72
|
+
a `<Tooltip>` takes no space and anchors to the field). |
|
|
73
|
+
| `clearable?` | boolean | — | Show a clear button once the field has a value. |
|
|
74
|
+
| `defaultValue?` | string | — | Initial value for the uncontrolled case (24-hour `"HH:mm"`). |
|
|
75
|
+
| `dimActions?` | boolean | — | Dim the trailing adornments at rest; they brighten on hover / focus. |
|
|
76
|
+
| `disabled?` | boolean | — | Disable the field. |
|
|
77
|
+
| `hint?` | ReactNode | — | Message below the field. `status` recolors it and prefixes a glyph. |
|
|
78
|
+
| `hour12?` | boolean | — | Force the clock: `true` = 12-hour (AM/PM), `false` = 24-hour. Omit to follow
|
|
79
|
+
the locale. |
|
|
80
|
+
| `icon?` | false \| IconShape | clock | Leading icon at the start of the field — the clock affordance. Pass another
|
|
81
|
+
shape to change it, or `false` to drop it. |
|
|
82
|
+
| `label?` | ReactNode | — | Field label, shown above the control and used as the segment group's
|
|
83
|
+
accessible name. |
|
|
84
|
+
| `locale?` | string | navigator.language | BCP-47 locale driving the clock (12h vs 24h), segment order, separator, and
|
|
85
|
+
the AM/PM text. |
|
|
86
|
+
| `max?` | string | — | Latest allowed time, 24-hour `"HH:mm"`. A complete value above it is clamped
|
|
87
|
+
down (on step / blur) and flagged `rangeOverflow`. |
|
|
88
|
+
| `min?` | string | — | Earliest allowed time, 24-hour `"HH:mm"`. A complete value below it is
|
|
89
|
+
clamped up (on step / blur) and flagged `rangeUnderflow` for form validity. |
|
|
90
|
+
| `name?` | string | — | Form field name — the 24-hour value submits under this key. |
|
|
91
|
+
| `onBlur?` | (e) => void | — | Fires when the field loses focus. |
|
|
92
|
+
| `onClearInput?` | (e) => void | — | Fires after the built-in clear button has cleared the field. |
|
|
93
|
+
| `onFocus?` | (e) => void | — | Fires when the field gains focus. |
|
|
94
|
+
| `onValueChange?` | (event, attrs) => void | — | Fires on every edit (`input`), with the native event + an `attrs` snapshot
|
|
95
|
+
(`value`, `name`, `empty`, `valid`, `validationMessage`). Also fires on
|
|
96
|
+
`change` (blur) and on clear. |
|
|
97
|
+
| `required?` | boolean | — | Mark the field required (drives native validity). |
|
|
98
|
+
| `round?` | boolean \| number \| string | — | Fully-round the field, or a custom radius (`number` px / CSS length). |
|
|
99
|
+
| `size?` | 'small' \| 'medium' \| 'large' | medium | Size variant. small=24px, medium=28px, large=32px tall. |
|
|
100
|
+
| `status?` | 'neutral' \| 'brand' \| 'info' \| 'success' \| 'warning' \| 'critical' | — | Validation / feedback tone. Only `critical` marks the field invalid; the
|
|
101
|
+
others are advisory. Omit (or `neutral`) for a plain field. |
|
|
102
|
+
| `statusIcon?` | (string & {}) \| false \| IconShape | — | Glyph before the `hint` when `status` is set (per-status default; pass a
|
|
103
|
+
shape to override, or `false` to drop it). |
|
|
104
|
+
| `tone?` | string | — | Custom accent color — any literal CSS color tints the resting + hover
|
|
105
|
+
border (focus ring stays `--focus-ring`); `status` overrides for validation. |
|
|
106
|
+
| `trailing?` | ReactNode | — | Content pinned to the end of the field (after the clear button). |
|
|
107
|
+
| `value?` | string | — | Controlled value — 24-hour `"HH:mm"`. Pair with `onValueChange`. |
|
|
108
|
+
|
|
109
|
+
Use the web component directly when you are not using React or Preact and a native control does not fit.
|
|
110
|
+
|
|
111
|
+
Slots supply the field label and leading icon.
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<a-input-time name="start-time" defaultvalue="09:30">
|
|
115
|
+
<span slot="label">Start time</span>
|
|
116
|
+
<a-icon slot="leading" shape="clock" aria-hidden="true"></a-icon>
|
|
117
|
+
</a-input-time>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Native HTML time input
|
|
121
|
+
|
|
122
|
+
For a form that can use the browser's time picker, add `data-anta` to a regular
|
|
123
|
+
time input. It gives the field Anta's resting chrome while the browser keeps its
|
|
124
|
+
own picker, validation, and keyboard behavior.
|
|
125
|
+
|
|
126
|
+
`data-anta-size`, `round`, and a custom-color `tone` use the matching Input
|
|
127
|
+
field treatments.
|
|
128
|
+
|
|
129
|
+
```html
|
|
130
|
+
<input data-anta type="time" name="reminder-at" value="09:00">
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Styling
|
|
134
|
+
|
|
135
|
+
`InputTime` renders an `<a-input-time>` whose field chrome mirrors `<a-input>`.
|
|
136
|
+
Route feedback color through `status`; everything else is reachable as plain CSS on
|
|
137
|
+
the host or through `::part()`. `segment` targets every editable input. `hour`,
|
|
138
|
+
`minute`, and `period` target one segment type regardless of locale order. `literal`
|
|
139
|
+
targets the localized separator. The element also exposes `field`, `segments`,
|
|
140
|
+
`leading`, `label`, `hint`, `clear`, and `trailing`. Don't override the internal
|
|
141
|
+
`--input-time-*` values directly; they are defaults, not a styling API.
|
|
142
|
+
|
|
143
|
+
```css
|
|
144
|
+
/* Make one field fill its container (the default is content-width). Style all
|
|
145
|
+
editable segments, then keep AM/PM and the locale separator quieter. */
|
|
146
|
+
.my-time { width: 100%; }
|
|
147
|
+
.my-time::part(segments) { color: #e5484d; }
|
|
148
|
+
.my-time::part(period) { color: var(--text-3); }
|
|
149
|
+
.my-time::part(literal) { color: var(--text-4); }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Drop the clock icon with the `icon={false}` prop, and point the `segments` part at
|
|
153
|
+
a monospaced family for fixed-width digits — a small `padding-top` re-centers the
|
|
154
|
+
tighter `1em` line:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<InputTime icon={false} className="plain-time" defaultValue="09:30" />
|
|
158
|
+
|
|
159
|
+
<style>{`
|
|
160
|
+
.plain-time::part(segments) {
|
|
161
|
+
font-family: var(--monospace, ui-monospace, monospace);
|
|
162
|
+
line-height: 1em;
|
|
163
|
+
padding-top: 2px;
|
|
164
|
+
}
|
|
165
|
+
`}</style>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
For a one-off accent, `tone` takes **any literal CSS color** (e.g. `#7c3aed`) and
|
|
169
|
+
tints the resting + hover border — the focus ring stays the global ring. It's a
|
|
170
|
+
color, not a named tone; the named feedback tones live on `status`.
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<InputTime label="Accent" tone="#7c3aed" defaultValue="09:30" />
|
|
174
|
+
```
|