@acronis-platform/ui-react 2.0.0 → 4.0.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.
- package/dist/components/ui/accordion-container/accordion-container.js +144 -0
- package/dist/components/ui/accordion-container/accordion-container.js.map +1 -0
- package/dist/components/ui/app-shell-chat/app-shell-chat.js.map +1 -1
- package/dist/components/ui/area-chart/area-chart.js +141 -139
- package/dist/components/ui/area-chart/area-chart.js.map +1 -1
- package/dist/components/ui/avatar/avatar.js +33 -22
- package/dist/components/ui/avatar/avatar.js.map +1 -1
- package/dist/components/ui/bar-chart/bar-chart.js +295 -293
- package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
- package/dist/components/ui/card/card.js +150 -74
- package/dist/components/ui/card/card.js.map +1 -1
- package/dist/components/ui/card-section/card-section.js +111 -0
- package/dist/components/ui/card-section/card-section.js.map +1 -0
- package/dist/components/ui/category-bar/category-bar.js +109 -93
- package/dist/components/ui/category-bar/category-bar.js.map +1 -1
- package/dist/components/ui/chart/chart-palette.js +113 -0
- package/dist/components/ui/chart/chart-palette.js.map +1 -0
- package/dist/components/ui/chart/chart.js +176 -129
- package/dist/components/ui/chart/chart.js.map +1 -1
- package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
- package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
- package/dist/components/ui/chart-state/chart-state.js +48 -34
- package/dist/components/ui/chart-state/chart-state.js.map +1 -1
- package/dist/components/ui/chart-widget/chart-widget.js +87 -0
- package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
- package/dist/components/ui/composed-chart/composed-chart.js +117 -115
- package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
- package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
- package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
- package/dist/components/ui/data-table/data-table.js +4 -2
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/empty-overlay/empty-overlay.js +49 -0
- package/dist/components/ui/empty-overlay/empty-overlay.js.map +1 -0
- package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
- package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
- package/dist/components/ui/histogram/histogram.js +94 -92
- package/dist/components/ui/histogram/histogram.js.map +1 -1
- package/dist/components/ui/input/input.js.map +1 -1
- package/dist/components/ui/label/label.js +2 -9
- package/dist/components/ui/label/label.js.map +1 -1
- package/dist/components/ui/line-chart/line-chart.js +143 -141
- package/dist/components/ui/line-chart/line-chart.js.map +1 -1
- package/dist/components/ui/metric/metric.js +74 -185
- package/dist/components/ui/metric/metric.js.map +1 -1
- package/dist/components/ui/page-content/page-content.js.map +1 -1
- package/dist/components/ui/pie-chart/pie-chart.js +201 -195
- package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
- package/dist/components/ui/radar-chart/radar-chart.js +133 -131
- package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
- package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
- package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
- package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
- package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
- package/dist/components/ui/section/section.js +157 -31
- package/dist/components/ui/section/section.js.map +1 -1
- package/dist/components/ui/stepper/stepper.js +24 -24
- package/dist/components/ui/stepper/stepper.js.map +1 -1
- package/dist/components/ui/stepper-item/stepper-item.js +43 -24
- package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
- package/dist/components/ui/table/table.js +27 -27
- package/dist/components/ui/table/table.js.map +1 -1
- package/dist/components/ui/treemap/treemap.js +133 -124
- package/dist/components/ui/treemap/treemap.js.map +1 -1
- package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
- package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
- package/dist/components/ui/wizard/wizard.js +59 -0
- package/dist/components/ui/wizard/wizard.js.map +1 -0
- package/dist/hooks/use-wizard.js +75 -0
- package/dist/hooks/use-wizard.js.map +1 -0
- package/dist/index.js +540 -525
- package/dist/index.js.map +1 -1
- package/dist/llms/accordion-container.md +181 -0
- package/dist/llms/accordion.md +124 -0
- package/dist/llms/alert.md +225 -0
- package/dist/llms/app-shell-chat.md +415 -0
- package/dist/llms/area-chart.md +355 -0
- package/dist/llms/avatar.md +208 -0
- package/dist/llms/bar-chart.md +406 -0
- package/dist/llms/breadcrumb.md +326 -0
- package/dist/llms/button-group.md +298 -0
- package/dist/llms/button-icon-input.md +142 -0
- package/dist/llms/button-icon-menu.md +209 -0
- package/dist/llms/button-icon.md +128 -0
- package/dist/llms/button-menu.md +172 -0
- package/dist/llms/button.md +185 -0
- package/dist/llms/calendar-panel.md +733 -0
- package/dist/llms/calendar.md +188 -0
- package/dist/llms/card-filter.md +214 -0
- package/dist/llms/card-section.md +293 -0
- package/dist/llms/card.md +447 -0
- package/dist/llms/carousel-dialog.md +156 -0
- package/dist/llms/category-bar.md +193 -0
- package/dist/llms/chart-state.md +190 -0
- package/dist/llms/chart-widget.md +209 -0
- package/dist/llms/chart.md +182 -0
- package/dist/llms/checkbox.md +257 -0
- package/dist/llms/chip.md +195 -0
- package/dist/llms/combobox.md +164 -0
- package/dist/llms/composed-chart.md +508 -0
- package/dist/llms/confidence-cone.md +277 -0
- package/dist/llms/data-table.md +474 -0
- package/dist/llms/date-range-picker.md +272 -0
- package/dist/llms/description-list.md +131 -0
- package/dist/llms/dialog-footer-carousel.md +147 -0
- package/dist/llms/dialog-footer-default.md +142 -0
- package/dist/llms/dialog-root.md +246 -0
- package/dist/llms/dialog-welcome.md +223 -0
- package/dist/llms/dialog.md +403 -0
- package/dist/llms/dropdown-menu.md +193 -0
- package/dist/llms/empty-overlay.md +146 -0
- package/dist/llms/empty.md +156 -0
- package/dist/llms/field.md +185 -0
- package/dist/llms/filter-cards.md +157 -0
- package/dist/llms/filter-chips.md +323 -0
- package/dist/llms/filter-search.md +512 -0
- package/dist/llms/form.md +154 -0
- package/dist/llms/funnel-chart.md +333 -0
- package/dist/llms/grid.md +80 -0
- package/dist/llms/histogram.md +190 -0
- package/dist/llms/input-date-picker.md +203 -0
- package/dist/llms/input-otp.md +173 -0
- package/dist/llms/input-password.md +197 -0
- package/dist/llms/input-search.md +170 -0
- package/dist/llms/input-select.md +278 -0
- package/dist/llms/input-text-area.md +271 -0
- package/dist/llms/input-text.md +192 -0
- package/dist/llms/line-chart.md +369 -0
- package/dist/llms/link.md +209 -0
- package/dist/llms/loading.md +130 -0
- package/dist/llms/meter.md +177 -0
- package/dist/llms/metric.md +204 -0
- package/dist/llms/number-field.md +122 -0
- package/dist/llms/page-content.md +69 -0
- package/dist/llms/page-header.md +182 -0
- package/dist/llms/pagination.md +133 -0
- package/dist/llms/pie-chart.md +307 -0
- package/dist/llms/popover.md +252 -0
- package/dist/llms/progress-circle.md +126 -0
- package/dist/llms/progress.md +111 -0
- package/dist/llms/radar-chart.md +316 -0
- package/dist/llms/radial-bar-chart.md +319 -0
- package/dist/llms/radio.md +255 -0
- package/dist/llms/resizable.md +195 -0
- package/dist/llms/sankey-chart.md +208 -0
- package/dist/llms/scatter-chart.md +239 -0
- package/dist/llms/scroll-area.md +183 -0
- package/dist/llms/section.md +401 -0
- package/dist/llms/select.md +210 -0
- package/dist/llms/separator.md +87 -0
- package/dist/llms/sheet.md +202 -0
- package/dist/llms/sidebar-primary.md +360 -0
- package/dist/llms/sidebar-secondary.md +417 -0
- package/dist/llms/skeleton.md +81 -0
- package/dist/llms/slider.md +97 -0
- package/dist/llms/spinner.md +100 -0
- package/dist/llms/stack.md +80 -0
- package/dist/llms/stepper-item.md +309 -0
- package/dist/llms/stepper.md +251 -0
- package/dist/llms/switch.md +140 -0
- package/dist/llms/table.md +436 -0
- package/dist/llms/tabs.md +197 -0
- package/dist/llms/tag.md +139 -0
- package/dist/llms/timeline.md +361 -0
- package/dist/llms/timer.md +259 -0
- package/dist/llms/toast.md +241 -0
- package/dist/llms/toggle-group.md +121 -0
- package/dist/llms/toolbar.md +453 -0
- package/dist/llms/tooltip.md +164 -0
- package/dist/llms/treemap.md +254 -0
- package/dist/llms/trend-indicator.md +132 -0
- package/dist/llms/widget-placeholder.md +169 -0
- package/dist/llms/wizard.md +412 -0
- package/dist/llms.txt +142 -0
- package/dist/react.js +540 -525
- package/dist/react.js.map +1 -1
- package/dist/src/components/ui/accordion-container/accordion-container.d.ts +44 -0
- package/dist/src/components/ui/accordion-container/index.d.ts +1 -0
- package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
- package/dist/src/components/ui/avatar/avatar.d.ts +27 -8
- package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
- package/dist/src/components/ui/button/button.d.ts +1 -1
- package/dist/src/components/ui/card/card.d.ts +69 -8
- package/dist/src/components/ui/card/index.d.ts +1 -1
- package/dist/src/components/ui/card-section/card-section.d.ts +50 -0
- package/dist/src/components/ui/card-section/index.d.ts +1 -0
- package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
- package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
- package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
- package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
- package/dist/src/components/ui/chart/chart.d.ts +66 -15
- package/dist/src/components/ui/chart/index.d.ts +4 -2
- package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
- package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
- package/dist/src/components/ui/chart-state/index.d.ts +1 -0
- package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
- package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
- package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
- package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
- package/dist/src/components/ui/dialog/dialog.d.ts +1 -1
- package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +20 -0
- package/dist/src/components/ui/empty-overlay/index.d.ts +2 -0
- package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
- package/dist/src/components/ui/grid/grid.d.ts +1 -1
- package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
- package/dist/src/components/ui/label/index.d.ts +1 -1
- package/dist/src/components/ui/label/label.d.ts +1 -5
- package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
- package/dist/src/components/ui/metric/metric.d.ts +13 -14
- package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
- package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
- package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
- package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
- package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
- package/dist/src/components/ui/section/index.d.ts +1 -1
- package/dist/src/components/ui/section/section.d.ts +75 -6
- package/dist/src/components/ui/sheet/sheet.d.ts +1 -1
- package/dist/src/components/ui/stack/stack.d.ts +1 -1
- package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
- package/dist/src/components/ui/tag/tag.d.ts +1 -1
- package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
- package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
- package/dist/src/components/ui/wizard/index.d.ts +1 -0
- package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
- package/dist/src/hooks/index.d.ts +1 -0
- package/dist/src/hooks/use-wizard.d.ts +80 -0
- package/dist/src/index.d.ts +5 -3
- package/dist/ui-react.css +1 -1
- package/package.json +12 -6
- package/dist/components/ui/app-shell/app-shell.js +0 -75
- package/dist/components/ui/app-shell/app-shell.js.map +0 -1
- package/dist/components/ui/auth-layout/auth-layout.js +0 -56
- package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
- package/dist/components/ui/collapsible/collapsible.js +0 -22
- package/dist/components/ui/collapsible/collapsible.js.map +0 -1
- package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
- package/dist/src/components/ui/app-shell/index.d.ts +0 -1
- package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
- package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
- package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
- package/dist/src/components/ui/collapsible/index.d.ts +0 -1
- package/dist/src/components/ui/label/label.docs.d.ts +0 -10
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# ButtonIconInput
|
|
2
|
+
|
|
3
|
+
> A smaller icon-only button (20×20, 16px glyph) meant to live inside an input's box (e.g. a clear or reveal affordance), as opposed to `ButtonIcon`'s standalone 32×32 sizing. `variant` (`normal` / `error`) mirrors the tone of the field it sits in.
|
|
4
|
+
|
|
5
|
+
**Status:** ready · **Category:** actions · **Since:** v0.58.0
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { ButtonIconInput } from '@acronis-platform/ui-react'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick example
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<ButtonIconInput aria-label="Show password">
|
|
17
|
+
<EyeIcon />
|
|
18
|
+
</ButtonIconInput>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
A smaller icon-only button (20×20, 16px glyph) meant to live inside an input's
|
|
22
|
+
box — e.g. `InputPassword`'s show/hide toggle. `variant` (`normal` / `error`)
|
|
23
|
+
mirrors the tone of the field it's embedded in.
|
|
24
|
+
|
|
25
|
+
## When to use
|
|
26
|
+
|
|
27
|
+
- An affordance embedded inside a text field's box (reveal/hide password,
|
|
28
|
+
clear, etc.) that needs to visually match the field's current tone.
|
|
29
|
+
|
|
30
|
+
## When not to use
|
|
31
|
+
|
|
32
|
+
- A standalone icon-only action outside an input — use **ButtonIcon** (32×32).
|
|
33
|
+
- An action that needs a text label — use **Button**.
|
|
34
|
+
|
|
35
|
+
## Example (React — implemented)
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { ButtonIconInput } from '@acronis-platform/ui-react';
|
|
39
|
+
import { EyeIcon } from '@acronis-platform/icons-react/stroke-mono';
|
|
40
|
+
|
|
41
|
+
<ButtonIconInput aria-label="Show password">
|
|
42
|
+
<EyeIcon />
|
|
43
|
+
</ButtonIconInput>;
|
|
44
|
+
|
|
45
|
+
// Error tone, matching a field in its error state
|
|
46
|
+
<ButtonIconInput variant="error" aria-label="Show password">
|
|
47
|
+
<EyeIcon />
|
|
48
|
+
</ButtonIconInput>;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Always provide an `aria-label` — the control has no text. Vue and Web Component
|
|
52
|
+
implementations are planned against the same contract.
|
|
53
|
+
|
|
54
|
+
## Parts
|
|
55
|
+
|
|
56
|
+
| Part | Element | Description |
|
|
57
|
+
| ------ | ---------- | ---------------------------------------------- |
|
|
58
|
+
| `root` | `<button>` | The 20×20 button surface (background, radius). |
|
|
59
|
+
| `icon` | `<svg>` | The single glyph, sized to 16px. |
|
|
60
|
+
|
|
61
|
+
## Props
|
|
62
|
+
|
|
63
|
+
| Prop | Type | Default | Required | Description |
|
|
64
|
+
|------|------|---------|----------|-------------|
|
|
65
|
+
| `variant` | `'normal' | 'error'` | `'normal'` | no | Visual tone — mirrors the field the button is embedded in. Each variant has its own idle/hover/active/disabled container + icon tokens and its own focus ring color (`--ui-focus-primary` for `normal`, `--ui-focus-error` for `error`). |
|
|
66
|
+
| `disabled` | `boolean` | `false` | no | Disables interaction and applies the disabled token set. |
|
|
67
|
+
| `type` | `'button' | 'submit' | 'reset'` | `'button'` | no | Native HTML button type. |
|
|
68
|
+
| `aria-label` | `string` | — | no | Accessible name. Required in practice — this control is icon-only and has no text to name it. |
|
|
69
|
+
|
|
70
|
+
## Events
|
|
71
|
+
|
|
72
|
+
| Event | Payload | Description |
|
|
73
|
+
|-------|---------|-------------|
|
|
74
|
+
| `click` | `MouseEvent` | Fired on activation. Not fired while disabled. |
|
|
75
|
+
|
|
76
|
+
## Content slots
|
|
77
|
+
|
|
78
|
+
| Slot | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| `default` | A single icon (SVG), sized to 16px and tinted via currentColor. |
|
|
81
|
+
|
|
82
|
+
## Behavior
|
|
83
|
+
|
|
84
|
+
### Rendering
|
|
85
|
+
|
|
86
|
+
#### Renders a compact icon-only button
|
|
87
|
+
|
|
88
|
+
**Given** a ButtonIconInput with a single icon child
|
|
89
|
+
**When** it renders
|
|
90
|
+
**Then** it is a 20×20 square with the icon centered at 16px
|
|
91
|
+
**And** background, glyph, and (for `error`) container/glyph tone resolve from
|
|
92
|
+
`--ui-button-icon-input-*` for the current variant and state.
|
|
93
|
+
|
|
94
|
+
### Interaction states
|
|
95
|
+
|
|
96
|
+
#### Tracks each state from its own token, per variant
|
|
97
|
+
|
|
98
|
+
**Given** the button is idle, hovered, or activated
|
|
99
|
+
**When** it renders
|
|
100
|
+
**Then** background and glyph each resolve from the matching `*-idle` /
|
|
101
|
+
`*-hover` / `*-active` token **for the current `variant`** (`normal` or
|
|
102
|
+
`error` — they don't share a token tier).
|
|
103
|
+
|
|
104
|
+
#### Disabled always uses the `normal` disabled tokens
|
|
105
|
+
|
|
106
|
+
**Given** a ButtonIconInput with `disabled`, regardless of `variant`
|
|
107
|
+
**When** it renders
|
|
108
|
+
**Then** background and glyph resolve from
|
|
109
|
+
`--ui-button-icon-input-normal-container-color-disabled` /
|
|
110
|
+
`-normal-icon-color-disabled` — the design defines no separate disabled
|
|
111
|
+
treatment for `error`.
|
|
112
|
+
|
|
113
|
+
#### Disabled suppresses click
|
|
114
|
+
|
|
115
|
+
**Given** a ButtonIconInput with `disabled`
|
|
116
|
+
**When** the user activates it
|
|
117
|
+
**Then** no `click` is emitted.
|
|
118
|
+
|
|
119
|
+
### Composition
|
|
120
|
+
|
|
121
|
+
#### Renders as another element
|
|
122
|
+
|
|
123
|
+
**Given** a `render` prop (React)
|
|
124
|
+
**When** it renders
|
|
125
|
+
**Then** the classes/props merge onto that element (e.g. an `<a>`).
|
|
126
|
+
|
|
127
|
+
## Accessibility
|
|
128
|
+
|
|
129
|
+
- **Role:** native `<button>`.
|
|
130
|
+
- **Accessible name (required):** the control is icon-only, so it MUST be given
|
|
131
|
+
an `aria-label` (or `aria-labelledby`). The icon itself should be
|
|
132
|
+
`aria-hidden`. Without a label the button is unusable to screen readers.
|
|
133
|
+
- **Keyboard:** Enter and Space activate (native). `disabled` removes it from
|
|
134
|
+
the tab order.
|
|
135
|
+
- **Focus visible:** 3px ring, flush to the edge — `--ui-focus-primary` for the
|
|
136
|
+
`normal` variant, `--ui-focus-error` for `error`.
|
|
137
|
+
- **Touch target:** 20×20 is well below the 44×44 guideline — this control is
|
|
138
|
+
meant to sit inside an input's box (e.g. a reveal/clear affordance), not to
|
|
139
|
+
stand alone as a primary touch target.
|
|
140
|
+
- **Contrast:** glyph/background pairs come from the design tokens (authored for
|
|
141
|
+
contrast).
|
|
142
|
+
- **WCAG:** 2.1.1, 2.4.7, 1.4.11, 4.1.2.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# ButtonIconMenu
|
|
2
|
+
|
|
3
|
+
> The kebab ("more options") trigger: a 32×32 bordered icon-only button holding a fixed 16px ellipsis glyph, across idle, hover, open, disabled, and focus states. Opens a menu of actions where there is no room for a label.
|
|
4
|
+
|
|
5
|
+
**Status:** ready · **Category:** actions · **Since:** v0.63.0
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { ButtonIconMenu } from '@acronis-platform/ui-react'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick example
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<ButtonIconMenu
|
|
17
|
+
ariaLabel="Row actions"
|
|
18
|
+
open={open}
|
|
19
|
+
onClick={toggle}
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
{/* Polymorphic: render as a menu trigger via the `render` prop */}
|
|
23
|
+
<ButtonIconMenu render={<Menu.Trigger />} ariaLabel="Row actions" />
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The kebab ("more options") trigger: a 32×32 bordered icon-only button holding a
|
|
27
|
+
fixed 16px ellipsis glyph, across idle, hover, open, disabled, and focus states.
|
|
28
|
+
|
|
29
|
+
It is the same surface as **ButtonIcon**'s `secondary` variant — the design draws
|
|
30
|
+
it from the same `--ui-button-icon-*` tokens — with the ellipsis glyph pinned and
|
|
31
|
+
menu-trigger semantics added.
|
|
32
|
+
|
|
33
|
+
## When to use
|
|
34
|
+
|
|
35
|
+
- A row, card, or toolbar needs a **menu of secondary actions** and there is no
|
|
36
|
+
room for a label.
|
|
37
|
+
|
|
38
|
+
## When not to use
|
|
39
|
+
|
|
40
|
+
- The trigger can carry a label — use **ButtonMenu**, which shows the label and a
|
|
41
|
+
chevron.
|
|
42
|
+
- The action is a single command, not a menu — use **ButtonIcon**.
|
|
43
|
+
- The glyph must be something other than the ellipsis — use **ButtonIcon** (this
|
|
44
|
+
component pins the glyph on purpose, so every kebab in the product looks the
|
|
45
|
+
same).
|
|
46
|
+
- Picking one option from a list, showing the chosen value — use **Select**.
|
|
47
|
+
|
|
48
|
+
## Example (React — implemented)
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { ButtonIconMenu } from '@acronis-platform/ui-react';
|
|
52
|
+
|
|
53
|
+
const [open, setOpen] = useState(false);
|
|
54
|
+
|
|
55
|
+
<ButtonIconMenu
|
|
56
|
+
ariaLabel="Row actions"
|
|
57
|
+
open={open}
|
|
58
|
+
onClick={() => setOpen((v) => !v)}
|
|
59
|
+
/>;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Composed as a real Base UI menu trigger:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { DropdownMenu, ButtonIconMenu } from '@acronis-platform/ui-react';
|
|
66
|
+
|
|
67
|
+
<DropdownMenu>
|
|
68
|
+
<DropdownMenuTrigger render={<ButtonIconMenu ariaLabel="Row actions" />} />
|
|
69
|
+
<DropdownMenuContent>{/* items */}</DropdownMenuContent>
|
|
70
|
+
</DropdownMenu>;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Keep `open` in sync with the menu the button controls so the active treatment and
|
|
74
|
+
`aria-expanded` reflect the real state. Vue and Web Component implementations are
|
|
75
|
+
planned against the same contract.
|
|
76
|
+
|
|
77
|
+
## Parts
|
|
78
|
+
|
|
79
|
+
| Part | Element | Notes |
|
|
80
|
+
| ------ | -------- | ----------------------------------------------------------------------- |
|
|
81
|
+
| `root` | `button` | The surface; `aria-haspopup="menu"`, reflects `aria-expanded` when open |
|
|
82
|
+
| `icon` | `svg` | Fixed 16px ellipsis glyph, centered — not swappable |
|
|
83
|
+
|
|
84
|
+
## Props
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Required | Description |
|
|
87
|
+
|------|------|---------|----------|-------------|
|
|
88
|
+
| `open` | `boolean` | `false` | no | Whether the associated menu is open. Applies the open (`*-active`) treatment to the container fill, glyph, and border, and reflects `aria-expanded`. Keep it in sync with the menu the button controls. |
|
|
89
|
+
| `disabled` | `boolean` | `false` | no | Disables interaction. Applies the explicit disabled tokens (not opacity) and suppresses click. |
|
|
90
|
+
| `ariaLabel` | `string` | `'More options'` | no | Accessible name. The control is icon-only and has no text to name it, so the default is only a fallback — pass a localized string. |
|
|
91
|
+
| `type` | `'button' | 'submit' | 'reset'` | `'button'` | no | Native HTML button type. |
|
|
92
|
+
|
|
93
|
+
## Events
|
|
94
|
+
|
|
95
|
+
| Event | Payload | Description |
|
|
96
|
+
|-------|---------|-------------|
|
|
97
|
+
| `click` | `MouseEvent` | Fired on activation (pointer or keyboard). Typically toggles the associated menu. Not fired while disabled. |
|
|
98
|
+
|
|
99
|
+
## Content slots
|
|
100
|
+
|
|
101
|
+
| Slot | Description |
|
|
102
|
+
|------|-------------|
|
|
103
|
+
| `none` | Takes no content — the ellipsis glyph is fixed by the design. Use ButtonIcon when the glyph has to change. |
|
|
104
|
+
|
|
105
|
+
## Behavior
|
|
106
|
+
|
|
107
|
+
### Rendering
|
|
108
|
+
|
|
109
|
+
#### Renders a bordered square carrying the ellipsis glyph
|
|
110
|
+
|
|
111
|
+
**Given** a ButtonIconMenu
|
|
112
|
+
**When** it renders
|
|
113
|
+
**Then** it shows a 32×32 button with a 1px border and a centered 16px ellipsis
|
|
114
|
+
glyph
|
|
115
|
+
**And** background, glyph, and border resolve from the `--ui-button-icon-*`
|
|
116
|
+
tokens for the current state.
|
|
117
|
+
|
|
118
|
+
#### The glyph is fixed
|
|
119
|
+
|
|
120
|
+
**Given** a consumer that needs a different icon
|
|
121
|
+
**When** they reach for this component
|
|
122
|
+
**Then** it offers no content slot — the design pins the ellipsis. Use
|
|
123
|
+
**ButtonIcon** instead.
|
|
124
|
+
|
|
125
|
+
### Open / closed
|
|
126
|
+
|
|
127
|
+
#### Open applies the active treatment
|
|
128
|
+
|
|
129
|
+
**Given** `open` is `false` (or unset)
|
|
130
|
+
**When** it renders
|
|
131
|
+
**Then** the idle tokens apply and `aria-expanded` is absent.
|
|
132
|
+
|
|
133
|
+
**Given** `open` is `true`
|
|
134
|
+
**When** it renders
|
|
135
|
+
**Then** the container fill, glyph, and border take their `*-active` tokens and
|
|
136
|
+
`aria-expanded="true"`.
|
|
137
|
+
|
|
138
|
+
### Interaction states
|
|
139
|
+
|
|
140
|
+
#### Tracks each state from its own token
|
|
141
|
+
|
|
142
|
+
**Given** the button is idle, hovered, pressed, open, or disabled
|
|
143
|
+
**When** it renders
|
|
144
|
+
**Then** the container fill, glyph color, and border color resolve from the
|
|
145
|
+
matching `*-idle` / `*-hover` / `*-active` / `*-disabled` token, so brand and
|
|
146
|
+
theme overrides are honored per state. Pressed and open share the `*-active`
|
|
147
|
+
tokens, as the design does.
|
|
148
|
+
|
|
149
|
+
#### Disabled suppresses click
|
|
150
|
+
|
|
151
|
+
**Given** a ButtonIconMenu with `disabled`
|
|
152
|
+
**When** the user activates it
|
|
153
|
+
**Then** no `click` is emitted and the disabled tokens apply (not opacity).
|
|
154
|
+
|
|
155
|
+
### Composition
|
|
156
|
+
|
|
157
|
+
#### Renders as another element
|
|
158
|
+
|
|
159
|
+
**Given** a `render` prop (React)
|
|
160
|
+
**When** it renders
|
|
161
|
+
**Then** the classes and props merge onto that element (e.g. a Base UI menu
|
|
162
|
+
trigger), so the button can drive a real menu while keeping its visual contract.
|
|
163
|
+
|
|
164
|
+
## Accessibility
|
|
165
|
+
|
|
166
|
+
## Role & name
|
|
167
|
+
|
|
168
|
+
- Renders a native `<button>` (role `button`).
|
|
169
|
+
- The control is **icon-only**, so it has no text to name it. The accessible name
|
|
170
|
+
comes from `ariaLabel` (or a native `aria-label` / `aria-labelledby`). The
|
|
171
|
+
built-in `'More options'` default is a fallback so the button is never
|
|
172
|
+
unnamed — pass a localized, context-specific name ("Row actions", "Backup plan
|
|
173
|
+
actions") whenever more than one of these sits on a screen.
|
|
174
|
+
- The ellipsis glyph is decorative and carries no separate accessible name.
|
|
175
|
+
|
|
176
|
+
## Expanded state
|
|
177
|
+
|
|
178
|
+
- The button sets `aria-haspopup="menu"` so assistive technology announces it as
|
|
179
|
+
a menu trigger before activation — unlike a labelled trigger, there is no text
|
|
180
|
+
to imply it.
|
|
181
|
+
- While `open`, it sets `aria-expanded="true"`; when closed the attribute is
|
|
182
|
+
absent (treated as not expanded). Keep `open` in sync with the menu it
|
|
183
|
+
controls.
|
|
184
|
+
- When wired to a real menu, the trigger should also reference the popup it
|
|
185
|
+
controls (`aria-controls`). The menu component owns that; ButtonIconMenu owns
|
|
186
|
+
only the trigger. Composing via `render={<Menu.Trigger />}` lets Base UI
|
|
187
|
+
manage those attributes.
|
|
188
|
+
|
|
189
|
+
## Keyboard
|
|
190
|
+
|
|
191
|
+
- `Tab` / `Shift+Tab` — move focus to / from the button.
|
|
192
|
+
- `Enter` / `Space` — activate the button (opens the associated menu).
|
|
193
|
+
- Disabled buttons are skipped in the tab order and ignore activation.
|
|
194
|
+
|
|
195
|
+
## Focus
|
|
196
|
+
|
|
197
|
+
- `:focus-visible` paints a 3px ring in `--ui-focus-primary` flush to the button
|
|
198
|
+
edge (no offset); the ring is suppressed for pointer focus.
|
|
199
|
+
|
|
200
|
+
## Contrast
|
|
201
|
+
|
|
202
|
+
- Color pairs come from `@acronis-platform/tokens-pd` and are maintained against
|
|
203
|
+
WCAG AA at the design-token level. The disabled treatment uses dedicated
|
|
204
|
+
disabled tokens rather than an opacity dim, so contrast stays predictable.
|
|
205
|
+
|
|
206
|
+
## Target size
|
|
207
|
+
|
|
208
|
+
- The 32×32 box meets the 24×24 minimum of WCAG 2.2 **Target Size (Minimum)**.
|
|
209
|
+
In dense rows keep adjacent triggers spaced so their targets do not overlap.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# ButtonIcon
|
|
2
|
+
|
|
3
|
+
> Icon-only button (32×32, 24px glyph) with idle, hover, active, and disabled states. Two variants share the same fill and icon colors: `ghost` (borderless) and `secondary` (a 1px container border). Use when an action is represented by an icon alone.
|
|
4
|
+
|
|
5
|
+
**Status:** ready · **Category:** actions · **Since:** v0.4.0
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { ButtonIcon } from '@acronis-platform/ui-react'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick example
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<ButtonIcon aria-label="Add">
|
|
17
|
+
<PlusIcon />
|
|
18
|
+
</ButtonIcon>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
An icon-only button: 32×32 with a single 24px glyph and
|
|
22
|
+
idle/hover/active/disabled states. Two variants share the same fill and icon
|
|
23
|
+
colors — `ghost` (borderless, the default) and `secondary` (a 1px container
|
|
24
|
+
border).
|
|
25
|
+
|
|
26
|
+
## When to use
|
|
27
|
+
|
|
28
|
+
- A compact action represented by an icon alone (e.g. a toolbar action) where a
|
|
29
|
+
text label would be redundant or there's no room for one.
|
|
30
|
+
|
|
31
|
+
## When not to use
|
|
32
|
+
|
|
33
|
+
- An action that needs a text label — use **Button** (it also sizes a leading
|
|
34
|
+
icon).
|
|
35
|
+
- A toggle — use a toggle/switch control.
|
|
36
|
+
|
|
37
|
+
## Example (React — implemented)
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { ButtonIcon } from '@acronis-platform/ui-react';
|
|
41
|
+
import { PlusIcon } from '@acronis-platform/icons-react/stroke-mono';
|
|
42
|
+
|
|
43
|
+
<ButtonIcon aria-label="Add">
|
|
44
|
+
<PlusIcon />
|
|
45
|
+
</ButtonIcon>;
|
|
46
|
+
|
|
47
|
+
// Bordered treatment
|
|
48
|
+
<ButtonIcon variant="secondary" aria-label="Add">
|
|
49
|
+
<PlusIcon />
|
|
50
|
+
</ButtonIcon>;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Always provide an `aria-label` — the control has no text. Vue and Web Component
|
|
54
|
+
implementations are planned against the same contract.
|
|
55
|
+
|
|
56
|
+
## Props
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Required | Description |
|
|
59
|
+
|------|------|---------|----------|-------------|
|
|
60
|
+
| `variant` | `'ghost' | 'secondary'` | `'ghost'` | no | Visual style. Both share the `--ui-button-icon-global-*` fill and icon colors; `secondary` additionally paints a 1px container border from the `--ui-button-icon-secondary-container-border-color-*` tokens, `ghost` is borderless. |
|
|
61
|
+
| `disabled` | `boolean` | `false` | no | Disables interaction. Applies the explicit disabled tokens (not opacity) and suppresses click. |
|
|
62
|
+
| `type` | `'button' | 'submit' | 'reset'` | `'button'` | no | Native HTML button type. |
|
|
63
|
+
| `aria-label` | `string` | — | no | Accessible name. Required in practice — this control is icon-only and has no text to name it. |
|
|
64
|
+
|
|
65
|
+
## Events
|
|
66
|
+
|
|
67
|
+
| Event | Payload | Description |
|
|
68
|
+
|-------|---------|-------------|
|
|
69
|
+
| `click` | `MouseEvent` | Fired on activation. Not fired while disabled. |
|
|
70
|
+
|
|
71
|
+
## Content slots
|
|
72
|
+
|
|
73
|
+
| Slot | Description |
|
|
74
|
+
|------|-------------|
|
|
75
|
+
| `default` | A single icon (SVG), sized to 24px and tinted via currentColor. |
|
|
76
|
+
|
|
77
|
+
## Behavior
|
|
78
|
+
|
|
79
|
+
### Rendering
|
|
80
|
+
|
|
81
|
+
#### Renders a square icon-only button
|
|
82
|
+
|
|
83
|
+
**Given** a ButtonIcon with a single icon child
|
|
84
|
+
**When** it renders
|
|
85
|
+
**Then** it is a 32×32 square with the icon centered at 24px
|
|
86
|
+
**And** background, glyph, and border resolve from `--ui-button-icon-*` for the
|
|
87
|
+
current state.
|
|
88
|
+
|
|
89
|
+
### Interaction states
|
|
90
|
+
|
|
91
|
+
#### Tracks each state from its own token
|
|
92
|
+
|
|
93
|
+
**Given** the button is idle, hovered, activated, or disabled
|
|
94
|
+
**When** it renders
|
|
95
|
+
**Then** background, glyph, and border each resolve from the matching
|
|
96
|
+
`*-idle` / `*-hover` / `*-active` / `*-disabled` token (brand/theme overrides
|
|
97
|
+
honored per state).
|
|
98
|
+
|
|
99
|
+
#### Disabled suppresses click
|
|
100
|
+
|
|
101
|
+
**Given** a ButtonIcon with `disabled`
|
|
102
|
+
**When** the user activates it
|
|
103
|
+
**Then** no `click` is emitted and the disabled tokens apply (not opacity).
|
|
104
|
+
|
|
105
|
+
### Composition
|
|
106
|
+
|
|
107
|
+
#### Renders as another element
|
|
108
|
+
|
|
109
|
+
**Given** a `render` prop (React)
|
|
110
|
+
**When** it renders
|
|
111
|
+
**Then** the classes/props merge onto that element (e.g. an `<a>`).
|
|
112
|
+
|
|
113
|
+
## Accessibility
|
|
114
|
+
|
|
115
|
+
- **Role:** native `<button>`.
|
|
116
|
+
- **Accessible name (required):** the control is icon-only, so it MUST be given
|
|
117
|
+
an `aria-label` (or `aria-labelledby`). The icon itself should be
|
|
118
|
+
`aria-hidden`. Without a label the button is unusable to screen readers.
|
|
119
|
+
- **Keyboard:** Enter and Space activate (native). `disabled` removes it from
|
|
120
|
+
the tab order.
|
|
121
|
+
- **Focus visible:** 3px `--ui-focus-primary` ring flush to the edge (no offset)
|
|
122
|
+
via `:focus-visible`.
|
|
123
|
+
- **Touch target:** 32×32 is below the 44×44 guideline; place with adequate
|
|
124
|
+
spacing, or extend the hit area with transparent padding where touch is a
|
|
125
|
+
primary input.
|
|
126
|
+
- **Contrast:** glyph/background pairs come from the design tokens (authored for
|
|
127
|
+
contrast).
|
|
128
|
+
- **WCAG:** 2.1.1, 2.4.7, 1.4.11, 4.1.2.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# ButtonMenu
|
|
2
|
+
|
|
3
|
+
> A button that opens a dropdown menu: a label followed by a chevron that points up while the menu is open. Two visual styles (primary, secondary) across idle, hover, open, and disabled states.
|
|
4
|
+
|
|
5
|
+
**Status:** ready · **Category:** actions · **Since:** v0.17.0
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { ButtonMenu } from '@acronis-platform/ui-react'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick example
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<ButtonMenu variant="primary" open={open} onClick={toggle}>
|
|
17
|
+
Actions
|
|
18
|
+
</ButtonMenu>
|
|
19
|
+
|
|
20
|
+
{/* Polymorphic: render as a menu trigger via the `render` prop */}
|
|
21
|
+
<ButtonMenu render={<Menu.Trigger />}>Actions</ButtonMenu>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A button that opens a dropdown menu: a label followed by a chevron that points up
|
|
25
|
+
while the menu is open. Two visual styles — `primary` (solid) and `secondary`
|
|
26
|
+
(bordered) — across idle, hover, open, and disabled states.
|
|
27
|
+
|
|
28
|
+
## When to use
|
|
29
|
+
|
|
30
|
+
- A control whose primary job is to **open a menu** of actions or options, where
|
|
31
|
+
the current selection isn't shown on the button itself.
|
|
32
|
+
|
|
33
|
+
## When not to use
|
|
34
|
+
|
|
35
|
+
- A plain action with no menu — use **Button**.
|
|
36
|
+
- A form control for picking one option from a list (showing the chosen value) —
|
|
37
|
+
use **Select**.
|
|
38
|
+
- An icon-only trigger with no label — use **ButtonIcon**.
|
|
39
|
+
|
|
40
|
+
## Example (React — implemented)
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { ButtonMenu } from '@acronis-platform/ui-react';
|
|
44
|
+
|
|
45
|
+
const [open, setOpen] = useState(false);
|
|
46
|
+
|
|
47
|
+
<ButtonMenu open={open} onClick={() => setOpen((v) => !v)}>
|
|
48
|
+
Actions
|
|
49
|
+
</ButtonMenu>;
|
|
50
|
+
|
|
51
|
+
// Bordered treatment
|
|
52
|
+
<ButtonMenu variant="secondary">Actions</ButtonMenu>;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Keep `open` in sync with the menu the button controls so the chevron and
|
|
56
|
+
`aria-expanded` reflect the real state. Use the `render` prop to compose it as a
|
|
57
|
+
Base UI menu trigger. Vue and Web Component implementations are planned against
|
|
58
|
+
the same contract.
|
|
59
|
+
|
|
60
|
+
## Parts
|
|
61
|
+
|
|
62
|
+
| Part | Element | Notes |
|
|
63
|
+
| ------- | -------- | ------------------------------------------------------ |
|
|
64
|
+
| `root` | `button` | The button surface; reflects `aria-expanded` when open |
|
|
65
|
+
| `label` | `span` | Text content, rendered before the chevron |
|
|
66
|
+
| `icon` | `svg` | Trailing chevron — down when closed, up when open |
|
|
67
|
+
|
|
68
|
+
## Props
|
|
69
|
+
|
|
70
|
+
| Prop | Type | Default | Required | Description |
|
|
71
|
+
|------|------|---------|----------|-------------|
|
|
72
|
+
| `variant` | `'primary' | 'secondary'` | `'primary'` | no | Visual style. `primary` is a solid filled button; `secondary` is bordered with a transparent fill. Each maps to its dedicated `--ui-button-menu-<variant>-*` tokens. |
|
|
73
|
+
| `open` | `boolean` | `false` | no | Whether the associated menu is open. Flips the trailing chevron (down → up), applies the open (`*-active`) treatment, and reflects `aria-expanded`. Keep it in sync with the menu the button controls. |
|
|
74
|
+
| `disabled` | `boolean` | `false` | no | Disables interaction. Applies the explicit disabled tokens (not opacity) and suppresses click. |
|
|
75
|
+
| `type` | `'button' | 'submit' | 'reset'` | `'button'` | no | Native HTML button type. |
|
|
76
|
+
|
|
77
|
+
## Events
|
|
78
|
+
|
|
79
|
+
| Event | Payload | Description |
|
|
80
|
+
|-------|---------|-------------|
|
|
81
|
+
| `click` | `MouseEvent` | Fired on activation (pointer or keyboard). Typically toggles the associated menu. Not fired while disabled. |
|
|
82
|
+
|
|
83
|
+
## Content slots
|
|
84
|
+
|
|
85
|
+
| Slot | Description |
|
|
86
|
+
|------|-------------|
|
|
87
|
+
| `default` | The label content, rendered before the chevron. Plain text or inline nodes. |
|
|
88
|
+
|
|
89
|
+
## Behavior
|
|
90
|
+
|
|
91
|
+
### Rendering
|
|
92
|
+
|
|
93
|
+
#### Renders a label and a trailing chevron
|
|
94
|
+
|
|
95
|
+
**Given** a ButtonMenu with label content
|
|
96
|
+
**When** it renders
|
|
97
|
+
**Then** it shows the label followed by a chevron icon (16px)
|
|
98
|
+
**And** background, label, icon, and — for `secondary` — border resolve from
|
|
99
|
+
`--ui-button-menu-*` for the current variant and state.
|
|
100
|
+
|
|
101
|
+
### Open / closed
|
|
102
|
+
|
|
103
|
+
#### Chevron reflects the open state
|
|
104
|
+
|
|
105
|
+
**Given** `open` is `false` (or unset)
|
|
106
|
+
**When** it renders
|
|
107
|
+
**Then** the chevron points **down** and `aria-expanded` is absent.
|
|
108
|
+
|
|
109
|
+
**Given** `open` is `true`
|
|
110
|
+
**When** it renders
|
|
111
|
+
**Then** the chevron points **up**, the container takes its `*-active` treatment,
|
|
112
|
+
and `aria-expanded="true"`.
|
|
113
|
+
|
|
114
|
+
### Interaction states
|
|
115
|
+
|
|
116
|
+
#### Tracks each state from its own token
|
|
117
|
+
|
|
118
|
+
**Given** the button is idle, hovered, pressed, open, or disabled
|
|
119
|
+
**When** it renders
|
|
120
|
+
**Then** the container fill (and `secondary`'s label/icon/border) resolve from
|
|
121
|
+
the matching `*-idle` / `*-hover` / `*-active` / `*-disabled` token (brand/theme
|
|
122
|
+
overrides honored per state). `primary` keeps a single label/icon color.
|
|
123
|
+
|
|
124
|
+
#### Disabled suppresses click
|
|
125
|
+
|
|
126
|
+
**Given** a ButtonMenu with `disabled`
|
|
127
|
+
**When** the user activates it
|
|
128
|
+
**Then** no `click` is emitted and the disabled tokens apply (not opacity).
|
|
129
|
+
|
|
130
|
+
### Composition
|
|
131
|
+
|
|
132
|
+
#### Renders as another element
|
|
133
|
+
|
|
134
|
+
**Given** a `render` prop (React)
|
|
135
|
+
**When** it renders
|
|
136
|
+
**Then** the classes/props merge onto that element (e.g. a menu trigger), so the
|
|
137
|
+
button can drive a Base UI menu while keeping its visual contract.
|
|
138
|
+
|
|
139
|
+
## Accessibility
|
|
140
|
+
|
|
141
|
+
## Role & name
|
|
142
|
+
|
|
143
|
+
- Renders a native `<button>` (role `button`). Its accessible name comes from the
|
|
144
|
+
label text content — always provide a meaningful label.
|
|
145
|
+
- The trailing chevron is decorative; it must not be the only thing conveying the
|
|
146
|
+
action and needs no separate accessible name.
|
|
147
|
+
|
|
148
|
+
## Expanded state
|
|
149
|
+
|
|
150
|
+
- While `open`, the button sets `aria-expanded="true"`; when closed the attribute
|
|
151
|
+
is absent (treated as not expanded). Keep `open` in sync with the menu the
|
|
152
|
+
button controls.
|
|
153
|
+
- When wired to a real menu, the trigger should also reference the menu it
|
|
154
|
+
controls (e.g. `aria-haspopup="menu"` and `aria-controls` pointing at the
|
|
155
|
+
popup). The menu component owns those; ButtonMenu only owns the trigger.
|
|
156
|
+
|
|
157
|
+
## Keyboard
|
|
158
|
+
|
|
159
|
+
- `Tab` / `Shift+Tab` — move focus to / from the button.
|
|
160
|
+
- `Enter` / `Space` — activate the button (toggles the associated menu).
|
|
161
|
+
- Disabled buttons are skipped in the tab order and ignore activation.
|
|
162
|
+
|
|
163
|
+
## Focus
|
|
164
|
+
|
|
165
|
+
- `:focus-visible` paints a 3px ring in `--ui-focus-primary` flush to the button
|
|
166
|
+
edge (no offset); the ring is suppressed for pointer focus.
|
|
167
|
+
|
|
168
|
+
## Contrast
|
|
169
|
+
|
|
170
|
+
- Color pairs come from `@acronis-platform/tokens-pd` and are maintained against
|
|
171
|
+
WCAG AA at the design-token level. The disabled treatment uses dedicated
|
|
172
|
+
disabled tokens rather than an opacity dim, so contrast stays predictable.
|