@antadesign/anta 0.2.1 → 0.3.0

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.
Files changed (85) hide show
  1. package/README.md +14 -0
  2. package/dist/anta_helpers.d.ts +39 -1
  3. package/dist/anta_helpers.js +30 -2
  4. package/dist/components/Button.d.ts +7 -4
  5. package/dist/components/Button.js +12 -14
  6. package/dist/components/Checkbox.d.ts +97 -0
  7. package/dist/components/Checkbox.js +77 -0
  8. package/dist/components/Expander.d.ts +74 -0
  9. package/dist/components/Expander.js +53 -0
  10. package/dist/components/Input.d.ts +159 -0
  11. package/dist/components/Input.js +150 -0
  12. package/dist/components/Menu.d.ts +70 -0
  13. package/dist/components/Menu.js +42 -0
  14. package/dist/components/MenuGroup.d.ts +24 -0
  15. package/dist/components/MenuGroup.js +19 -0
  16. package/dist/components/MenuItem.d.ts +50 -0
  17. package/dist/components/MenuItem.js +41 -0
  18. package/dist/components/MenuSeparator.d.ts +14 -0
  19. package/dist/components/MenuSeparator.js +7 -0
  20. package/dist/components/Progress.d.ts +12 -6
  21. package/dist/components/Progress.js +7 -4
  22. package/dist/components/Radio.d.ts +37 -0
  23. package/dist/components/Radio.js +33 -0
  24. package/dist/components/RadioGroup.d.ts +119 -0
  25. package/dist/components/RadioGroup.js +108 -0
  26. package/dist/components/Tag.d.ts +38 -5
  27. package/dist/components/Tag.js +9 -5
  28. package/dist/components/Text.d.ts +27 -12
  29. package/dist/components/Text.js +6 -3
  30. package/dist/components/Title.d.ts +10 -1
  31. package/dist/components/Tooltip.d.ts +19 -9
  32. package/dist/components/Tooltip.js +2 -2
  33. package/dist/elements/a-button.css +1 -1
  34. package/dist/elements/a-button.d.ts +56 -0
  35. package/dist/elements/a-button.js +13 -11
  36. package/dist/elements/a-checkbox.css +1 -0
  37. package/dist/elements/a-checkbox.d.ts +52 -0
  38. package/dist/elements/a-checkbox.js +130 -0
  39. package/dist/elements/a-expander.css +1 -0
  40. package/dist/elements/a-expander.d.ts +28 -0
  41. package/dist/elements/a-expander.js +237 -0
  42. package/dist/elements/a-icon.d.ts +14 -0
  43. package/dist/elements/a-icon.shapes.css +1 -1
  44. package/dist/elements/a-icon.shapes.d.ts +10 -2
  45. package/dist/elements/a-icon.shapes.js +12 -3
  46. package/dist/elements/a-input.css +1 -0
  47. package/dist/elements/a-input.d.ts +68 -0
  48. package/dist/elements/a-input.js +511 -0
  49. package/dist/elements/a-menu-group.css +1 -0
  50. package/dist/elements/a-menu-group.d.ts +13 -0
  51. package/dist/elements/a-menu-group.js +15 -0
  52. package/dist/elements/a-menu-item.css +1 -0
  53. package/dist/elements/a-menu-item.d.ts +47 -0
  54. package/dist/elements/a-menu-item.js +30 -0
  55. package/dist/elements/a-menu-separator.css +1 -0
  56. package/dist/elements/a-menu-separator.d.ts +13 -0
  57. package/dist/elements/a-menu-separator.js +15 -0
  58. package/dist/elements/a-menu.css +1 -0
  59. package/dist/elements/a-menu.d.ts +171 -0
  60. package/dist/elements/a-menu.js +714 -0
  61. package/dist/elements/a-progress.css +1 -1
  62. package/dist/elements/a-progress.d.ts +12 -0
  63. package/dist/elements/a-progress.js +1 -0
  64. package/dist/elements/a-radio-group.css +1 -0
  65. package/dist/elements/a-radio-group.d.ts +33 -0
  66. package/dist/elements/a-radio-group.js +160 -0
  67. package/dist/elements/a-radio.css +1 -0
  68. package/dist/elements/a-radio.d.ts +14 -0
  69. package/dist/elements/a-radio.js +46 -0
  70. package/dist/elements/a-tag.css +1 -1
  71. package/dist/elements/a-text.css +1 -1
  72. package/dist/elements/a-text.d.ts +42 -3
  73. package/dist/elements/a-text.js +73 -33
  74. package/dist/elements/a-title.css +1 -1
  75. package/dist/elements/a-tooltip.d.ts +65 -15
  76. package/dist/elements/a-tooltip.js +155 -115
  77. package/dist/elements/index.d.ts +9 -0
  78. package/dist/elements/index.js +27 -0
  79. package/dist/general_types.d.ts +471 -19
  80. package/dist/index.d.ts +16 -0
  81. package/dist/index.js +16 -0
  82. package/dist/jsx-runtime.d.ts +42 -7
  83. package/dist/jsx-runtime.js +14 -2
  84. package/dist/tokens.css +1 -1
  85. package/package.json +1 -1
