@antadesign/anta 0.3.29 → 0.3.31
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/dist/anta_helpers.d.ts +4 -0
- package/dist/anta_helpers.js +11 -1
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +39 -30
- package/dist/components/Breadcrumbs.d.ts +1 -1
- package/dist/components/Button.d.ts +3 -3
- package/dist/components/ButtonCopy.d.ts +1 -1
- package/dist/components/InputDate.js +2 -0
- package/dist/components/MenuItem.d.ts +9 -7
- package/dist/components/MenuItem.js +21 -2
- package/dist/components/Text.js +2 -3
- package/dist/components/Title.d.ts +8 -2
- package/dist/components/Title.js +17 -6
- package/dist/elements/a-box.js +2 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +5 -2
- package/dist/elements/a-calendar.js +3 -1
- package/dist/elements/a-copy.js +23 -3
- package/dist/elements/a-icon.shapes.d.ts +1 -1
- package/dist/elements/a-input-time.js +4 -3
- package/dist/elements/a-input.js +2 -2
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu.js +3 -0
- package/dist/elements/a-panel.css +1 -1
- package/dist/elements/a-panel.js +1 -1
- package/dist/elements/a-radio-group.js +2 -2
- package/dist/elements/a-slider.js +2 -2
- package/dist/elements/a-tabs.js +2 -2
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-tooltip.js +1 -1
- package/dist/elements/shadow-aria.d.ts +1 -1
- package/dist/general_types.d.ts +4 -0
- package/dist/jsx-runtime.d.ts +10 -0
- package/dist/jsx-runtime.js +12 -0
- package/dist/theme-antune.css +1 -1
- package/dist/toaster.d.ts +1 -1
- package/docs/changelog.md +37 -0
- package/docs/comparison.md +1 -1
- package/docs/components/button.md +127 -381
- package/docs/components/menu.md +37 -15
- package/docs/components/panel.md +5 -6
- package/docs/components/title.md +19 -0
- package/docs/credits.md +3 -0
- package/docs/index.md +1 -0
- package/docs/packages/plot.md +3771 -0
- package/package.json +15 -11
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
# Button
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
size, and state are all plain attributes, so the styling is identical
|
|
6
|
-
whether you use the wrapper or author the element by hand.
|
|
3
|
+
A button starts an action. Use its priority, tone, and size to match the action's
|
|
4
|
+
importance and context.
|
|
7
5
|
|
|
8
6
|
## Priority
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
Use one primary button for the main action in a group. Lower priorities reduce
|
|
9
|
+
visual emphasis.
|
|
11
10
|
|
|
12
11
|
```tsx
|
|
13
|
-
<Button tone="brand" priority="primary"
|
|
14
|
-
<Button tone="brand" priority="secondary"
|
|
15
|
-
<Button tone="brand" priority="tertiary"
|
|
12
|
+
<Button tone="brand" priority="primary" label="Publish" />
|
|
13
|
+
<Button tone="brand" priority="secondary" label="Move" />
|
|
14
|
+
<Button tone="brand" priority="tertiary" label="Cancel" />
|
|
16
15
|
<Button tone="brand" priority="quaternary" label="Remind" />
|
|
17
16
|
```
|
|
18
17
|
|
|
19
|
-
- `primary
|
|
20
|
-
- `secondary
|
|
21
|
-
- `tertiary
|
|
22
|
-
- `quaternary
|
|
18
|
+
- `primary`: main call to action
|
|
19
|
+
- `secondary`: supporting action and the default
|
|
20
|
+
- `tertiary`: low-emphasis action with a hover background
|
|
21
|
+
- `quaternary`: text-only action
|
|
23
22
|
|
|
24
23
|
## Tone
|
|
25
24
|
|
|
26
|
-
Six named tones
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
Six named tones: `neutral` (default), `brand`, `critical`, `info`, `success`,
|
|
26
|
+
and `warning`. Omitting `tone`, or passing an empty string, resolves to
|
|
27
|
+
`neutral`. A custom tone is also possible: pass any literal CSS color and the
|
|
28
|
+
button will adapt to it.
|
|
30
29
|
|
|
31
30
|
```tsx
|
|
32
31
|
<Button label="Save" />
|
|
@@ -37,264 +36,157 @@ literal CSS color and the button will adapt to it.
|
|
|
37
36
|
<Button tone="warning" label="Archive" />
|
|
38
37
|
```
|
|
39
38
|
|
|
39
|
+
### Custom tone
|
|
40
|
+
|
|
41
|
+
Pass any CSS color to `tone`. Custom tones work with every priority and adapt to
|
|
42
|
+
the current color mode.
|
|
43
|
+
|
|
40
44
|
```tsx
|
|
41
|
-
<Button priority="primary"
|
|
45
|
+
<Button priority="primary" tone="#ff1493" label="Pinkify" />
|
|
42
46
|
<Button priority="secondary" tone="oklch(0.655 0.261 356.9)" label="Pinkify" />
|
|
43
|
-
<Button priority="tertiary"
|
|
44
|
-
<Button priority="primary"
|
|
45
|
-
<Button priority="secondary" tone="rgb(102 205 170)"
|
|
46
|
-
<Button priority="tertiary"
|
|
47
|
+
<Button priority="tertiary" tone="hsl(328 100% 54%)" label="Pinkify" />
|
|
48
|
+
<Button priority="primary" tone="mediumaquamarine" label="Mintify" />
|
|
49
|
+
<Button priority="secondary" tone="rgb(102 205 170)" label="Mintify" />
|
|
50
|
+
<Button priority="tertiary" tone="lch(75.7% 39.2 167.8)" label="Mintify" />
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
For custom tones, **primary** keeps the source's hue and chroma but pins
|
|
50
|
-
its *lightness* near the Brand primary's, so any input — too light or too
|
|
51
|
-
dark — still lands at a Brand-like fill (hover / active step the lightness,
|
|
52
|
-
and the label keeps the standard primary text color). **Secondary**,
|
|
53
|
-
**tertiary**, and **quaternary** take only its *hue* — lightness, chroma,
|
|
54
|
-
and alpha come from the brand-tone curve (via `oklch()` relative color), so
|
|
55
|
-
pale or low-chroma inputs (`tone="#cccccc"`, `tone="white"`) still produce a
|
|
56
|
-
legible button. The full priority × state matrix — rest, hover, active,
|
|
57
|
-
secondary alpha overlay, tertiary fill — is derived automatically, and
|
|
58
|
-
re-tunes between light and dark.
|
|
59
|
-
|
|
60
|
-
If you need pixel-precise color, set `--button-fg` or `--button-bg`
|
|
61
|
-
yourself — inline via `style`, or from your own class or selector. The
|
|
62
|
-
resolver lives in `@layer anta`, so any un-layered rule of yours wins
|
|
63
|
-
regardless of specificity (and inline beats everything). The same override
|
|
64
|
-
also pins hover and active to that color — it overrides the per-state rules
|
|
65
|
-
too, so there's no state change; to keep distinct states, set the per-state
|
|
66
|
-
variables instead — `--button-bg-{priority}-hover`,
|
|
67
|
-
`--button-bg-{priority}-active`, and the `--button-fg-*` equivalents.
|
|
68
|
-
|
|
69
53
|
## Size
|
|
70
54
|
|
|
55
|
+
Buttons come in `small`, `medium`, and `large`. `medium` is the default.
|
|
56
|
+
|
|
71
57
|
```tsx
|
|
72
|
-
<Button tone="brand" size="small"
|
|
73
|
-
<Button tone="brand" size="medium" label="Medium" />
|
|
74
|
-
<Button tone="brand" size="large"
|
|
58
|
+
<Button tone="brand" size="small" label="Small" />
|
|
59
|
+
<Button tone="brand" size="medium" label="Medium" />
|
|
60
|
+
<Button tone="brand" size="large" label="Large" />
|
|
75
61
|
```
|
|
76
62
|
|
|
77
|
-
Three sizes (`medium` is default). The **type scale** (font / line-height) and
|
|
78
|
-
the **icon** track the size, matching Anta's text scale and the same-size
|
|
79
|
-
`Input`; the hit area grows or shrinks to match.
|
|
80
|
-
|
|
81
|
-
Height comes from the label's `line-height` plus a uniform 3.5px vertical padding
|
|
82
|
-
and a 1px `padding-bottom` that optically centers Anta's font (its glyphs sit a
|
|
83
|
-
touch low in the line-box) — netting `line-height + 8`, so it lands at
|
|
84
|
-
24 / 28 / 32px without any per-size padding tuning.
|
|
85
|
-
|
|
86
|
-
| size | height | font / line | icon | text-edge `padding-x` | icon-edge `padding-x` |
|
|
87
|
-
|---|---|---|---|---|---|
|
|
88
|
-
| `small` | 24px | 13 / 16 | 14px | 7px | 5px |
|
|
89
|
-
| `medium` (default) | 28px | 15 / 20 | 16px | 9px | 7px |
|
|
90
|
-
| `large` | 32px | 17 / 24 | 18px | 13px | 11px |
|
|
91
|
-
|
|
92
|
-
The **icon-edge** padding is the text-edge value minus 2px — an icon at
|
|
93
|
-
an edge needs less breathing room than a glyph — so only the side a
|
|
94
|
-
(leading or trailing) icon occupies is trimmed; the text side keeps the
|
|
95
|
-
full padding. The gap between an icon and the label is `0.5ch` at every
|
|
96
|
-
size.
|
|
97
|
-
|
|
98
|
-
Need a different font size? Style the `<a-button-label>` directly — set
|
|
99
|
-
its `font-size` and `line-height` (the label's `line-height` drives the
|
|
100
|
-
button's height, so the box follows your value), and (if the text then sits a
|
|
101
|
-
little high) drop the 1px `padding-bottom` that optically centers Anta's font.
|
|
102
|
-
|
|
103
|
-
By default a button packs its content to the start, so when buttons share
|
|
104
|
-
a width — a vertical menu, equal grid cells — their labels line up on a
|
|
105
|
-
common left edge, which usually reads best in a list.
|
|
106
|
-
|
|
107
|
-
To center the label inside a wider button instead, set
|
|
108
|
-
`justify-content: center` on it (the tones grid above does exactly this).
|
|
109
|
-
|
|
110
63
|
### Paddingless
|
|
111
64
|
|
|
65
|
+
Use `paddingless` with a quaternary button when an action should sit flush with
|
|
66
|
+
surrounding text.
|
|
67
|
+
|
|
112
68
|
```tsx
|
|
113
69
|
If you're familiar with the basics, click
|
|
114
70
|
<Button tone="critical" priority="quaternary" paddingless label="here" />
|
|
115
|
-
to skip
|
|
71
|
+
to skip the live demo.
|
|
116
72
|
```
|
|
117
73
|
|
|
118
|
-
Only valid on `priority="quaternary"`. Zeros the outer padding so the
|
|
119
|
-
button sits flush with surrounding prose — useful when you want a
|
|
120
|
-
button to read as an inline link inside a sentence.
|
|
121
|
-
|
|
122
74
|
## Round
|
|
123
75
|
|
|
124
|
-
`round`
|
|
125
|
-
|
|
126
|
-
adapts to every `size` with no configuration. Pass a **number** (px) or a CSS length
|
|
127
|
-
string for a custom radius instead of a full pill.
|
|
76
|
+
Set `round` for a pill or circular icon button. Pass a number or CSS length for
|
|
77
|
+
a custom corner radius.
|
|
128
78
|
|
|
129
79
|
```tsx
|
|
130
80
|
<Button round tone="brand" label="Pill" />
|
|
131
|
-
<Button round tone="brand" icon="heart" aria-label="Like" />
|
|
132
|
-
<Button round={10} tone="brand" label="Custom 10px" />
|
|
81
|
+
<Button round tone="brand" icon="heart" aria-label="Like" />
|
|
82
|
+
<Button round={10} tone="brand" label="Custom 10px" />
|
|
133
83
|
```
|
|
134
84
|
|
|
135
85
|
## Icons
|
|
136
86
|
|
|
87
|
+
Use `icon` for a leading icon and `iconTrailing` for a trailing icon. See
|
|
88
|
+
[Icon](./icon.md) for available shapes.
|
|
89
|
+
|
|
137
90
|
```tsx
|
|
138
91
|
<Button tone="brand" priority="primary" icon="check" label="Confirm" />
|
|
139
92
|
<Button tone="brand" iconTrailing="external-link" label="Read the docs" />
|
|
140
93
|
<Button tone="brand" priority="tertiary" icon="filter" iconTrailing="chevron-down" label="Filter" />
|
|
141
94
|
```
|
|
142
95
|
|
|
143
|
-
The wrapper renders content in this order inside the button: `icon` →
|
|
144
|
-
`label` → `children` → `iconTrailing`. Icon shape names come from the
|
|
145
|
-
`IconShape` union — see the [Icon](./icon.md) page for the full
|
|
146
|
-
set. `children` (if any) lands between `label` and `iconTrailing`.
|
|
147
|
-
|
|
148
96
|
### Icon-only
|
|
149
97
|
|
|
98
|
+
Omit the label for an icon-only button. Pass a clear `aria-label` when the icon
|
|
99
|
+
name does not describe the action well.
|
|
100
|
+
|
|
150
101
|
```tsx
|
|
151
|
-
<Button
|
|
152
|
-
<Button tone="critical" icon="trash" />
|
|
153
|
-
<Button tone="brand"
|
|
102
|
+
<Button icon="dots-vertical" size="small" aria-label="More options" />
|
|
103
|
+
<Button tone="critical" icon="trash" aria-label="Delete" />
|
|
104
|
+
<Button round tone="brand" icon="check" size="large" aria-label="Confirm" />
|
|
154
105
|
```
|
|
155
106
|
|
|
156
|
-
Pass `icon` alone — no `label`, no `iconTrailing`, no `children` — and
|
|
157
|
-
the button collapses to a square. A min-size is pinned to a square
|
|
158
|
-
matching the labeled-button height (24px / 28px / 32px for small /
|
|
159
|
-
medium / large) so icon-only and labeled buttons line up, and a tight
|
|
160
|
-
flex parent can't clip the icon.
|
|
161
|
-
|
|
162
|
-
Icon-only buttons get an accessible name automatically — the wrapper
|
|
163
|
-
sets `aria-label={icon}` so `<Button icon="trash" />` ships with the
|
|
164
|
-
name "trash". Pass your own `aria-label` to override.
|
|
165
|
-
|
|
166
107
|
### Children
|
|
167
108
|
|
|
109
|
+
Use children for inline content such as keyboard hints, badges, or counters.
|
|
110
|
+
Text and number children receive the same label styling as the `label` prop.
|
|
111
|
+
|
|
168
112
|
```tsx
|
|
169
113
|
<Button tone="brand" label="Save" icon="check" aria-keyshortcuts="Meta+s">
|
|
170
|
-
<kbd aria-hidden="true"
|
|
114
|
+
<kbd aria-hidden="true">⌘S</kbd>
|
|
171
115
|
</Button>
|
|
172
116
|
```
|
|
173
117
|
|
|
174
|
-
Children render after the label and before the trailing icon, so you
|
|
175
|
-
can mix custom inline content — keyboard hints, badges, counters —
|
|
176
|
-
with the prop-driven API.
|
|
177
|
-
|
|
178
|
-
Children also work without `label` — pass them as the only content.
|
|
179
|
-
|
|
180
|
-
Text and number children are auto-wrapped in `<a-button-label>` (so the
|
|
181
|
-
truncation rule applies and they don't trip the icon-only detector);
|
|
182
|
-
element children — a `<span>`, a `<Tooltip>`, … — pass through
|
|
183
|
-
unwrapped. Children with no visible content render nothing: empty or
|
|
184
|
-
whitespace-only strings, `NaN`, `null` / `undefined`, and booleans are
|
|
185
|
-
dropped (a valid `0` still renders).
|
|
186
|
-
|
|
187
118
|
## Underline
|
|
188
119
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<Button tone="brand" priority="tertiary" underline="dashed" label="Dashed" />
|
|
192
|
-
<Button tone="brand" priority="tertiary" underline="dotted" label="Dotted" />
|
|
193
|
-
<Button tone="brand" priority="quaternary" underline="solid" underlineOnHover label="Hover only" />
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
When the button has a [link mode](#link-mode), or you simply want an
|
|
197
|
-
underline stylistically, it supports three styles — `solid`, `dashed`,
|
|
198
|
-
`dotted` (only valid on `priority="tertiary"` / `"quaternary"`). Set
|
|
199
|
-
`underlineOnHover` to keep that underline hidden until pointer hover.
|
|
120
|
+
Tertiary and quaternary buttons support solid, dashed, and dotted underlines.
|
|
121
|
+
Use `underlineOnHover` to show the underline only on hover.
|
|
200
122
|
|
|
201
123
|
## States
|
|
202
124
|
|
|
125
|
+
`loading` and `disabled` prevent activation. `selected` communicates a toggled
|
|
126
|
+
or pressed state.
|
|
127
|
+
|
|
203
128
|
```tsx
|
|
204
129
|
<Button tone="brand" loading label="Submitting" />
|
|
205
130
|
<Button tone="brand" disabled label="Locked" />
|
|
206
131
|
<Button tone="brand" selected label="Toggled on" />
|
|
207
|
-
<Button tone="brand" loading disabled label="Critical" />
|
|
208
132
|
```
|
|
209
133
|
|
|
210
|
-
- **`loading`** — diagonal stripe overlay slides across the button.
|
|
211
|
-
Stripe color follows `currentColor`, so it tracks the tone. Blocks
|
|
212
|
-
clicks via `pointer-events: none`, and (like `disabled`) removes the
|
|
213
|
-
button from the tab order so Enter/Space can't fire it mid-flight.
|
|
214
|
-
- **`disabled`** — locks the colors to the disabled palette, sets
|
|
215
|
-
`pointer-events: none`, and removes the button from the tab order.
|
|
216
|
-
Beats inline `--button-bg` overrides.
|
|
217
|
-
- **`selected`** — toggled-on / pressed visual; shares the active
|
|
218
|
-
state's look. Useful for filter chips and icon toggles.
|
|
219
|
-
|
|
220
134
|
## ButtonCopy
|
|
221
135
|
|
|
222
|
-
`ButtonCopy` is a
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
136
|
+
`ButtonCopy` is a `Button` preset for copy-to-clipboard. Its copy glyph changes
|
|
137
|
+
to a check on success or an x on failure, then returns to its resting state.
|
|
138
|
+
`onCopied(ok)` reports the result. Omit the label for an icon-only copy button.
|
|
139
|
+
|
|
140
|
+
The preset composes a regular `Button` with `<a-copy>`. Use `<a-copy>` directly
|
|
141
|
+
when you need the same behavior in another control.
|
|
228
142
|
|
|
229
143
|
```tsx
|
|
230
144
|
<ButtonCopy copy="npm i @antadesign/anta" label="Copy install command" />
|
|
231
|
-
<ButtonCopy copy="https://anta.design" priority="tertiary" />
|
|
232
|
-
|
|
233
|
-
<ButtonCopy
|
|
234
|
-
copy="npm i @antadesign/anta"
|
|
235
|
-
label="Copy install command"
|
|
236
|
-
iconPlacement="none"
|
|
237
|
-
copiedLabel="Copied to clipboard"
|
|
238
|
-
/>
|
|
145
|
+
<ButtonCopy copy="https://anta.design" priority="tertiary" />
|
|
239
146
|
```
|
|
240
147
|
|
|
241
|
-
The write lives in the standalone `<a-copy>` element, so the button stays a plain
|
|
242
|
-
button. `ButtonCopy` slots it in for you; to build the same by hand, drop an
|
|
243
|
-
`<a-copy copy=…>` into a `<Button>` or `<a-button>`. `onCopied(ok)` fires after
|
|
244
|
-
each attempt. Override the resting glyph with `icon`; the check / ✕ swap in only
|
|
245
|
-
during the feedback window.
|
|
246
|
-
|
|
247
|
-
With `iconPlacement="none"`, the button stays unchanged. A successful pointer
|
|
248
|
-
copy shows `✓ Copied` beside the pointer. A keyboard copy shows it at the
|
|
249
|
-
button's inline start. Use `copiedLabel` to change the text.
|
|
250
|
-
|
|
251
148
|
### Icon placement
|
|
252
149
|
|
|
253
|
-
`iconPlacement`
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
150
|
+
Set `iconPlacement` to `leading`, `trailing`, or `none`. With `none`, the button
|
|
151
|
+
does not change. Successful pointer activation shows a confirmation beside the
|
|
152
|
+
pointer; keyboard activation shows it at the button's inline start. Use
|
|
153
|
+
`copiedLabel` to change the message.
|
|
257
154
|
|
|
258
155
|
```tsx
|
|
259
|
-
<ButtonCopy copy={value} label="Leading" />
|
|
156
|
+
<ButtonCopy copy={value} label="Leading" />
|
|
260
157
|
<ButtonCopy copy={value} label="Trailing" iconPlacement="trailing" />
|
|
261
158
|
<ButtonCopy copy={value} label="No icon" iconPlacement="none" />
|
|
262
159
|
```
|
|
263
160
|
|
|
264
161
|
### Copy a DOM node
|
|
265
162
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
button itself is stripped from what's copied.
|
|
163
|
+
Use `copyNode` to copy a rendered region as `text/html` and plain text. Bare
|
|
164
|
+
`copyNode` finds the nearest `data-copy-source`; a string selects an ancestor.
|
|
165
|
+
The copy control itself is omitted from the copied content.
|
|
270
166
|
|
|
271
167
|
```tsx
|
|
272
168
|
<div data-copy-source>
|
|
273
169
|
<Text>The quick brown fox jumps over the lazy dog.</Text>
|
|
274
|
-
<ButtonCopy copyNode label="Copy card"
|
|
170
|
+
<ButtonCopy copyNode label="Copy card" />
|
|
275
171
|
</div>
|
|
276
172
|
```
|
|
277
173
|
|
|
278
|
-
Copying rich text lets a paste target keep formatting (bold, links, list
|
|
279
|
-
structure) while a plain-text target still gets clean text. Paste the copied
|
|
280
|
-
card into a rich editor and a plain one to see both.
|
|
281
|
-
|
|
282
174
|
### Copy the page URL
|
|
283
175
|
|
|
284
|
-
`copyUrl`
|
|
285
|
-
|
|
286
|
-
carries a link back to where it came from.
|
|
176
|
+
Use `copyUrl` to copy `location.href`. `copyWithUrl` prefixes copied text with
|
|
177
|
+
`// URL: <current page URL>`.
|
|
287
178
|
|
|
288
179
|
```tsx
|
|
289
180
|
<ButtonCopy copyUrl label="Copy link" />
|
|
290
|
-
<ButtonCopy copy={snippet} copyWithUrl label="Copy snippet" />
|
|
181
|
+
<ButtonCopy copy={snippet} copyWithUrl label="Copy snippet" />
|
|
291
182
|
```
|
|
292
183
|
|
|
293
184
|
### Copy dynamic text
|
|
294
185
|
|
|
295
|
-
`copy` is
|
|
296
|
-
`onCopyRequest`. The
|
|
297
|
-
|
|
186
|
+
`copy` is controlled. For text generated on demand, initialize it to `''` and
|
|
187
|
+
update it in `onCopyRequest`. The callback fires on pointerdown or Enter/Space
|
|
188
|
+
keydown, before activation writes the current `copy` value. Its return value is
|
|
189
|
+
ignored.
|
|
298
190
|
|
|
299
191
|
```tsx
|
|
300
192
|
const [report, setReport] = useState('')
|
|
@@ -306,24 +198,18 @@ const [report, setReport] = useState('')
|
|
|
306
198
|
/>
|
|
307
199
|
```
|
|
308
200
|
|
|
309
|
-
`onCopyRequest` fires on pointerdown or Enter/Space keydown, before the click or
|
|
310
|
-
menu selection that writes to the clipboard.
|
|
311
|
-
|
|
312
201
|
#### Why `copy` is controlled
|
|
313
202
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
thread, but the application's JSX code can be elsewhere. A function cannot cross
|
|
318
|
-
that boundary as a callable reference.
|
|
203
|
+
Anta supports applications whose JSX renderer runs in a worker. The DOM copy
|
|
204
|
+
control and Clipboard API remain on the browser's UI thread, and a callback
|
|
205
|
+
cannot cross that boundary as a callable reference.
|
|
319
206
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
current URL (`copyUrl`).
|
|
207
|
+
`onCopyRequest` asks the application to calculate the text. The resulting state
|
|
208
|
+
update sends a serializable `copy` string to the DOM control, which writes it
|
|
209
|
+
during the user activation required by the Clipboard API. A `lazyCopy` callback
|
|
210
|
+
would only hide this state update in a main-thread wrapper and would not work
|
|
211
|
+
across renderers. Separate `copy`, `copyNode`, and `copyUrl` inputs also keep the
|
|
212
|
+
clipboard format explicit.
|
|
327
213
|
|
|
328
214
|
### Props
|
|
329
215
|
|
|
@@ -363,105 +249,64 @@ current URL (`copyUrl`).
|
|
|
363
249
|
|
|
364
250
|
## Link mode
|
|
365
251
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
Setting `href` switches the rendered tag from `<a-button>` to
|
|
371
|
-
`<a role="button" data-anta>`. Styling is identical — both selectors share
|
|
372
|
-
the same CSS rules. `<Button>` adds the `data-anta` marker for you.
|
|
373
|
-
|
|
374
|
-
**`href` is optional**, so a conditional URL needs no branching. Pass
|
|
375
|
-
`href={maybeUrl}` (a `string | undefined`): a definite string links out, an
|
|
376
|
-
absent / `undefined` href renders a plain `<a-button>`. Pair it with `disabled`
|
|
377
|
-
for a link that's live when the URL exists and inert otherwise — no two-render
|
|
378
|
-
split or conditional spread:
|
|
252
|
+
Set `href` to render a link with button styling. An absent or `undefined` URL
|
|
253
|
+
keeps the regular button, which makes conditional links straightforward.
|
|
379
254
|
|
|
380
255
|
```tsx
|
|
381
|
-
|
|
382
|
-
<Button
|
|
256
|
+
<Button href="/docs" target="_blank" label="Read the docs" />
|
|
257
|
+
<Button
|
|
258
|
+
href={reportUrl}
|
|
259
|
+
disabled={!reportUrl}
|
|
260
|
+
iconTrailing="external-link"
|
|
261
|
+
label="View report"
|
|
262
|
+
/>
|
|
383
263
|
```
|
|
384
264
|
|
|
385
265
|
### Routing libraries
|
|
386
266
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
gets the styling. That means anta doesn't need an `as` / `asChild` /
|
|
390
|
-
`component` prop or per-framework integrations. Compose your own thin wrapper
|
|
391
|
-
around your library's `Link` component — which renders an `<a>`, so adding
|
|
392
|
-
`role="button"` and `data-anta` matches the selector.
|
|
393
|
-
|
|
394
|
-
The `data-anta` marker is required because `role="button"` is a *generic* ARIA
|
|
395
|
-
role that other widgets emit too — gating on the marker keeps anta from
|
|
396
|
-
restyling anchors it doesn't own (a third-party menu, an embedded editor's
|
|
397
|
-
toolbar, etc.).
|
|
267
|
+
For client-side routing, wrap your router's link and add `role="button"` and
|
|
268
|
+
`data-anta` to its anchor output.
|
|
398
269
|
|
|
399
270
|
```tsx
|
|
400
|
-
|
|
401
|
-
import { Link, type LinkProps } from 'react-router-dom'
|
|
402
|
-
import type { IconShape } from '@antadesign/anta'
|
|
403
|
-
|
|
404
|
-
type LinkButtonProps = LinkProps & {
|
|
405
|
-
tone?: 'neutral' | 'brand' | 'critical' | 'info' | 'success' | 'warning'
|
|
406
|
-
priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary'
|
|
407
|
-
size?: 'small' | 'medium' | 'large'
|
|
408
|
-
icon?: IconShape
|
|
409
|
-
iconTrailing?: IconShape
|
|
410
|
-
label?: string
|
|
411
|
-
}
|
|
271
|
+
import { Link } from 'react-router-dom'
|
|
412
272
|
|
|
413
|
-
export const LinkButton = ({
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
<Link role="button" data-anta tone={tone} priority={priority} size={size} {...rest}>
|
|
417
|
-
{icon && <a-icon shape={icon} aria-hidden="true" />}
|
|
418
|
-
{label != null && <a-button-label>{label}</a-button-label>}
|
|
419
|
-
{children}
|
|
420
|
-
{iconTrailing && <a-icon shape={iconTrailing} aria-hidden="true" />}
|
|
273
|
+
export const LinkButton = ({ label, ...props }) => (
|
|
274
|
+
<Link role="button" data-anta {...props}>
|
|
275
|
+
<a-button-label>{label}</a-button-label>
|
|
421
276
|
</Link>
|
|
422
277
|
)
|
|
423
278
|
```
|
|
424
279
|
|
|
425
|
-
Usage:
|
|
426
|
-
|
|
427
|
-
```tsx
|
|
428
|
-
<LinkButton to="/dashboard" tone="brand" label="Dashboard" />
|
|
429
|
-
<LinkButton to="/docs" priority="tertiary" iconTrailing="external-link" label="Docs" />
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
This approach would work for Next.js `<Link>`, TanStack Router, or any
|
|
433
|
-
other routing library.
|
|
434
|
-
|
|
435
280
|
## Special events
|
|
436
281
|
|
|
437
|
-
Beyond a plain click, a
|
|
438
|
-
event
|
|
282
|
+
Beyond a plain click, a button can submit or reset a native form and dispatch a
|
|
283
|
+
named custom event.
|
|
439
284
|
|
|
440
285
|
### Form submission
|
|
441
286
|
|
|
442
|
-
For non-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
287
|
+
For non-link buttons, `type="submit"` and `type="reset"` integrate with native
|
|
288
|
+
forms. The `form` prop associates a button with a form elsewhere on the page.
|
|
289
|
+
Submitting calls `form.requestSubmit()`, so the form's validation and `submit`
|
|
290
|
+
event still run. It also dispatches `submitdetailed` on the form with
|
|
291
|
+
`{ formData, submitter: { tag, attrs } }` in `detail`, which can identify the
|
|
292
|
+
trigger in analytics or multi-button forms.
|
|
447
293
|
|
|
448
294
|
```tsx
|
|
449
295
|
<form id="signup">
|
|
450
296
|
<Button tone="brand" type="submit" label="Sign up" />
|
|
451
|
-
<Button
|
|
297
|
+
<Button priority="tertiary" type="reset" label="Clear" />
|
|
452
298
|
</form>
|
|
453
|
-
|
|
454
|
-
<Button tone="neutral" type="submit" form="signup" label="Submit from outside" />
|
|
299
|
+
<Button type="submit" form="signup" label="Submit from outside" />
|
|
455
300
|
```
|
|
456
301
|
|
|
457
302
|
### Custom click events
|
|
458
303
|
|
|
459
|
-
`data-custom-event="<name>"`
|
|
460
|
-
|
|
461
|
-
|
|
304
|
+
Set `data-custom-event="<name>"` to dispatch a bubbling `CustomEvent("<name>")`
|
|
305
|
+
on click. This is useful for declarative actions or analytics that should not
|
|
306
|
+
take ownership of `onClick`.
|
|
462
307
|
|
|
463
308
|
```tsx
|
|
464
|
-
<Button
|
|
309
|
+
<Button label="Save" data-custom-event="save-clicked" />
|
|
465
310
|
```
|
|
466
311
|
|
|
467
312
|
## Component props
|
|
@@ -494,9 +339,7 @@ without taking ownership of `onClick`.
|
|
|
494
339
|
|
|
495
340
|
## Web Component
|
|
496
341
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
Set `role="button"` and `tabindex="0"` when authoring `<a-button>` directly.
|
|
342
|
+
When using `<a-button>` directly, add its button role and keyboard tab stop.
|
|
500
343
|
|
|
501
344
|
```html
|
|
502
345
|
<a-button role="button" tabindex="0" priority="primary">
|
|
@@ -505,124 +348,27 @@ Set `role="button"` and `tabindex="0"` when authoring `<a-button>` directly.
|
|
|
505
348
|
</a-button>
|
|
506
349
|
```
|
|
507
350
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
The styling attaches to three element shapes, so you can adopt the button look on
|
|
511
|
-
markup you already own instead of routing through `<Button>`. `data-anta` is the
|
|
512
|
-
opt-in marker — it stops Anta restyling a `role="button"` element it does not own
|
|
513
|
-
(a third-party menu, an embedded editor's toolbar):
|
|
514
|
-
|
|
515
|
-
| Element | For |
|
|
516
|
-
| --- | --- |
|
|
517
|
-
| `<a-button>` | the component's own tag, always styled — what `<Button>` renders |
|
|
518
|
-
| `<a role="button" data-anta>` | a link — what `<Button href>` renders (see [Link mode](#link-mode)) |
|
|
519
|
-
| `<button data-anta>` | a native form control — keeps native form submission, `disabled`, and Enter / Space activation |
|
|
520
|
-
|
|
521
|
-
`tone` / `priority` / `size` are plain attributes on the element (the `<Button>`
|
|
522
|
-
wrapper sets them for you). A native `<button>` also carries its own default
|
|
523
|
-
`type="submit"`, so inside a `<form>` it submits without extra wiring:
|
|
351
|
+
Use `<button data-anta>` when you need native button and form behavior.
|
|
524
352
|
|
|
525
353
|
```html
|
|
526
|
-
<!-- A real <button>: submits forms and toggles `disabled` natively. -->
|
|
527
354
|
<button data-anta tone="brand" priority="primary">Save changes</button>
|
|
528
|
-
<button data-anta
|
|
529
|
-
<button data-anta tone="critical" priority="tertiary">Delete</button>
|
|
355
|
+
<button data-anta disabled>Unavailable</button>
|
|
530
356
|
```
|
|
531
357
|
|
|
532
358
|
## Styling
|
|
533
359
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
[`--focus-ring`](../colors.md#focus-ring).
|
|
538
|
-
|
|
539
|
-
```tsx
|
|
540
|
-
<Button tone="#e0457b" priority="primary" label="Custom" />
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
For anything beyond the props, `<a-button>` is light-DOM — restyle it with plain
|
|
544
|
-
CSS (an un-layered rule beats `@layer anta` without `!important`). Set
|
|
545
|
-
`background-color` / `color` **per state**, plus full type control (size,
|
|
546
|
-
line-height, letter-spacing, `font-feature-settings`), padding, radius, even a
|
|
547
|
-
frosted `backdrop-filter` — no need to touch a single token. **`light-dark()`** works
|
|
548
|
-
too (Anta sets `color-scheme` from its theme toggle), so colors adapt to dark mode
|
|
549
|
-
with no `.dark` selector. The classes below are just for the demos:
|
|
360
|
+
Use `tone`, `priority`, `size`, and `round` before adding custom CSS. For a
|
|
361
|
+
distinct treatment, target a class on the button and cover its interaction
|
|
362
|
+
states.
|
|
550
363
|
|
|
551
364
|
```css
|
|
552
|
-
/* First — inverted pill: a theme-flipping gradient (near-black in light,
|
|
553
|
-
near-white in dark) via light-dark() in the gradient stops. Anta sets
|
|
554
|
-
color-scheme from its .dark toggle, so it adapts with no .dark selector. */
|
|
555
365
|
a-button.checkout {
|
|
556
|
-
background: linear-gradient(140deg, light-dark(#26262b, #fff), light-dark(#000, #dcdce0));
|
|
557
|
-
color: light-dark(#fff, #0b0b0c);
|
|
558
|
-
font-size: 20px;
|
|
559
|
-
line-height: 1.2em;
|
|
560
|
-
padding: 12px 26px;
|
|
561
|
-
border-radius: 999px;
|
|
562
|
-
}
|
|
563
|
-
a-button.checkout:hover { background: linear-gradient(140deg, light-dark(#3a3a42, #fff), light-dark(#161618, #cacace)); }
|
|
564
|
-
a-button.checkout:active { background: linear-gradient(140deg, light-dark(#000, #ececf0), light-dark(#1a1a1c, #fff)); }
|
|
565
|
-
a-button.checkout a-button-label { /* customized label */
|
|
566
|
-
text-transform: uppercase;
|
|
567
|
-
letter-spacing: 0.14em;
|
|
568
|
-
font-weight: 600;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
/* Second — liquid glass: frost + translucent tint + a diagonal specular sheen,
|
|
572
|
-
a top/bottom bevel, and a soft lift. Sits on a colorful backdrop so it reads. */
|
|
573
|
-
a-button.glass {
|
|
574
366
|
color: #fff;
|
|
575
|
-
background
|
|
576
|
-
background-image: linear-gradient(135deg, rgba(255,255,255,0.55), rgba(255,255,255,0.06) 45%, transparent 65%);
|
|
577
|
-
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
367
|
+
background: #673de6;
|
|
578
368
|
border-radius: 999px;
|
|
579
|
-
|
|
580
|
-
box-shadow:
|
|
581
|
-
inset 0 1px 1px rgba(255,255,255,0.65), /* top bevel */
|
|
582
|
-
inset 0 -2px 3px rgba(255,255,255,0.18),
|
|
583
|
-
0 8px 24px rgba(0,0,0,0.22); /* lift */
|
|
584
|
-
font-size: 20px; line-height: 1.2em; padding: 12px 26px;
|
|
585
|
-
}
|
|
586
|
-
a-button.glass:hover { background-color: rgba(255, 255, 255, 0.22); }
|
|
587
|
-
a-button.glass:active { background-color: rgba(255, 255, 255, 0.08); }
|
|
588
|
-
a-button.glass a-button-label { /* beautified label — gradient text */
|
|
589
|
-
font-weight: 600;
|
|
590
|
-
background: linear-gradient(180deg, #fff, #cfe0ff);
|
|
591
|
-
background-clip: text;
|
|
592
|
-
color: transparent;
|
|
593
|
-
filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3));
|
|
369
|
+
padding-inline: 20px;
|
|
594
370
|
}
|
|
595
|
-
```
|
|
596
371
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
<style>{`
|
|
601
|
-
/* Keep loading's blocked interaction; replace only its stripe overlay. */
|
|
602
|
-
a-button.custom[loading]::before {
|
|
603
|
-
inset: -200%;
|
|
604
|
-
border-radius: 100%;
|
|
605
|
-
background: conic-gradient(
|
|
606
|
-
from 0deg,
|
|
607
|
-
color-mix(in oklch, currentColor 0%, transparent),
|
|
608
|
-
color-mix(in oklch, currentColor 10%, transparent)
|
|
609
|
-
);
|
|
610
|
-
opacity: 1;
|
|
611
|
-
filter: none;
|
|
612
|
-
animation: button-loader-field-spin 1s linear infinite;
|
|
613
|
-
animation-delay: -9999s;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
@keyframes button-loader-field-spin {
|
|
617
|
-
to { transform: rotate(1turn); }
|
|
618
|
-
}
|
|
619
|
-
`}</style>
|
|
372
|
+
a-button.checkout:hover { background: #5931c4; }
|
|
373
|
+
a-button.checkout:active { background: #48269f; }
|
|
620
374
|
```
|
|
621
|
-
|
|
622
|
-
**Loader field.** `loading` still blocks pointer and keyboard activation. This
|
|
623
|
-
only replaces its default stripe overlay with the Loader’s conic field, scaled
|
|
624
|
-
beyond the button so it can rotate behind the label without exposing an edge.
|
|
625
|
-
|
|
626
|
-
Don't reach for the resolved `--button-fg` / `--button-bg`: they're recomputed per
|
|
627
|
-
state, so setting one only catches a single state — restyle per state as above, or
|
|
628
|
-
use `tone` for a full custom-color curve.
|