@@ -0,0 +1,119 @@
1
+ import type { BaseProps } from "../general_types";
2
+ /** The element's `statechange` payload. `next`/`prev` are values (`null` = nothing
3
+ * selected); `reason` distinguishes a user pick from a form reset / bfcache restore. */
4
+ type StateReason = "user" | "reset" | "restore";
5
+ type StateDetail = {
6
+ next: string | null;
7
+ prev: string | null;
8
+ reason: StateReason;
9
+ };
10
+ type StateChangeEvent = CustomEvent<StateDetail>;
11
+ /** Snapshot passed as the 2nd argument to `onAnyChange` — the new value plus the
12
+ * field name, so you don't poke at `event.target`. Mirrors `Input`/`Checkbox`. */
13
+ export interface RadioChangeAttrs {
14
+ value: string | null;
15
+ name?: string;
16
+ }
17
+ /** One option in a `<RadioGroup>`. The wrapper renders an `<a-radio>` per entry. */
18
+ export interface RadioOption {
19
+ /** This option's identity and the value submitted when it's selected.
20
+ * Must be unique within the group (a dev-only warning fires on duplicates). */
21
+ value: string;
22
+ /** The visible label. */
23
+ label?: React.ReactNode;
24
+ /** Secondary text under the label — explanatory copy, like `Input`'s hint. */
25
+ hint?: React.ReactNode;
26
+ /** Disable just this option (skipped by keyboard, dropped from the tab order). */
27
+ disabled?: boolean;
28
+ /** Override this one option's tone (defaults to the group's `tone`). */
29
+ tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
30
+ /** Override this one option's size (defaults to the group's `size`). */
31
+ size?: "small" | "medium" | "large";
32
+ /** Override this one option's priority (defaults to the group's `priority`). */
33
+ priority?: "primary" | "secondary";
34
+ }
35
+ /** Public props for `<RadioGroup>` — the single-select container. */
36
+ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"> {
37
+ /** The options. The wrapper renders one `<a-radio>` per entry and computes its
38
+ * `selected` / roving `tabindex` / `role` declaratively. */
39
+ options: RadioOption[];
40
+ /** Controlled selected value. When provided, the consumer owns selection: the
41
+ * group follows this prop and a pick only *requests* a change via
42
+ * `onStateChange` (reject by not updating). Leave undefined for uncontrolled. */
43
+ value?: string;
44
+ /** Initial selected value for the uncontrolled case (the wrapper then owns the
45
+ * selection in local state). */
46
+ defaultValue?: string;
47
+ /** Fired whenever selection changes — event-first. `detail` is
48
+ * `{ next, prev, reason }`: `next`/`prev` are values (`null` = nothing selected);
49
+ * `reason` is `'user'` | `'reset'` | `'restore'`. A `'user'` pick fires *before*
50
+ * applying and is **cancelable** — `event.preventDefault()` vetoes it
51
+ * (uncontrolled), or in controlled mode answer by updating `value` (reject by
52
+ * doing nothing). `'reset'` (form reset) and `'restore'` (bfcache / autofill) are
53
+ * not cancelable — filter on `reason` if you only track user picks. */
54
+ onStateChange?: (event: StateChangeEvent, detail: StateDetail) => void;
55
+ /** Fired *after* the selection changes — a native `change` event (the post-apply
56
+ * counterpart to `onStateChange`). Not cancelable; for a controlled group it
57
+ * fires once you've updated `value`. */
58
+ onChange?: (event: Event) => void;
59
+ /** Like `onChange`, but with a `{ value, name }` snapshot as the 2nd argument —
60
+ * the ergonomic "just give me the new value" callback (mirrors `Input`). */
61
+ onAnyChange?: (event: Event, attrs: RadioChangeAttrs) => void;
62
+ /** Fired when focus enters the group (any option) — wired to `focusin`, since
63
+ * focus lands on an individual option, not the group element itself. */
64
+ onFocus?: (event: FocusEvent) => void;
65
+ /** Fired when focus leaves the group entirely — wired to `focusout`. */
66
+ onBlur?: (event: FocusEvent) => void;
67
+ /** Form field name — the group submits one `name=value` (it's the
68
+ * form-associated element). */
69
+ name?: string;
70
+ /** Plain-text label for the whole group, rendered above the options. */
71
+ label?: string;
72
+ /** Plain-text description for the group, rendered directly under `label` (above
73
+ * the options) — typically instructional copy. Per-option helper text goes on
74
+ * the option's own `hint` instead. */
75
+ hint?: string;
76
+ /** Validation/feedback tone for the group `hint` — recolours it (same tone set
77
+ * as `Input`'s `status`). Use `critical` for an error message, etc.; omit for
78
+ * the neutral default.
79
+ * @defaultValue 'neutral' */
80
+ status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical";
81
+ /** Tone applied to every option (an option's own `tone` wins), or any literal
82
+ * CSS color for a one-off custom tone. Tints fill, label, hint, and the
83
+ * unselected ring border. Named tones track light/dark mode.
84
+ * @defaultValue 'neutral' */
85
+ tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
86
+ /** Size applied to every option (an option's own `size` wins).
87
+ * @defaultValue 'medium' */
88
+ size?: "small" | "medium" | "large";
89
+ /** Visual priority applied to every option (an option's own `priority` wins).
90
+ * `primary` fills the selected ring with the tone colour and draws a white dot;
91
+ * `secondary` keeps the ring unfilled and draws the border + dot in the tone
92
+ * colour (an outlined look).
93
+ * @defaultValue 'primary' */
94
+ priority?: "primary" | "secondary";
95
+ /** Disable the whole group. */
96
+ disabled?: boolean;
97
+ /** Layout + arrow-key axis.
98
+ * @defaultValue 'vertical' */
99
+ orientation?: "vertical" | "horizontal";
100
+ }
101
+ /**
102
+ * `<RadioGroup>` — a single-select radio control, rendered from `options`.
103
+ *
104
+ * This wrapper is convenience over the web components: it renders an `<a-radio>`
105
+ * per option and, crucially, owns the two **declarative** DOM concerns the
106
+ * elements deliberately don't touch — the roving **`tabindex`** (so keyboard Tab
107
+ * lands on the right option) and each radio's **`role`**. Selection itself lives
108
+ * in `<a-radio-group>` off-DOM (it sets each radio's `selected` property), so the
109
+ * elements never mutate the DOM; this wrapper just reflects the current value into
110
+ * `tabindex` on re-render. (Hand-assembling raw `<a-radio-group>` / `<a-radio>`
111
+ * also works — see the element docs — this wrapper is the ergonomic path.)
112
+ *
113
+ * Controlled (`value` + `onStateChange`) or uncontrolled (`defaultValue`); either
114
+ * way the wrapper holds the value so it can compute the roving `tabindex`.
115
+ *
116
+ * Requires `@antadesign/anta/elements` (client-side only).
117
+ */
118
+ export declare const RadioGroup: ({ options, value, defaultValue, onStateChange, onChange, onAnyChange, onFocus, onBlur, name, label, hint, status, tone, size, priority, disabled, orientation, className, style, ...rest }: RadioGroupProps) => any;
119
+ export {};
@@ -0,0 +1,108 @@
1
+ import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
+ import { useId, useState } from "../jsx-runtime";
3
+ import { nativeStateChange, toneStyle } from "../anta_helpers";
4
+ const radioAttrsOf = (el) => ({
5
+ value: el?.value ?? null,
6
+ name: el?.getAttribute?.("name") ?? void 0
7
+ });
8
+ const RadioGroup = ({
9
+ options,
10
+ value,
11
+ defaultValue,
12
+ onStateChange,
13
+ onChange,
14
+ onAnyChange,
15
+ onFocus,
16
+ onBlur,
17
+ name,
18
+ label,
19
+ hint,
20
+ status,
21
+ tone,
22
+ size,
23
+ priority,
24
+ disabled,
25
+ orientation,
26
+ className,
27
+ style,
28
+ ...rest
29
+ }) => {
30
+ const controlled = value !== void 0;
31
+ const [internalValue, setInternalValue] = useState(defaultValue);
32
+ const currentValue = controlled ? value : internalValue;
33
+ const seen = /* @__PURE__ */ new Set();
34
+ for (const o of options) {
35
+ if (seen.has(o.value))
36
+ console.warn(`[anta] <RadioGroup> duplicate option value ${JSON.stringify(o.value)} \u2014 values must be unique.`);
37
+ seen.add(o.value);
38
+ }
39
+ const labelId = useId();
40
+ const hintId = useId();
41
+ const tabStopValue = disabled ? void 0 : options.find((o) => o.value === currentValue)?.value ?? options.find((o) => !o.disabled)?.value;
42
+ const onstatechange = (e) => {
43
+ const { event, detail } = nativeStateChange(e);
44
+ if (!detail) return;
45
+ onStateChange?.(event, detail);
46
+ if (controlled) return;
47
+ if (detail.reason === "user" && event.defaultPrevented) return;
48
+ setInternalValue(detail.next ?? void 0);
49
+ };
50
+ const onchange = onChange || onAnyChange ? (e) => {
51
+ onChange?.(e);
52
+ onAnyChange?.(e, radioAttrsOf(e.currentTarget));
53
+ } : void 0;
54
+ return /* @__PURE__ */ jsxs(
55
+ "a-radio-group",
56
+ {
57
+ role: "radiogroup",
58
+ "aria-disabled": disabled ? "true" : void 0,
59
+ "aria-labelledby": label ? labelId : void 0,
60
+ "aria-describedby": hint ? hintId : void 0,
61
+ ...rest,
62
+ state: controlled ? value : void 0,
63
+ "default-state": !controlled ? defaultValue : void 0,
64
+ name,
65
+ status: status && status !== "neutral" ? status : void 0,
66
+ tone: tone && tone !== "neutral" ? tone : void 0,
67
+ size: size && size !== "medium" ? size : void 0,
68
+ priority: priority && priority !== "primary" ? priority : void 0,
69
+ disabled: disabled ? "" : void 0,
70
+ orientation: orientation && orientation !== "vertical" ? orientation : void 0,
71
+ onstatechange,
72
+ onchange,
73
+ onfocusin: onFocus,
74
+ onfocusout: onBlur,
75
+ class: className,
76
+ style: toneStyle(tone, "--radio-tone-source", style),
77
+ children: [
78
+ label && /* @__PURE__ */ jsx("a-radio-group-label", { id: labelId, children: label }),
79
+ hint && /* @__PURE__ */ jsx("a-radio-group-hint", { id: hintId, children: hint }),
80
+ /* @__PURE__ */ jsx("a-radio-list", { children: options.map((o) => {
81
+ const optDisabled = disabled || o.disabled;
82
+ return /* @__PURE__ */ jsxs(
83
+ "a-radio",
84
+ {
85
+ role: "radio",
86
+ value: o.value,
87
+ "aria-disabled": optDisabled ? "true" : void 0,
88
+ tabIndex: o.value === tabStopValue ? 0 : -1,
89
+ tone: o.tone && o.tone !== "neutral" ? o.tone : void 0,
90
+ size: o.size && o.size !== "medium" ? o.size : void 0,
91
+ priority: o.priority && o.priority !== "primary" ? o.priority : void 0,
92
+ disabled: o.disabled ? "" : void 0,
93
+ style: toneStyle(o.tone, "--radio-tone-source"),
94
+ children: [
95
+ /* @__PURE__ */ jsx("a-radio-label", { children: o.label }),
96
+ o.hint != null && /* @__PURE__ */ jsx("a-radio-hint", { children: o.hint })
97
+ ]
98
+ },
99
+ o.value
100
+ );
101
+ }) })
102
+ ]
103
+ }
104
+ );
105
+ };
106
+ export {
107
+ RadioGroup
108
+ };
@@ -10,12 +10,19 @@ export interface TagProps extends BaseProps {
10
10
  * label; the color + weight contrast does the separating. */
11
11
  value?: string;
12
12
  /** Semantic tone, or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`)
13
- * for a one-off custom tone. Named tones map to the `--text-2-{tone}` /
14
- * `--bg-4-{tone}` palette; a custom color keeps its hue while lightness
15
- * and chroma are pinned. `'neutral'` (the default) is the gray tag —
16
- * the same as omitting `tone`.
13
+ * for a one-off custom tone. Each tone renders the secondary tag style:
14
+ * `--text-3-{tone}` text over an alpha tint of the tone's hue (fill + a
15
+ * slightly stronger hairline border). A custom color is tinted the same
16
+ * way, with the text deepened to a readable foreground. `'neutral'` (the
17
+ * default) is the gray tag — the same as omitting `tone`.
17
18
  * @defaultValue neutral */
18
19
  tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
20
+ /** Emphasis level. `secondary` (the default) is the subtle alpha-tint
21
+ * fill; `primary` is a solid fill with white text; `tertiary` is a
22
+ * transparent outline. Omitting it (or passing `'secondary'`) renders
23
+ * the default and emits no DOM attribute.
24
+ * @defaultValue secondary */
25
+ priority?: 'primary' | 'secondary' | 'tertiary';
19
26
  /** Size variant. `small` = 16px tall, `medium` = 20px, `large` = 24px
20
27
  * (matching `Button`). Omit the attribute or pass `'medium'` for the
21
28
  * default — both render identically and emit no DOM attribute.
@@ -45,6 +52,32 @@ export interface TagProps extends BaseProps {
45
52
  * Requires `@antadesign/anta/elements` to be imported (client-side only)
46
53
  * so the CSS ships with the page.
47
54
  *
55
+ * Styling notes (`a-tag.css` ships comment-free):
56
+ * - Sizing is intrinsic — no fixed height, like `<a-button>`: height falls
57
+ * out of `line-height` + `padding-block` + the 0.5px border (the base
58
+ * 1.5px block padding compensates the half-pixel border to keep the pill
59
+ * at 20px), so text is never clipped and the padding tokens can be
60
+ * retuned freely. An edge icon trims ~2px off its side's padding
61
+ * (optical), and icons scale to `--tag-icon-size`.
62
+ * - Color comes from the theme-aware semantic tokens, so named tones need
63
+ * no `.dark` rules; the hairline border and the segment divider both
64
+ * derive from `--tag-text`, so every tone gets a matching edge. A lone
65
+ * `label` is dropped into `<a-tag-value>` by this wrapper so it keeps the
66
+ * default weight; `<a-tag-label>` only renders as the bold key before a
67
+ * value (weight contrast does the separating — no divider).
68
+ * - Segmented children: raw children (not the structured label/value/icon
69
+ * elements) get a hairline left border per segment after the first; the
70
+ * flex `gap` sits left of the border and `padding-left` balances it.
71
+ * - Custom tones (any non-named `tone`) keep the source hue with
72
+ * lightness/chroma pinned via oklch relative color; the `--_tag-*` knobs
73
+ * are the only numbers to tune and the `.dark` block re-tunes them. The
74
+ * wrapper writes `--tag-tone-source` inline; a typed `attr()` fallback
75
+ * picks up raw `<a-tag tone="…">` on Chrome 133+/Safari 18.2+.
76
+ * - `nocaps` drops the uppercase transform and tightens tracking to the
77
+ * body-text 0.02ch (uppercase needs 0.08ch); tabular figures + `ss05`
78
+ * stay on. Large + nocaps bumps to 13px, keeping the same +1px
79
+ * over-uppercase relationship medium has, with height unchanged.
80
+ *
48
81
  * @example Basic usage
49
82
  * ```tsx
50
83
  * <Tag tone="success" label="Running" />
@@ -52,4 +85,4 @@ export interface TagProps extends BaseProps {
52
85
  * <Tag tone="brand" size="small" nocaps value="v2.1.0" />
53
86
  * ```
54
87
  */
55
- export declare const Tag: ({ icon, iconTrailing, label, value, tone, size, nocaps, className, style, children, ...rest }: TagProps) => any;
88
+ export declare const Tag: ({ icon, iconTrailing, label, value, tone, priority, size, nocaps, className, style, children, ...rest }: TagProps) => any;
@@ -1,11 +1,13 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- const NAMED_TONES = /* @__PURE__ */ new Set(["neutral", "brand", "info", "success", "warning", "critical"]);
2
+ import { toneStyle } from "../anta_helpers";
3
+ import { Icon } from "./Icon";
3
4
  const Tag = ({
4
5
  icon,
5
6
  iconTrailing,
6
7
  label,
7
8
  value,
8
9
  tone,
10
+ priority,
9
11
  size,
10
12
  nocaps,
11
13
  className,
@@ -13,24 +15,26 @@ const Tag = ({
13
15
  children,
14
16
  ...rest
15
17
  }) => {
16
- const isCustomTone = tone != null && !NAMED_TONES.has(tone);
17
- const computedStyle = isCustomTone ? { ...style, ["--tag-tone-source"]: tone } : style;
18
+ const computedStyle = toneStyle(tone, "--tag-tone-source", style);
18
19
  const hasValue = value != null;
20
+ const isIconOnly = icon != null && label == null && value == null && children == null && iconTrailing == null;
19
21
  return /* @__PURE__ */ jsxs(
20
22
  "a-tag",
21
23
  {
22
24
  tone,
25
+ "aria-label": isIconOnly ? `${icon} tag` : void 0,
26
+ priority: priority && priority !== "secondary" ? priority : void 0,
23
27
  size: size && size !== "medium" ? size : void 0,
24
28
  nocaps: nocaps ? "" : void 0,
25
29
  class: className,
26
30
  style: computedStyle,
27
31
  ...rest,
28
32
  children: [
29
- icon && /* @__PURE__ */ jsx("a-icon", { shape: icon, "aria-hidden": "true" }),
33
+ icon && /* @__PURE__ */ jsx(Icon, { shape: icon }),
30
34
  label != null && (hasValue ? /* @__PURE__ */ jsx("a-tag-label", { children: label }) : /* @__PURE__ */ jsx("a-tag-value", { children: label })),
31
35
  hasValue && /* @__PURE__ */ jsx("a-tag-value", { children: value }),
32
36
  children,
33
- iconTrailing && /* @__PURE__ */ jsx("a-icon", { shape: iconTrailing, "aria-hidden": "true" })
37
+ iconTrailing && /* @__PURE__ */ jsx(Icon, { shape: iconTrailing })
34
38
  ]
35
39
  }
36
40
  );
@@ -1,28 +1,42 @@
1
1
  import type { BaseProps } from "../general_types";
2
- export interface TextProps extends BaseProps {
2
+ /** Truncation / expansion axis. `expandable` only takes effect with `truncate`;
3
+ * `collapsible` only with `expandable` — so the type forbids `collapsible`
4
+ * unless `expandable` is set (a dynamic `expandable={cond}` is still allowed). */
5
+ type ExpandMode = {
6
+ expandable?: false;
7
+ collapsible?: never;
8
+ } | {
9
+ /** Show a fade hint and chevron over the truncated text and let the user
10
+ * expand it by clicking the chevron region or pressing Enter while the
11
+ * chevron has keyboard focus. Only takes effect together with `truncate`.
12
+ * On its own, expanding is **one-way** — the control is removed once
13
+ * expanded; add `collapsible` for a two-way toggle. */
14
+ expandable: boolean;
15
+ /** Let the reader collapse back after expanding: the chevron becomes a
16
+ * "Show more" / "Show less" toggle that stays visible while expanded.
17
+ * Only takes effect together with `expandable`. */
18
+ collapsible?: boolean;
19
+ };
20
+ export type TextProps = BaseProps & {
3
21
  /** Visual priority. Maps to text-1..text-5 (`primary` = text-1, the
4
22
  * strongest). The default is `secondary` (text-2) — body text reads a
5
23
  * step softer than the strongest foreground; pass `primary` for emphasis.
6
24
  * @defaultValue secondary */
7
25
  priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary';
8
26
  /** Color tint. Applies the matching `--text-{N}-{tone}` palette. */
9
- tone?: 'brand' | 'success' | 'critical' | 'warning' | 'info';
27
+ tone?: 'brand' | 'info' | 'success' | 'warning' | 'critical';
10
28
  /** Type scale. `small` = 13/16, `medium` = 15/20, `large` = 17/24.
11
29
  * @defaultValue medium */
12
30
  size?: 'small' | 'medium' | 'large';
13
31
  /** Render as inline-block instead of the default block element. */
14
32
  inline?: boolean;
15
33
  /** Truncate with a trailing ellipsis. `true` (or `1`) clamps to a
16
- * single line; any integer ≥ 2 clamps to that many lines. Uses the
17
- * `-webkit-line-clamp` technique, supported in all major browsers
18
- * (Firefox 68+, Chrome, Safari, Edge). */
34
+ * single line; any integer ≥ 2 clamps to that many lines; `0` or a
35
+ * negative value means no truncation. Uses the `-webkit-line-clamp`
36
+ * technique, supported in all major browsers (Firefox 68+, Chrome,
37
+ * Safari, Edge). */
19
38
  truncate?: boolean | number;
20
- /** Show a fade hint and chevron over the truncated text and let the
21
- * user expand it by clicking the chevron region or pressing Enter
22
- * while the chevron has keyboard focus. Only takes effect together
23
- * with `truncate`. */
24
- expandable?: boolean;
25
- }
39
+ } & ExpandMode;
26
40
  /**
27
41
  * Block-level text container with priority and tone support.
28
42
  *
@@ -45,4 +59,5 @@ export interface TextProps extends BaseProps {
45
59
  * <Text truncate={3} expandable>…long paragraph…</Text>
46
60
  * ```
47
61
  */
48
- export declare const Text: ({ priority, tone, size, inline, truncate, expandable, className, style, children, ...rest }: TextProps) => any;
62
+ export declare const Text: ({ priority, tone, size, inline, truncate, expandable, collapsible, className, style, children, ...rest }: TextProps) => any;
63
+ export {};
@@ -1,7 +1,9 @@
1
1
  import { jsx } from "@antadesign/anta/jsx-runtime";
2
- const Text = ({ priority, tone, size, inline, truncate, expandable, className, style, children, ...rest }) => {
3
- const lineCount = typeof truncate === "number" ? truncate : truncate ? 1 : null;
2
+ const Text = ({ priority, tone, size, inline, truncate, expandable, collapsible, className, style, children, ...rest }) => {
3
+ const n = typeof truncate === "number" ? truncate : truncate ? 1 : null;
4
+ const lineCount = n != null && n >= 1 ? n : null;
4
5
  const computedStyle = lineCount != null ? { ...style, ["--line-clamp"]: lineCount } : style;
6
+ const canExpand = expandable && lineCount != null;
5
7
  return /* @__PURE__ */ jsx(
6
8
  "a-text",
7
9
  {
@@ -10,7 +12,8 @@ const Text = ({ priority, tone, size, inline, truncate, expandable, className, s
10
12
  size,
11
13
  inline: inline ? "" : void 0,
12
14
  truncate: lineCount != null ? String(lineCount) : void 0,
13
- expandable: expandable && truncate ? "" : void 0,
15
+ expandable: canExpand ? "" : void 0,
16
+ collapsible: canExpand && collapsible ? "" : void 0,
14
17
  class: className,
15
18
  style: computedStyle,
16
19
  ...rest,
@@ -9,7 +9,7 @@ export interface TitleProps extends BaseProps {
9
9
  * @defaultValue primary */
10
10
  priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary';
11
11
  /** Color tint. Applies the matching `--text-{N}-{tone}` palette. */
12
- tone?: 'brand' | 'success' | 'critical' | 'warning' | 'info';
12
+ tone?: 'brand' | 'info' | 'success' | 'warning' | 'critical';
13
13
  }
14
14
  /**
15
15
  * Block-level heading with level 1-6, priority, and tone.
@@ -24,6 +24,15 @@ export interface TitleProps extends BaseProps {
24
24
  * so use a real heading tag if SEO matters and you don't need the
25
25
  * `tone` / `priority` props.
26
26
  *
27
+ * Styling notes (`a-title.css` ships comment-free): `<a-title>` is
28
+ * intentionally CSS-only — no JS, no shadow DOM, not even
29
+ * `customElements.define`; the browser treats it as a generic unknown
30
+ * element and the CSS gives it block layout, the demi-bold variable-font
31
+ * weight, and the per-level type scale + vertical rhythm. The matching
32
+ * `h1`–`h6` rules in `src/reset.css` are kept in lockstep so raw markup
33
+ * looks the same as `<Title level={n}>`. The tone × priority color matrix
34
+ * has the same shape as `a-text`'s.
35
+ *
27
36
  * Requires `@antadesign/anta/elements` to be imported (client-side only)
28
37
  * so the CSS ships with the page.
29
38
  *
@@ -11,12 +11,14 @@ export interface TooltipProps extends BaseProps {
11
11
  * side when there isn't room.
12
12
  * @defaultValue bottom */
13
13
  placement?: 'top' | 'bottom';
14
- /** Pin the bubble under the anchor instead of following the cursor. */
15
- static?: boolean;
14
+ /** Follow the cursor instead of pinning under the anchor. The bubble is
15
+ * pinned (anchored beneath the target) by default; pass `follow` for the
16
+ * cursor-tracking behaviour, which fades by distance as the cursor leaves. */
17
+ follow?: boolean;
16
18
  /** Make the bubble hoverable and clickable — enables pointer events and
17
19
  * keeps it open while the cursor is over it, so its content (links,
18
- * buttons) can be interacted with. Implies `static` (an interactive
19
- * bubble can't follow the cursor). */
20
+ * buttons) can be interacted with. Always pinned (an interactive bubble
21
+ * can't follow the cursor, even with `follow`). */
20
22
  interactive?: boolean;
21
23
  }
22
24
  /**
@@ -27,8 +29,8 @@ export interface TooltipProps extends BaseProps {
27
29
  * Shows on hover (after `delay`) and on keyboard focus; dismisses on mouse
28
30
  * leave, blur, Escape, or when the anchor scrolls away. On touch devices it
29
31
  * opens on press-and-hold (a tap never surfaces it) and lingers briefly after
30
- * release. Follows the cursor by default — pass `static` to pin it under the
31
- * anchor instead.
32
+ * release. Pinned under the anchor by default — pass `follow` to make it track
33
+ * the cursor instead.
32
34
  *
33
35
  * Requires `@antadesign/anta/elements` to be imported (client-side only)
34
36
  * to register the underlying custom element.
@@ -44,14 +46,22 @@ export interface TooltipProps extends BaseProps {
44
46
  * </button>
45
47
  * ```
46
48
  *
47
- * @example Pinned above, rich content
49
+ * @example Above the anchor, rich content
48
50
  * ```tsx
49
51
  * <span style={{ cursor: 'help' }}>
50
52
  * Status
51
- * <Tooltip placement="top" static>
53
+ * <Tooltip placement="top">
52
54
  * <strong>Healthy</strong> — last checked 2m ago
53
55
  * </Tooltip>
54
56
  * </span>
55
57
  * ```
58
+ *
59
+ * @example Follow the cursor
60
+ * ```tsx
61
+ * <button>
62
+ * Hover me
63
+ * <Tooltip follow>Tracks the pointer</Tooltip>
64
+ * </button>
65
+ * ```
56
66
  */
57
- export declare const Tooltip: ({ delay, placement, static: isStatic, interactive, className, children, ...rest }: TooltipProps) => any;
67
+ export declare const Tooltip: ({ delay, placement, follow, interactive, className, children, ...rest }: TooltipProps) => any;
@@ -2,7 +2,7 @@ import { jsx } from "@antadesign/anta/jsx-runtime";
2
2
  const Tooltip = ({
3
3
  delay,
4
4
  placement,
5
- static: isStatic,
5
+ follow,
6
6
  interactive,
7
7
  className,
8
8
  children,
@@ -13,7 +13,7 @@ const Tooltip = ({
13
13
  {
14
14
  delay: delay != null ? String(delay) : void 0,
15
15
  placement: placement === "top" ? "top" : void 0,
16
- static: isStatic ? "" : void 0,
16
+ follow: follow ? "" : void 0,
17
17
  interactive: interactive ? "" : void 0,
18
18
  class: className,
19
19
  ...rest,
@@ -1 +1 @@
1
- @layer anta{a-button,a[role=button]{--button-primary-fg: #ffffff;--button-focus: #503cb4;--bg-primary-disabled: #ece9ec;--bg-secondary-disabled: #f6f4f6;--fg-disabled-primary: #afa9b1;--fg-disabled: #afa9b1;--button-loading-stripe: 14px;--button-loading-stripe-gap: 16px;--button-loading-period: 30px;--button-loading-angle: 125deg;--button-loading-x-period: calc( var(--button-loading-period) / cos(var(--button-loading-angle) - 90deg) );--button-loading-opacity: .15;--button-loading-blur: 2.5px;--button-bg-primary-rest: #635b65;--button-bg-primary-hover: #534c57;--button-bg-primary-active: #49424c;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #45374c12;--button-bg-secondary-hover: #44374b1a;--button-bg-secondary-active: #44374b26;--button-fg-secondary-rest: #534c57;--button-fg-secondary-hover: #49424c;--button-fg-secondary-l-shift: .05;--button-fg-tertiary-rest: #635b65;--button-fg-tertiary-hover: #534c57;--button-bg-tertiary-hover: #44374b0d;--button-bg-tertiary-active: #44374b1a;--button-fg-quaternary-rest: #635b65;--button-fg-quaternary-hover: #49424c;--button-padding-x: 9px;--button-padding-y: 5px;--button-max-width: 100%;--button-max-height: 100%;--button-timing-in: 75ms ease-in;--button-timing-active: 50ms linear;--button-timing-out: .15s ease-out;--button-loading-duration: .5s}a-button[tone=brand],a[role=button][tone=brand]{--button-bg-primary-rest: #5f4bc3;--button-bg-primary-hover: #503cb4;--button-bg-primary-active: #483493;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #7460d71a;--button-bg-secondary-hover: #7460d726;--button-bg-secondary-active: #7460d733;--button-fg-secondary-rest: #5f4bc3;--button-fg-secondary-hover: #503cb4;--button-fg-tertiary-rest: #5f4bc3;--button-fg-tertiary-hover: #503cb4;--button-bg-tertiary-hover: #7460d71a;--button-bg-tertiary-active: #7460d726;--button-fg-quaternary-rest: #5f4bc3;--button-fg-quaternary-hover: #483493}a-button[tone=critical],a[role=button][tone=critical]{--button-bg-primary-rest: #c9302c;--button-bg-primary-hover: #b02120;--button-bg-primary-active: #a01c1c;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #de45451a;--button-bg-secondary-hover: #de454526;--button-bg-secondary-active: #de454533;--button-fg-secondary-rest: #c9302c;--button-fg-secondary-hover: #b02120;--button-fg-tertiary-rest: #c9302c;--button-fg-tertiary-hover: #b02120;--button-bg-tertiary-hover: #de45451a;--button-bg-tertiary-active: #de454533;--button-fg-quaternary-rest: #c9302c;--button-fg-quaternary-hover: #a01c1c}a-button[tone=info],a[role=button][tone=info]{--button-bg-primary-rest: #1f6eb2;--button-bg-primary-hover: #1a5b93;--button-bg-primary-active: #175082;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #2686d91a;--button-bg-secondary-hover: #2686d926;--button-bg-secondary-active: #2686d933;--button-fg-secondary-rest: #1f6eb2;--button-fg-secondary-hover: #1a5b93;--button-fg-tertiary-rest: #1f6eb2;--button-fg-tertiary-hover: #1a5b93;--button-bg-tertiary-hover: #2686d91a;--button-bg-tertiary-active: #2686d926;--button-fg-quaternary-rest: #1f6eb2;--button-fg-quaternary-hover: #175082}a-button[tone=success],a[role=button][tone=success]{--button-bg-primary-rest: #2a7e43;--button-bg-primary-hover: #226737;--button-bg-primary-active: #1f5c31;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #3295501a;--button-bg-secondary-hover: #32955026;--button-bg-secondary-active: #32955033;--button-fg-secondary-rest: #2a7e43;--button-fg-secondary-hover: #226737;--button-fg-tertiary-rest: #2a7e43;--button-fg-tertiary-hover: #226737;--button-bg-tertiary-hover: #3295501a;--button-bg-tertiary-active: #32955026;--button-fg-quaternary-rest: #2a7e43;--button-fg-quaternary-hover: #1f5c31}a-button[tone=warning],a[role=button][tone=warning]{--button-bg-primary-rest: #c37416;--button-bg-primary-hover: #ae6613;--button-bg-primary-active: #995200;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #c374161a;--button-bg-secondary-hover: #c3741626;--button-bg-secondary-active: #c3741633;--button-fg-secondary-rest: #c37416;--button-fg-secondary-hover: #ae6613;--button-fg-tertiary-rest: #c37416;--button-fg-tertiary-hover: #ae6613;--button-bg-tertiary-hover: #c374161a;--button-bg-tertiary-active: #c3741633;--button-fg-quaternary-rest: #c37416;--button-fg-quaternary-hover: #995200}.dark a-button,.dark a[role=button]{--button-focus: #a897fc;--bg-primary-disabled: #272329;--bg-secondary-disabled: #1d1a1e;--fg-disabled-primary: #776e77;--fg-disabled: #635b65;--button-bg-primary-rest: #534c57;--button-bg-primary-hover: #635b65;--button-bg-primary-active: #938d96;--button-bg-secondary-rest: #e4d1ef1c;--button-bg-secondary-hover: #e4d1ef24;--button-bg-secondary-active: #e4d1ef2e;--button-fg-secondary-rest: #c1b9c1;--button-fg-secondary-hover: #d4ced4;--button-fg-secondary-l-shift: 0;--button-fg-tertiary-rest: #afa9b1;--button-fg-tertiary-hover: #afa9b1;--button-bg-tertiary-hover: #e4d1ef14;--button-bg-tertiary-active: #e4d1ef21;--button-fg-quaternary-rest: #afa9b1;--button-fg-quaternary-hover: #cac4ca}.dark a-button[tone=brand],.dark a[role=button][tone=brand]{--button-bg-primary-rest: #503cb4;--button-bg-primary-hover: #5f4bc3;--button-bg-primary-active: #7460d7;--button-bg-secondary-rest: #7460d73b;--button-bg-secondary-hover: #7460d747;--button-bg-secondary-active: #7460d754;--button-fg-secondary-rest: #c5baff;--button-fg-secondary-hover: #d2cbf6;--button-fg-tertiary-rest: #ada0ee;--button-fg-tertiary-hover: #bcb1f1;--button-bg-tertiary-hover: #7460d73b;--button-bg-tertiary-active: #7460d747;--button-fg-quaternary-rest: #ada0ee;--button-fg-quaternary-hover: #c7bef4}.dark a-button[tone=critical],.dark a[role=button][tone=critical]{--button-bg-primary-rest: #b02120;--button-bg-primary-hover: #c9302c;--button-bg-primary-active: #de4545;--button-bg-secondary-rest: #de45453b;--button-bg-secondary-hover: #de454547;--button-bg-secondary-active: #de454554;--button-fg-secondary-rest: #ffabac;--button-fg-secondary-hover: #f4c2c2;--button-fg-tertiary-rest: #e78e90;--button-fg-tertiary-hover: #efa4a4;--button-bg-tertiary-hover: #de45453b;--button-bg-tertiary-active: #de454547;--button-fg-quaternary-rest: #e78e90;--button-fg-quaternary-hover: #ffabac}.dark a-button[tone=info],.dark a[role=button][tone=info]{--button-bg-primary-rest: #1a5b93;--button-bg-primary-hover: #1f6eb2;--button-bg-primary-active: #2686d9;--button-bg-secondary-rest: #2686d93b;--button-bg-secondary-hover: #2686d947;--button-bg-secondary-active: #2686d954;--button-fg-secondary-rest: #9ed2ff;--button-fg-secondary-hover: #bad6f3;--button-fg-tertiary-rest: #7db6e8;--button-fg-tertiary-hover: #93c5ec;--button-bg-tertiary-hover: #2686d93b;--button-bg-tertiary-active: #2686d947;--button-fg-quaternary-rest: #7db6e8;--button-fg-quaternary-hover: #a6cdef}.dark a-button[tone=success],.dark a[role=button][tone=success]{--button-bg-primary-rest: #226737;--button-bg-primary-hover: #2a7e43;--button-bg-primary-active: #329550;--button-bg-secondary-rest: #3295503b;--button-bg-secondary-hover: #32955047;--button-bg-secondary-active: #32955054;--button-fg-secondary-rest: #8ceca9;--button-fg-secondary-hover: #b3e5c2;--button-fg-tertiary-rest: #74cd8e;--button-fg-tertiary-hover: #88d7a0;--button-bg-tertiary-hover: #3295503b;--button-bg-tertiary-active: #32955047;--button-fg-quaternary-rest: #74cd8e;--button-fg-quaternary-hover: #9ddeb1}.dark a-button[tone=warning],.dark a[role=button][tone=warning]{--button-bg-primary-rest: #7f410b;--button-bg-primary-hover: #995200;--button-bg-primary-active: #ae6613;--button-bg-secondary-rest: #c374163b;--button-bg-secondary-hover: #c3741647;--button-bg-secondary-active: #c3741654;--button-fg-secondary-rest: #f7c06e;--button-fg-secondary-hover: #f3cc91;--button-fg-tertiary-rest: #e1a452;--button-fg-tertiary-hover: #edb25a;--button-bg-tertiary-hover: #c374163b;--button-bg-tertiary-active: #c3741647;--button-fg-quaternary-rest: #e1a452;--button-fg-quaternary-hover: #f0bf75}a-button,a[role=button]{user-select:none;display:inline-flex;align-items:center;gap:.5ch;overflow:hidden;cursor:pointer;flex-shrink:0;color:var(--button-fg);background-color:var(--button-bg);border-radius:4px;text-decoration:none;box-shadow:inset 0 0 1px color-mix(in oklch,currentColor,transparent 70%);font-size:15px;font-family:var(--sans-serif);font-weight:450;font-variation-settings:"wdth" 88,"slnt" 0,"ital" 0;line-height:18px;letter-spacing:.05ch;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;max-width:var(--button-max-width);max-height:var(--button-max-height);padding-inline:var(--button-padding-x);padding-block:var(--button-padding-y);>a-button-label{display:inline-block;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;overflow:hidden;min-width:0;line-height:17px;padding-bottom:1px;&:has(>*){display:inline-flex;gap:.25ch}}>*{pointer-events:none}& a-icon{transition:color var(--button-timing-out)}transition:color var(--button-timing-out),background-color var(--button-timing-out);&:hover,&:focus-visible{transition:color var(--button-timing-in),background-color var(--button-timing-in);& a-icon{transition:color var(--button-timing-in)}}&:active,&[selected]{transition:color var(--button-timing-active),background-color var(--button-timing-active);& a-icon{transition:color var(--button-timing-active)}}&[disabled]{pointer-events:none;cursor:not-allowed;transition:none;& a-icon{transition:none}}&:focus-visible{outline:1px solid var(--button-focus);outline-offset:1px}&[priority=quaternary]{--button-timing-in: 0s;--button-timing-active: 0s;--button-timing-out: 0s}&[size=small]{--button-padding-y: 3px;--button-padding-x: 7px}&[size=large]{--button-padding-y: 7px;--button-padding-x: 13px}&[priority=tertiary],&[priority=quaternary]{&[underline=solid]{text-decoration:underline solid}&[underline=dashed]{text-decoration:underline dashed}&[underline=dotted]{text-decoration:underline dotted}&[underline]{text-decoration-color:color-mix(in srgb,currentColor 75%,transparent);text-decoration-thickness:1px;text-underline-offset:3px;&[selected]{text-decoration-color:var(--button-fg);text-decoration-thickness:1px}@media(hover:hover)and (pointer:fine){&:hover{text-decoration-color:var(--button-fg);text-decoration-thickness:1px}}}}&[priority=quaternary][paddingless]{--button-padding-x: 0;--button-padding-y: 0}&:has(>a-icon:only-child){--button-padding-y: 5px;--button-padding-x: 5px;min-width:28px;min-height:28px;justify-content:center;&[size=small]{--button-padding-y: 3px;--button-padding-x: 3px;min-width:24px;min-height:24px}&[size=large]{--button-padding-y: 7px;--button-padding-x: 7px;min-width:32px;min-height:32px}}&:has(>a-icon:first-child:not(:only-child)){padding-inline-start:max(0px,var(--button-padding-x) - 2px)}&:has(>a-icon:last-child:not(:only-child)){padding-inline-end:max(0px,var(--button-padding-x) - 2px)}&[loading]{position:relative;pointer-events:none;cursor:wait;&:before{content:"";position:absolute;top:0;bottom:0;left:calc(0px - var(--button-loading-x-period));right:0;pointer-events:none;background:repeating-linear-gradient(var(--button-loading-angle),transparent 0,transparent var(--button-loading-stripe-gap),currentColor var(--button-loading-stripe-gap),currentColor calc(var(--button-loading-stripe-gap) + var(--button-loading-stripe)));opacity:var(--button-loading-opacity);filter:blur(var(--button-loading-blur));will-change:transform;animation:btn-loading-slide var(--button-loading-duration) linear infinite;animation-delay:-9999s}}&[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=critical],[tone=info],[tone=success],[tone=warning]){--button-tone-source: attr(tone type(<color>), transparent);--_tone-fg-l: .46;--_tone-fg-strong-l: .4;--_tone-fg-c: .17;--_tone-bg-l: .54;--_tone-bg-c: .16;--_tone-bg-a-rest: .1;--_tone-bg-a-hover: .15;--_tone-bg-a-active: .2;--_tone-primary-l-rest: .5;--_tone-primary-l-hover: .45;--_tone-primary-l-active: .4;--button-bg-primary-rest: oklch(from var(--button-tone-source) var(--_tone-primary-l-rest) c h);--button-bg-primary-hover: oklch(from var(--button-tone-source) var(--_tone-primary-l-hover) c h);--button-bg-primary-active: oklch(from var(--button-tone-source) var(--_tone-primary-l-active) c h);--button-fg-primary-rest: var(--button-primary-fg);--button-fg-secondary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-secondary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-fg-tertiary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-tertiary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-fg-quaternary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-quaternary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-bg-secondary-rest: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-rest));--button-bg-secondary-hover: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-hover));--button-bg-secondary-active: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-active));--button-bg-tertiary-hover: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-rest));--button-bg-tertiary-active: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-hover))}.dark &[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=critical],[tone=info],[tone=success],[tone=warning]){--_tone-fg-l: .78;--_tone-fg-strong-l: .85;--_tone-fg-c: .11;--_tone-bg-l: .58;--_tone-bg-a-rest: .23;--_tone-bg-a-hover: .28;--_tone-bg-a-active: .33;--_tone-primary-l-rest: .45;--_tone-primary-l-hover: .5;--_tone-primary-l-active: .57}--button-fg: oklch(from var(--button-fg-secondary-rest) calc(l - var(--button-fg-secondary-l-shift)) c h);--button-bg: var(--button-bg-secondary-rest);@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-secondary-hover);--button-bg: var(--button-bg-secondary-hover)}}&:active,&[selected]{--button-fg: var(--button-fg-secondary-hover);--button-bg: var(--button-bg-secondary-active)}&[priority=primary]{--button-fg: var(--button-fg-primary-rest);--button-bg: var(--button-bg-primary-rest);box-shadow:none;@media(hover:hover)and (pointer:fine){&:hover{--button-bg: var(--button-bg-primary-hover)}}&:active,&[selected]{--button-bg: var(--button-bg-primary-active)}}&[priority=tertiary]{--button-fg: var(--button-fg-tertiary-rest);--button-bg: transparent;box-shadow:none;@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-tertiary-hover);--button-bg: var(--button-bg-tertiary-hover)}}&:active,&[selected]{--button-fg: var(--button-fg-tertiary-hover);--button-bg: var(--button-bg-tertiary-active)}}&[priority=quaternary]{--button-fg: color-mix(in oklch, var(--button-fg-quaternary-rest) 90%, transparent);--button-bg: transparent;box-shadow:none;font-weight:415;@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-quaternary-hover)}}&[selected]{--button-fg: var(--button-fg-quaternary-hover)}&:active{--button-fg: oklch(from var(--button-fg-quaternary-rest) calc(l + .05) c h)}.dark &:active{--button-fg: var(--button-fg-quaternary-rest)}}&[selected]{box-shadow:inset 0 0 0 1px currentColor}&[disabled]{background-color:var(--bg-secondary-disabled);color:var(--fg-disabled);&[priority=primary]{background-color:var(--bg-primary-disabled);color:var(--fg-disabled-primary)}&[priority=tertiary],&[priority=quaternary]{background-color:transparent;color:var(--fg-disabled)}}}}@keyframes btn-loading-slide{to{transform:translate(var(--button-loading-x-period))}}
1
+ @layer anta{a-button,a[role=button]{--button-primary-fg: #ffffff;--bg-primary-disabled: #ece9ec;--bg-secondary-disabled: #f6f4f6;--fg-disabled-primary: #afa9b1;--fg-disabled: #afa9b1;--button-loading-stripe: 14px;--button-loading-stripe-gap: 16px;--button-loading-period: 30px;--button-loading-angle: 125deg;--button-loading-x-period: calc( var(--button-loading-period) / cos(var(--button-loading-angle) - 90deg) );--button-loading-opacity: .15;--button-loading-blur: 2.5px;--button-bg-primary-rest: #635b65;--button-bg-primary-hover: #534c57;--button-bg-primary-active: #49424c;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #45374c12;--button-bg-secondary-hover: #44374b1a;--button-bg-secondary-active: #44374b26;--button-fg-secondary-rest: #534c57;--button-fg-secondary-hover: #49424c;--button-fg-secondary-l-shift: .05;--button-fg-tertiary-rest: #635b65;--button-fg-tertiary-hover: #534c57;--button-bg-tertiary-hover: #44374b0d;--button-bg-tertiary-active: #44374b1a;--button-fg-quaternary-rest: #635b65;--button-fg-quaternary-hover: #49424c;--_fs: 15px;--_lh: 20px;--_pb: 1px;--button-padding-x: 9px;--button-padding-y: calc((8px - var(--_pb)) / 2);--button-max-width: 100%;--button-max-height: 100%;--button-timing-in: 75ms ease-in;--button-timing-active: 50ms linear;--button-timing-out: .15s ease-out;--button-loading-duration: .5s}a-button[tone=brand],a[role=button][tone=brand]{--button-bg-primary-rest: #5f4bc3;--button-bg-primary-hover: #503cb4;--button-bg-primary-active: #483493;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #7460d71a;--button-bg-secondary-hover: #7460d726;--button-bg-secondary-active: #7460d733;--button-fg-secondary-rest: #5f4bc3;--button-fg-secondary-hover: #503cb4;--button-fg-tertiary-rest: #5f4bc3;--button-fg-tertiary-hover: #503cb4;--button-bg-tertiary-hover: #7460d71a;--button-bg-tertiary-active: #7460d726;--button-fg-quaternary-rest: #5f4bc3;--button-fg-quaternary-hover: #483493}a-button[tone=critical],a[role=button][tone=critical]{--button-bg-primary-rest: #c9302c;--button-bg-primary-hover: #b02120;--button-bg-primary-active: #a01c1c;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #de45451a;--button-bg-secondary-hover: #de454526;--button-bg-secondary-active: #de454533;--button-fg-secondary-rest: #c9302c;--button-fg-secondary-hover: #b02120;--button-fg-tertiary-rest: #c9302c;--button-fg-tertiary-hover: #b02120;--button-bg-tertiary-hover: #de45451a;--button-bg-tertiary-active: #de454533;--button-fg-quaternary-rest: #c9302c;--button-fg-quaternary-hover: #a01c1c}a-button[tone=info],a[role=button][tone=info]{--button-bg-primary-rest: #1f6eb2;--button-bg-primary-hover: #1a5b93;--button-bg-primary-active: #175082;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #2686d91a;--button-bg-secondary-hover: #2686d926;--button-bg-secondary-active: #2686d933;--button-fg-secondary-rest: #1f6eb2;--button-fg-secondary-hover: #1a5b93;--button-fg-tertiary-rest: #1f6eb2;--button-fg-tertiary-hover: #1a5b93;--button-bg-tertiary-hover: #2686d91a;--button-bg-tertiary-active: #2686d926;--button-fg-quaternary-rest: #1f6eb2;--button-fg-quaternary-hover: #175082}a-button[tone=success],a[role=button][tone=success]{--button-bg-primary-rest: #2a7e43;--button-bg-primary-hover: #226737;--button-bg-primary-active: #1f5c31;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #3295501a;--button-bg-secondary-hover: #32955026;--button-bg-secondary-active: #32955033;--button-fg-secondary-rest: #2a7e43;--button-fg-secondary-hover: #226737;--button-fg-tertiary-rest: #2a7e43;--button-fg-tertiary-hover: #226737;--button-bg-tertiary-hover: #3295501a;--button-bg-tertiary-active: #32955026;--button-fg-quaternary-rest: #2a7e43;--button-fg-quaternary-hover: #1f5c31}a-button[tone=warning],a[role=button][tone=warning]{--button-bg-primary-rest: #c37416;--button-bg-primary-hover: #ae6613;--button-bg-primary-active: #995200;--button-fg-primary-rest: var(--button-primary-fg);--button-bg-secondary-rest: #c374161a;--button-bg-secondary-hover: #c3741626;--button-bg-secondary-active: #c3741633;--button-fg-secondary-rest: #c37416;--button-fg-secondary-hover: #ae6613;--button-fg-tertiary-rest: #c37416;--button-fg-tertiary-hover: #ae6613;--button-bg-tertiary-hover: #c374161a;--button-bg-tertiary-active: #c3741633;--button-fg-quaternary-rest: #c37416;--button-fg-quaternary-hover: #995200}.dark a-button,.dark a[role=button]{--bg-primary-disabled: #272329;--bg-secondary-disabled: #1d1a1e;--fg-disabled-primary: #776e77;--fg-disabled: #635b65;--button-bg-primary-rest: #534c57;--button-bg-primary-hover: #635b65;--button-bg-primary-active: #938d96;--button-bg-secondary-rest: #e4d1ef1c;--button-bg-secondary-hover: #e4d1ef24;--button-bg-secondary-active: #e4d1ef2e;--button-fg-secondary-rest: #c1b9c1;--button-fg-secondary-hover: #d4ced4;--button-fg-secondary-l-shift: 0;--button-fg-tertiary-rest: #afa9b1;--button-fg-tertiary-hover: #afa9b1;--button-bg-tertiary-hover: #e4d1ef14;--button-bg-tertiary-active: #e4d1ef21;--button-fg-quaternary-rest: #afa9b1;--button-fg-quaternary-hover: #cac4ca}.dark a-button[tone=brand],.dark a[role=button][tone=brand]{--button-bg-primary-rest: #503cb4;--button-bg-primary-hover: #5f4bc3;--button-bg-primary-active: #7460d7;--button-bg-secondary-rest: #7460d73b;--button-bg-secondary-hover: #7460d747;--button-bg-secondary-active: #7460d754;--button-fg-secondary-rest: #c5baff;--button-fg-secondary-hover: #d2cbf6;--button-fg-tertiary-rest: #ada0ee;--button-fg-tertiary-hover: #bcb1f1;--button-bg-tertiary-hover: #7460d73b;--button-bg-tertiary-active: #7460d747;--button-fg-quaternary-rest: #ada0ee;--button-fg-quaternary-hover: #c7bef4}.dark a-button[tone=critical],.dark a[role=button][tone=critical]{--button-bg-primary-rest: #b02120;--button-bg-primary-hover: #c9302c;--button-bg-primary-active: #de4545;--button-bg-secondary-rest: #de45453b;--button-bg-secondary-hover: #de454547;--button-bg-secondary-active: #de454554;--button-fg-secondary-rest: #ffabac;--button-fg-secondary-hover: #f4c2c2;--button-fg-tertiary-rest: #e78e90;--button-fg-tertiary-hover: #efa4a4;--button-bg-tertiary-hover: #de45453b;--button-bg-tertiary-active: #de454547;--button-fg-quaternary-rest: #e78e90;--button-fg-quaternary-hover: #ffabac}.dark a-button[tone=info],.dark a[role=button][tone=info]{--button-bg-primary-rest: #1a5b93;--button-bg-primary-hover: #1f6eb2;--button-bg-primary-active: #2686d9;--button-bg-secondary-rest: #2686d93b;--button-bg-secondary-hover: #2686d947;--button-bg-secondary-active: #2686d954;--button-fg-secondary-rest: #9ed2ff;--button-fg-secondary-hover: #bad6f3;--button-fg-tertiary-rest: #7db6e8;--button-fg-tertiary-hover: #93c5ec;--button-bg-tertiary-hover: #2686d93b;--button-bg-tertiary-active: #2686d947;--button-fg-quaternary-rest: #7db6e8;--button-fg-quaternary-hover: #a6cdef}.dark a-button[tone=success],.dark a[role=button][tone=success]{--button-bg-primary-rest: #226737;--button-bg-primary-hover: #2a7e43;--button-bg-primary-active: #329550;--button-bg-secondary-rest: #3295503b;--button-bg-secondary-hover: #32955047;--button-bg-secondary-active: #32955054;--button-fg-secondary-rest: #8ceca9;--button-fg-secondary-hover: #b3e5c2;--button-fg-tertiary-rest: #74cd8e;--button-fg-tertiary-hover: #88d7a0;--button-bg-tertiary-hover: #3295503b;--button-bg-tertiary-active: #32955047;--button-fg-quaternary-rest: #74cd8e;--button-fg-quaternary-hover: #9ddeb1}.dark a-button[tone=warning],.dark a[role=button][tone=warning]{--button-bg-primary-rest: #7f410b;--button-bg-primary-hover: #995200;--button-bg-primary-active: #ae6613;--button-bg-secondary-rest: #c374163b;--button-bg-secondary-hover: #c3741647;--button-bg-secondary-active: #c3741654;--button-fg-secondary-rest: #f7c06e;--button-fg-secondary-hover: #f3cc91;--button-fg-tertiary-rest: #e1a452;--button-fg-tertiary-hover: #edb25a;--button-bg-tertiary-hover: #c374163b;--button-bg-tertiary-active: #c3741647;--button-fg-quaternary-rest: #e1a452;--button-fg-quaternary-hover: #f0bf75}a-button,a[role=button]{user-select:none;display:inline-flex;align-items:center;gap:.5ch;overflow:hidden;cursor:pointer;flex-shrink:0;color:var(--button-fg);background-color:var(--button-bg);border-radius:4px;text-decoration:none;box-shadow:inset 0 0 1px color-mix(in oklch,currentColor,transparent 70%);font-size:var(--_fs);font-family:var(--sans-serif);font-weight:450;font-variation-settings:"wdth" 88,"slnt" 0,"ital" 0;font-feature-settings:"ss02","ss05";line-height:var(--_lh);letter-spacing:.05ch;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;max-width:var(--button-max-width);max-height:var(--button-max-height);padding-inline:var(--button-padding-x);padding-block:var(--button-padding-y);>a-button-label{display:inline-block;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;overflow:hidden;min-width:0;line-height:var(--_lh);padding-bottom:var(--_pb);&:has(>*){display:inline-flex;gap:.25ch}}>*{pointer-events:none}& a-icon{transition:color var(--button-timing-out)}transition:color var(--button-timing-out),background-color var(--button-timing-out);&:hover,&:focus-visible{transition:color var(--button-timing-in),background-color var(--button-timing-in);& a-icon{transition:color var(--button-timing-in)}}&:active,&[selected]{transition:color var(--button-timing-active),background-color var(--button-timing-active);& a-icon{transition:color var(--button-timing-active)}}&[disabled]{pointer-events:none;cursor:not-allowed;transition:none;& a-icon{transition:none}}&:focus-visible{outline:1px solid var(--focus-ring);outline-offset:1px}&[priority=quaternary]{--button-timing-in: 0s;--button-timing-active: 0s;--button-timing-out: 0s}&[size=small]{--button-padding-x: 7px;--_fs: 13px;--_lh: 16px;--_pb: .5px;& a-icon{--icon-size: 14px}}&[size=large]{--button-padding-x: 13px;--_fs: 17px;--_lh: 24px;--_pb: 1.5px;& a-icon{--icon-size: 18px}}&[priority=tertiary],&[priority=quaternary]{&[underline=solid]{text-decoration:underline solid}&[underline=dashed]{text-decoration:underline dashed}&[underline=dotted]{text-decoration:underline dotted}&[underline]{text-decoration-color:color-mix(in srgb,currentColor 75%,transparent);text-decoration-thickness:1px;text-underline-offset:3px;&[selected]{text-decoration-color:var(--button-fg);text-decoration-thickness:1px}@media(hover:hover)and (pointer:fine){&:hover{text-decoration-color:var(--button-fg);text-decoration-thickness:1px}}}}&[priority=quaternary][paddingless]{--button-padding-x: 0;--button-padding-y: 0}&:has(>a-icon):not(:has(>a-icon~a-icon)):not(:has(>:not(a-icon):not(a-tooltip))){--button-padding-y: 5px;--button-padding-x: 5px;min-width:28px;min-height:28px;justify-content:center;&[size=small]{--button-padding-y: 3px;--button-padding-x: 3px;min-width:24px;min-height:24px}&[size=large]{--button-padding-y: 7px;--button-padding-x: 7px;min-width:32px;min-height:32px}}&:is(:has(>a-icon:first-child),:has(>a-tooltip:first-child+a-icon)):is(:has(>a-icon~a-icon),:has(>:not(a-icon):not(a-tooltip))){padding-inline-start:max(0px,var(--button-padding-x) - 2px)}&:is(:has(>a-icon:last-child),:has(>a-icon+a-tooltip:last-child)):is(:has(>a-icon~a-icon),:has(>:not(a-icon):not(a-tooltip))){padding-inline-end:max(0px,var(--button-padding-x) - 2px)}&[loading]{position:relative;pointer-events:none;cursor:wait;&:before{content:"";position:absolute;top:0;bottom:0;left:calc(0px - var(--button-loading-x-period));right:0;pointer-events:none;background:repeating-linear-gradient(var(--button-loading-angle),transparent 0,transparent var(--button-loading-stripe-gap),currentColor var(--button-loading-stripe-gap),currentColor calc(var(--button-loading-stripe-gap) + var(--button-loading-stripe)));opacity:var(--button-loading-opacity);filter:blur(var(--button-loading-blur));will-change:transform;animation:btn-loading-slide var(--button-loading-duration) linear infinite;animation-delay:-9999s}}&[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=critical],[tone=info],[tone=success],[tone=warning]){--button-tone-source: attr(tone type(<color>), transparent);--_tone-fg-l: .46;--_tone-fg-strong-l: .4;--_tone-fg-c: .17;--_tone-bg-l: .54;--_tone-bg-c: .16;--_tone-bg-a-rest: .1;--_tone-bg-a-hover: .15;--_tone-bg-a-active: .2;--_tone-primary-l-rest: .5;--_tone-primary-l-hover: .45;--_tone-primary-l-active: .4;--button-bg-primary-rest: oklch(from var(--button-tone-source) var(--_tone-primary-l-rest) c h);--button-bg-primary-hover: oklch(from var(--button-tone-source) var(--_tone-primary-l-hover) c h);--button-bg-primary-active: oklch(from var(--button-tone-source) var(--_tone-primary-l-active) c h);--button-fg-primary-rest: var(--button-primary-fg);--button-fg-secondary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-secondary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-fg-tertiary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-tertiary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-fg-quaternary-rest: oklch(from var(--button-tone-source) var(--_tone-fg-l) var(--_tone-fg-c) h);--button-fg-quaternary-hover: oklch(from var(--button-tone-source) var(--_tone-fg-strong-l) var(--_tone-fg-c) h);--button-bg-secondary-rest: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-rest));--button-bg-secondary-hover: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-hover));--button-bg-secondary-active: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-active));--button-bg-tertiary-hover: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-rest));--button-bg-tertiary-active: oklch(from var(--button-tone-source) var(--_tone-bg-l) var(--_tone-bg-c) h / var(--_tone-bg-a-hover))}.dark &[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=critical],[tone=info],[tone=success],[tone=warning]){--_tone-fg-l: .78;--_tone-fg-strong-l: .85;--_tone-fg-c: .11;--_tone-bg-l: .58;--_tone-bg-a-rest: .23;--_tone-bg-a-hover: .28;--_tone-bg-a-active: .33;--_tone-primary-l-rest: .45;--_tone-primary-l-hover: .5;--_tone-primary-l-active: .57}--button-fg: oklch(from var(--button-fg-secondary-rest) calc(l - var(--button-fg-secondary-l-shift)) c h);--button-bg: var(--button-bg-secondary-rest);@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-secondary-hover);--button-bg: var(--button-bg-secondary-hover)}}&:active,&[selected]{--button-fg: var(--button-fg-secondary-hover);--button-bg: var(--button-bg-secondary-active)}&[priority=primary]{--button-fg: var(--button-fg-primary-rest);--button-bg: var(--button-bg-primary-rest);box-shadow:none;@media(hover:hover)and (pointer:fine){&:hover{--button-bg: var(--button-bg-primary-hover)}}&:active,&[selected]{--button-bg: var(--button-bg-primary-active)}}&[priority=tertiary]{--button-fg: var(--button-fg-tertiary-rest);--button-bg: transparent;box-shadow:none;@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-tertiary-hover);--button-bg: var(--button-bg-tertiary-hover)}}&:active,&[selected]{--button-fg: var(--button-fg-tertiary-hover);--button-bg: var(--button-bg-tertiary-active)}}&[priority=quaternary]{--button-fg: var(--button-fg-quaternary-rest);--button-bg: transparent;box-shadow:none;font-weight:400;letter-spacing:.06ch;@media(hover:hover)and (pointer:fine){&:hover{--button-fg: var(--button-fg-quaternary-hover)}}&[selected]{--button-fg: var(--button-fg-quaternary-hover)}&:active{--button-fg: oklch(from var(--button-fg-quaternary-rest) calc(l + .05) c h)}.dark &:active{--button-fg: var(--button-fg-quaternary-rest)}}&[selected]{box-shadow:inset 0 0 0 1px currentColor}&[disabled]{background-color:var(--bg-secondary-disabled);color:var(--fg-disabled);&[priority=primary]{background-color:var(--bg-primary-disabled);color:var(--fg-disabled-primary)}&[priority=tertiary],&[priority=quaternary]{background-color:transparent;color:var(--fg-disabled)}}}}@keyframes btn-loading-slide{to{transform:translate(var(--button-loading-x-period))}}