@workday/canvas-kit-docs 17.0.0-alpha.0623-next.0 → 17.0.0-alpha.0631-next.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/es6/lib/stackblitzFiles/packageJSONFile.js +5 -5
- package/dist/es6/lib/stackblitzFiles/packageJSONFile.ts +5 -5
- package/dist/mdx/API_PATTERN_GUIDELINES.mdx +10 -14
- package/dist/mdx/react/action-bar/ActionBar.mdx +139 -7
- package/dist/mdx/react/button/button/Button.mdx +138 -40
- package/package.json +6 -6
|
@@ -18,11 +18,11 @@ export const packageJSONFile = `{
|
|
|
18
18
|
"@emotion/react": "11.11.4",
|
|
19
19
|
"@types/react": "18.2.60",
|
|
20
20
|
"@types/react-dom": "18.2.19",
|
|
21
|
-
"@workday/canvas-kit-labs-react": "16.1.
|
|
22
|
-
"@workday/canvas-kit-preview-react": "16.1.
|
|
23
|
-
"@workday/canvas-kit-react": "16.1.
|
|
24
|
-
"@workday/canvas-kit-react-fonts": "^16.1.
|
|
25
|
-
"@workday/canvas-kit-styling": "16.1.
|
|
21
|
+
"@workday/canvas-kit-labs-react": "16.1.7",
|
|
22
|
+
"@workday/canvas-kit-preview-react": "16.1.7",
|
|
23
|
+
"@workday/canvas-kit-react": "16.1.7",
|
|
24
|
+
"@workday/canvas-kit-react-fonts": "^16.1.7",
|
|
25
|
+
"@workday/canvas-kit-styling": "16.1.7",
|
|
26
26
|
"@workday/canvas-system-icons-web": "^5.0.3",
|
|
27
27
|
"@workday/canvas-expressive-icons-web": "1.0.1",
|
|
28
28
|
"@workday/canvas-tokens-web": "4.4.0-beta.11"
|
|
@@ -19,11 +19,11 @@ export const packageJSONFile = `{
|
|
|
19
19
|
"@emotion/react": "11.11.4",
|
|
20
20
|
"@types/react": "18.2.60",
|
|
21
21
|
"@types/react-dom": "18.2.19",
|
|
22
|
-
"@workday/canvas-kit-labs-react": "16.1.
|
|
23
|
-
"@workday/canvas-kit-preview-react": "16.1.
|
|
24
|
-
"@workday/canvas-kit-react": "16.1.
|
|
25
|
-
"@workday/canvas-kit-react-fonts": "^16.1.
|
|
26
|
-
"@workday/canvas-kit-styling": "16.1.
|
|
22
|
+
"@workday/canvas-kit-labs-react": "16.1.7",
|
|
23
|
+
"@workday/canvas-kit-preview-react": "16.1.7",
|
|
24
|
+
"@workday/canvas-kit-react": "16.1.7",
|
|
25
|
+
"@workday/canvas-kit-react-fonts": "^16.1.7",
|
|
26
|
+
"@workday/canvas-kit-styling": "16.1.7",
|
|
27
27
|
"@workday/canvas-system-icons-web": "^5.0.3",
|
|
28
28
|
"@workday/canvas-expressive-icons-web": "1.0.1",
|
|
29
29
|
"@workday/canvas-tokens-web": "4.4.0-beta.11"
|
|
@@ -13,7 +13,7 @@ Some of the below rules are inspired by painpoints we've encountered in this pro
|
|
|
13
13
|
- [Patterns](#patterns)
|
|
14
14
|
- [Event Handlers](#event-handlers-1)
|
|
15
15
|
- [Grow Interface](#grow-interface)
|
|
16
|
-
- [
|
|
16
|
+
- [Focus indicators](#focus-indicators)
|
|
17
17
|
- [Prop Spread Behavior](#prop-spread-behavior)
|
|
18
18
|
- [Controlled Components](#controlled-components)
|
|
19
19
|
- [Accessibility](#accessibility)
|
|
@@ -135,22 +135,18 @@ If objects are desired, the keys follow these rules:
|
|
|
135
135
|
- Then use the `grow` boolean prop in your styles to achieve the desired effect (e.g.
|
|
136
136
|
`width: grow ? '100%' : undefined`)
|
|
137
137
|
|
|
138
|
-
####
|
|
138
|
+
#### Focus indicators
|
|
139
139
|
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- Do not use `
|
|
144
|
-
|
|
145
|
-
- Make sure you provide fully accessible styling by default, and only override for mouse usage.
|
|
146
|
-
-
|
|
140
|
+
- Visible focus indicators are required by default. Use **`:focus-visible`** so browser heuristics
|
|
141
|
+
show the ring for keyboard (and other non-pointer) focus. Pair it with a `&.focus` class twin for
|
|
142
|
+
Chromatic / `StaticStates` visual testing.
|
|
143
|
+
- Do **not** use `data-whatinput` or `InputProvider` — those were removed in v14. Never remove
|
|
144
|
+
`outline` on `:focus` without a `:focus-visible` replacement.
|
|
147
145
|
|
|
148
146
|
```tsx
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
outline: 'none',
|
|
153
|
-
border: 'none',
|
|
147
|
+
'&:is(.focus, :focus-visible)': {
|
|
148
|
+
outline: `2px solid ${system.legacy.color.brand.border.primary}`,
|
|
149
|
+
outlineOffset: '-2px',
|
|
154
150
|
},
|
|
155
151
|
```
|
|
156
152
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {ExampleCodeBlock, SymbolDoc} from '@workday/canvas-kit-docs';
|
|
2
2
|
import Basic from './examples/Basic';
|
|
3
|
-
import Icons from './examples/Icons';
|
|
4
3
|
import DeleteAction from './examples/DeleteAction';
|
|
4
|
+
import Icons from './examples/Icons';
|
|
5
5
|
import OverflowActionBar from './examples/OverflowActionBar';
|
|
6
6
|
import OverflowActionBarCustomButtonCount from './examples/OverflowActionBarCustomButtonCount';
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
# Canvas Kit Action Bar
|
|
9
10
|
|
|
10
11
|
Action Bar is a [compound component](/get-started/for-developers/documentation/compound-components/)
|
|
@@ -71,13 +72,144 @@ You can change it from the default of 3 to any number greater than 1 and less th
|
|
|
71
72
|
|
|
72
73
|
## Accessibility
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
a
|
|
75
|
+
The primary accessibility goal is a clearly named group of page-level actions where every action is
|
|
76
|
+
a native, keyboard-operable button. Use Action Bar for the primary and secondary actions of a page
|
|
77
|
+
or task. For a single action, use a [Button](/components/buttons/button/#accessibility) directly.
|
|
78
|
+
For a dense set of icon or dropdown controls that behaves as one tab stop, use
|
|
79
|
+
[Toolbar](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-toolbar--docs). For
|
|
80
|
+
actions that open a task flow, compose [Modal](/components/popups/modal/#accessibility) or
|
|
81
|
+
[Dialog](/components/popups/dialog/#accessibility) from an **`ActionBar.Item`**.
|
|
82
|
+
|
|
83
|
+
See the [Menu Button pattern (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/), the
|
|
84
|
+
[Button pattern (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/button/), and the Canvas Kit
|
|
85
|
+
[Accessibility overview](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-overview--docs).
|
|
86
|
+
|
|
87
|
+
### Minimum Accessible Structure
|
|
88
|
+
|
|
89
|
+
The following matches the [Basic Example](#basic-example): an **`ActionBar.List`** rendered as a
|
|
90
|
+
labelled `section`, with a primary action first and secondary actions after it. **`ActionBar.List`**
|
|
91
|
+
and **`ActionBar.Item`** should always be inside **`ActionBar`**.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import {ActionBar} from '@workday/canvas-kit-react/action-bar';
|
|
95
|
+
import {PrimaryButton} from '@workday/canvas-kit-react/button';
|
|
96
|
+
|
|
97
|
+
<ActionBar>
|
|
98
|
+
<ActionBar.List as="section" aria-label="Page actions">
|
|
99
|
+
<ActionBar.Item as={PrimaryButton} onClick={() => console.log('first action')}>
|
|
100
|
+
First Action
|
|
101
|
+
</ActionBar.Item>
|
|
102
|
+
<ActionBar.Item>Second Action</ActionBar.Item>
|
|
103
|
+
</ActionBar.List>
|
|
104
|
+
</ActionBar>;
|
|
105
|
+
```
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
107
|
+
Provide a translated, descriptive **`aria-label`** on **`ActionBar.List`**. Every
|
|
108
|
+
**`ActionBar.Item`** needs non-empty visible text, which becomes its accessible name.
|
|
109
|
+
|
|
110
|
+
### Built-in Behaviors
|
|
111
|
+
|
|
112
|
+
Canvas Kit applies these automatically. **Do not duplicate them** in consuming code.
|
|
113
|
+
|
|
114
|
+
**ARIA and DOM** (_applied by hooks/subcomponents_):
|
|
115
|
+
|
|
116
|
+
- **`ActionBar`**: Does not render an element. It creates the model and wraps its children in
|
|
117
|
+
**`Menu`** so the overflow menu shares state.
|
|
118
|
+
- **`ActionBar.List`**: Renders a `div` by default. It has no role of its own—use `as="section"`
|
|
119
|
+
with **`aria-label`** to expose a landmark. It is positioned fixed to the bottom of the viewport
|
|
120
|
+
unless you override `position`.
|
|
121
|
+
- **`ActionBar.Item`**: Renders a native `<button>` through **`SecondaryButton`** (or the component
|
|
122
|
+
passed to `as`). It inherits the [Button accessibility](/components/buttons/button/#accessibility)
|
|
123
|
+
behavior, including visible label wiring and decorative `icon` handling.
|
|
124
|
+
- **Overflow**: Items that do not fit, or that exceed `maximumVisible`, receive `aria-hidden`,
|
|
125
|
+
`inert`, and `disabled`, so they are removed from the tab order and the accessibility tree and
|
|
126
|
+
appear in the overflow menu instead.
|
|
127
|
+
- **`ActionBar.OverflowButton`**: Renders a **`SecondaryButton`** with the related-actions icon,
|
|
128
|
+
`aria-haspopup`, and `aria-expanded` through the **`Menu.Target`**. It is `aria-hidden` with
|
|
129
|
+
`tabIndex={-1}` while no items overflow, and gains `tabIndex={0}` once items overflow.
|
|
130
|
+
- **`ActionBar.Menu`**: Is the standard [Menu](/components/popups/menu/#accessibility).
|
|
131
|
+
**`ActionBar.Menu.List`** has `role="menu"` labelled by the overflow button, and
|
|
132
|
+
**`ActionBar.Menu.Item`** has `role="menuitem"` with roving `tabIndex`.
|
|
133
|
+
|
|
134
|
+
**Focus** (_applied by the model_):
|
|
135
|
+
|
|
136
|
+
- Opening the overflow menu moves focus to its first item.
|
|
137
|
+
- Selecting an item closes the menu.
|
|
138
|
+
- Closing the menu (Escape, outside click, or selection) returns focus to **`ActionBar.OverflowButton`**.
|
|
139
|
+
|
|
140
|
+
**Keyboard**:
|
|
141
|
+
|
|
142
|
+
| Key | Behavior |
|
|
143
|
+
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
144
|
+
| <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> | Moves between each visible **`ActionBar.Item`** and the overflow button. Every visible item is its own tab stop; Action Bar does not use roving tabindex |
|
|
145
|
+
| <kbd>Enter</kbd> / <kbd>Space</kbd> | Activates the focused item, or opens the overflow menu |
|
|
146
|
+
| <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> | Opens the overflow menu from the overflow button |
|
|
147
|
+
| <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> inside menu | Moves between overflow menu items |
|
|
148
|
+
| <kbd>Escape</kbd> | Closes the overflow menu and returns focus to the overflow button |
|
|
149
|
+
| <kbd>Tab</kbd> inside menu | Closes the menu and moves focus to the next focusable element on the page |
|
|
150
|
+
|
|
151
|
+
**Screen reader expectations** (_when built-in behaviors are used as intended_):
|
|
152
|
+
|
|
153
|
+
- On entering the group, the landmark is announced with the **`aria-label`** (for example, "Page
|
|
154
|
+
actions, region").
|
|
155
|
+
- Each visible item is announced by its text and role (for example, "First Action, button").
|
|
156
|
+
- The overflow button is announced with its **`aria-label`** and as a menu button with expanded or
|
|
157
|
+
collapsed state (for example, "More actions, menu button, collapsed").
|
|
158
|
+
- Items moved into the overflow menu are no longer announced as buttons in the bar. They are
|
|
159
|
+
announced as menu items when the menu is open.
|
|
160
|
+
|
|
161
|
+
### Accessibility Requirements
|
|
162
|
+
|
|
163
|
+
Required in application code for an accessible Action Bar. Rows marked _(conditional)_ apply only
|
|
164
|
+
when the situation matches—otherwise omit.
|
|
165
|
+
|
|
166
|
+
**If no design spec is provided:** render **`ActionBar`** → **`ActionBar.List`** with `as="section"`
|
|
167
|
+
and a translated **`aria-label`**, one primary **`ActionBar.Item`** first, followed by secondary
|
|
168
|
+
**`ActionBar.Item`** components with visible text. Omit `icon`, `disabled`, the overflow API, custom
|
|
169
|
+
`maximumVisible`, and custom `data-id` unless the spec requires them.
|
|
170
|
+
|
|
171
|
+
| Requirement | How to satisfy |
|
|
172
|
+
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
173
|
+
| Group label | `as="section"` and a translated **`aria-label`** on **`ActionBar.List`** that is unique among landmarks on the page |
|
|
174
|
+
| Item accessible name | Non-empty visible text as the child of every **`ActionBar.Item`** |
|
|
175
|
+
| Composition order | **`ActionBar`** → **`ActionBar.List`** → **`ActionBar.Item`**; add **`ActionBar.Menu`** as a sibling of **`ActionBar.List`** for overflow |
|
|
176
|
+
| Primary action _(conditional)_ | **`as={PrimaryButton}`** on only the first **`ActionBar.Item`**; secondary actions use the default; do not use **`TertiaryButton`** |
|
|
177
|
+
| Destructive action _(conditional)_ | **`as={DeleteButton}`** only for destructive actions, per design |
|
|
178
|
+
| Decorative icon _(conditional)_ | **`icon`** on **`ActionBar.Item`** with visible text—no extra ARIA on the icon |
|
|
179
|
+
| Overflow button name _(conditional)_ | Translated **`aria-label`** on **`ActionBar.OverflowButton`** (required by its type), passed through **`overflowButton`** on **`ActionBar.List`** |
|
|
180
|
+
| Overflow menu _(conditional)_ | Dynamic API: `items` on **`useActionBarModel`**, render props on both **`ActionBar.List`** and **`ActionBar.Menu.List`**, and **`ActionBar.Menu.Popper`** → **`Card`** → **`List`** → **`Item`** with the same item text |
|
|
181
|
+
| Menu item activation _(conditional)_ | The same `onClick` handler on **`ActionBar.Item`** and its **`ActionBar.Menu.Item`** counterpart so an action behaves the same wherever it renders |
|
|
182
|
+
| Fixed placement _(conditional)_ | **`ActionBar.List`** is `position: fixed` at the bottom of the viewport. Reserve space so page content and focused controls are not hidden behind it, or pass `position="relative"` when the bar sits in the page flow |
|
|
183
|
+
| Disabled action _(conditional)_ | Native **`disabled`** on **`ActionBar.Item`** when the spec marks the action unavailable |
|
|
184
|
+
|
|
185
|
+
**Summary for code generation:**
|
|
186
|
+
|
|
187
|
+
- **REQUIRED:** **`ActionBar.List`** with `as="section"` and a translated **`aria-label`**; every
|
|
188
|
+
**`ActionBar.Item`** with visible text; one primary action first
|
|
189
|
+
- **CONDITIONAL:** **`icon`**; **`DeleteButton`**; **`overflowButton`** with an **`aria-label`**;
|
|
190
|
+
matching **`ActionBar.Menu`** items and handlers; `position="relative"`; **`disabled`**
|
|
191
|
+
|
|
192
|
+
### Anti-Patterns
|
|
193
|
+
|
|
194
|
+
Do **not** generate code that does the following (see **Accessibility Requirements** above for what
|
|
195
|
+
to supply instead):
|
|
196
|
+
|
|
197
|
+
- Omit `as="section"` or **`aria-label`** on **`ActionBar.List`**, which leaves the group
|
|
198
|
+
unidentifiable to screen reader users
|
|
199
|
+
- Reuse the same **`aria-label`** for **`ActionBar.List`** and another landmark on the page
|
|
200
|
+
- Use more than one **`PrimaryButton`** or any **`TertiaryButton`** in an Action Bar
|
|
201
|
+
- Render **`ActionBar.Item`** without visible text or as a non-button element with `onClick`
|
|
202
|
+
- Add `role="toolbar"`, `role="group"`, roving tabindex, or arrow-key handlers to
|
|
203
|
+
**`ActionBar.List`**—each item must be a separate tab stop
|
|
204
|
+
- Render **`ActionBar.OverflowButton`** without **`aria-label`**
|
|
205
|
+
- Set `aria-haspopup`, `aria-expanded`, or `aria-hidden` on **`ActionBar.OverflowButton`** or
|
|
206
|
+
**`ActionBar.Item`**—the model sets them
|
|
207
|
+
- Hide overflowing items with CSS, `hidden`, or conditional rendering—use the dynamic API
|
|
208
|
+
and `maximumVisible`
|
|
209
|
+
- Use the overflow behavior with static children—it requires `items` on the model and render props
|
|
210
|
+
- Provide an overflow menu whose items differ in text or behavior from the action bar items
|
|
211
|
+
- Move focus manually after the overflow menu closes—**`Menu`** returns focus to the overflow button
|
|
212
|
+
- Leave the fixed **`ActionBar.List`** covering page content or focused controls
|
|
81
213
|
|
|
82
214
|
## Component API
|
|
83
215
|
|
|
@@ -113,47 +113,145 @@ tokens with the fallback being `brand.primary.**`.
|
|
|
113
113
|
|
|
114
114
|
## Accessibility
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
- Button padding ensures adequate spacing between interactive elements to prevent accidental
|
|
150
|
-
activation.
|
|
151
|
-
|
|
152
|
-
### Button Groups
|
|
116
|
+
The primary accessibility goal is a visible, programmatically determinable name on a native control
|
|
117
|
+
that performs an in-page action (submit, open, dismiss, and similar). This page covers
|
|
118
|
+
**`PrimaryButton`**, **`SecondaryButton`**, **`TertiaryButton`**, and **`DeleteButton`**. Use
|
|
119
|
+
[Hyperlink](https://workday.github.io/canvas-kit/?path=/docs/components-hyperlink--docs) when the
|
|
120
|
+
control navigates to another URL or in-page location. For
|
|
121
|
+
[Toolbar](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-toolbar--docs)
|
|
122
|
+
icon and dropdown controls, see that component’s documentation. For a control that opens a menu,
|
|
123
|
+
compose [Menu](/components/popups/menu/) so **`Menu.Target`** wires popup state. When users choose
|
|
124
|
+
one value from **two or more** mutually exclusive options, use
|
|
125
|
+
[Segmented Control](/components/buttons/segmented-control/) (`SegmentedControl.List` with multiple
|
|
126
|
+
**`SegmentedControl.Item`** components)—not a lone variant button.
|
|
127
|
+
|
|
128
|
+
See the [Button pattern (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/button/) and Canvas Kit
|
|
129
|
+
[Accessibility overview](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-overview--docs).
|
|
130
|
+
|
|
131
|
+
### Minimum Accessible Structure
|
|
132
|
+
|
|
133
|
+
The following matches the [PrimaryButton](#primarybutton) examples: visible text for the default case,
|
|
134
|
+
text plus a decorative icon, and an icon-only control with an accessible name.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import {PrimaryButton} from '@workday/canvas-kit-react/button';
|
|
138
|
+
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
139
|
+
import {plusIcon, relatedActionsVerticalIcon} from '@workday/canvas-system-icons-web';
|
|
140
|
+
|
|
141
|
+
<PrimaryButton>Save</PrimaryButton>;
|
|
142
|
+
|
|
143
|
+
<PrimaryButton icon={plusIcon}>Add item</PrimaryButton>;
|
|
144
|
+
|
|
145
|
+
<Tooltip title="Related Actions">
|
|
146
|
+
<PrimaryButton icon={relatedActionsVerticalIcon} />
|
|
147
|
+
</Tooltip>;
|
|
148
|
+
```
|
|
153
149
|
|
|
154
|
-
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
For icon-only buttons, prefer **`Tooltip`** with **`title`** and default `type="label"` (which sets
|
|
151
|
+
**`aria-label`** from **`title`** so sighted users also see the label). If the spec explicitly says
|
|
152
|
+
not to use a tooltip, set **`aria-label`** on the button instead. The same patterns apply to
|
|
153
|
+
**`SecondaryButton`**, **`TertiaryButton`**, and **`DeleteButton`**.
|
|
154
|
+
|
|
155
|
+
### Built-in Behaviors
|
|
156
|
+
|
|
157
|
+
Canvas Kit applies these automatically on **`PrimaryButton`**, **`SecondaryButton`**,
|
|
158
|
+
**`TertiaryButton`**, and **`DeleteButton`**. **Do not duplicate them** in consuming code.
|
|
159
|
+
|
|
160
|
+
**ARIA and DOM** (_applied by button components_):
|
|
161
|
+
|
|
162
|
+
- **Variant buttons**: Render a native `<button type="button">` (via **`BaseButton`**). Do not add
|
|
163
|
+
`role="button"`.
|
|
164
|
+
- **Visible label**: Button text is rendered in **`BaseButton.Label`** (`<span>`) inside the
|
|
165
|
+
`<button>` so its text contributes to the accessible name.
|
|
166
|
+
- **`icon`**: Renders **`BaseButton.Icon`** (`SystemIcon`). Canvas Kit icon SVG markup uses
|
|
167
|
+
`role="presentation"` and `focusable="false"`, so icons beside visible text are not announced
|
|
168
|
+
separately.
|
|
169
|
+
- **`disabled`**: Maps to the native `disabled` attribute; disabled buttons are skipped in the tab
|
|
170
|
+
order.
|
|
171
|
+
- **Focus**: Visible focus styling uses `:focus-visible` (and a `.focus` class twin for visual
|
|
172
|
+
testing).
|
|
173
|
+
- **`ref`**: Forwards to the underlying `<button>`.
|
|
174
|
+
- **Native button attributes**: Standard props (for example `aria-label`, `aria-pressed`,
|
|
175
|
+
`aria-expanded`, `id`, `onClick`) pass through to the `<button>` unless you change the element with
|
|
176
|
+
**`as`**. Variant buttons do not set **`aria-pressed`** unless you pass it for a deliberate toggle
|
|
177
|
+
design.
|
|
178
|
+
- **Menus**: Variant buttons do **not** set `aria-haspopup` or `aria-expanded`.
|
|
179
|
+
**`Menu.Target`** (and related Menu APIs) apply those when a menu is attached.
|
|
180
|
+
|
|
181
|
+
**Keyboard** (_native `<button>` behavior_):
|
|
182
|
+
|
|
183
|
+
Variant buttons use native button keyboard support: <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd>
|
|
184
|
+
for focus order, and <kbd>Enter</kbd> or <kbd>Space</kbd> to activate. Do not replace the
|
|
185
|
+
`<button>` with a non-focusable element or suppress activation keys.
|
|
186
|
+
|
|
187
|
+
**Screen reader expectations** (_when built-in behaviors are used as intended_):
|
|
188
|
+
|
|
189
|
+
- On focus, assistive technology announces the button name (visible text and/or `aria-label`) and
|
|
190
|
+
role (for example, "Save, button").
|
|
191
|
+
- Icons rendered with **`icon`** next to visible text are not announced as separate images.
|
|
192
|
+
- Disabled buttons are announced as unavailable and are not in the tab order.
|
|
193
|
+
- When the button opens a menu through **`Menu`**, **`Menu.Target`** exposes popup and expanded
|
|
194
|
+
state; see [Menu accessibility](/components/popups/menu/#accessibility).
|
|
195
|
+
|
|
196
|
+
### Accessibility Requirements
|
|
197
|
+
|
|
198
|
+
Required in application code for an accessible button. Rows marked _(conditional)_ apply only when the
|
|
199
|
+
situation matches—otherwise omit.
|
|
200
|
+
|
|
201
|
+
**If no design spec is provided:** use a **`PrimaryButton`** (or the variant that matches the design)
|
|
202
|
+
with non-empty visible text. Omit **`icon`**, **`disabled`**, **`Tooltip`**, **`aria-label`**, custom
|
|
203
|
+
**`id`**, **`as`**, and a **`ref`** unless the spec requires them.
|
|
204
|
+
|
|
205
|
+
| Requirement | How to satisfy |
|
|
206
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
207
|
+
| Accessible name | Non-empty visible text inside the variant button |
|
|
208
|
+
| Icon-only name _(conditional)_ | **`Tooltip`** with `type="label"` and **`title`** (preferred; see [PrimaryButton](#primarybutton)), or **`aria-label`** when the spec explicitly says not to use a tooltip. Do not use `type="muted"` on **`Tooltip`**—it does not set an accessible name |
|
|
209
|
+
| Variant choice | **`PrimaryButton`**, **`SecondaryButton`**, **`TertiaryButton`**, or **`DeleteButton`** per design; **`DeleteButton`** only for destructive actions |
|
|
210
|
+
| Decorative icon _(conditional)_ | **`icon`** with visible text—no extra ARIA on the icon; meaning comes from button text |
|
|
211
|
+
| Mutually exclusive group _(conditional)_ | [Segmented Control](/components/buttons/segmented-control/) with two or more **`SegmentedControl.Item`** siblings and **`aria-label`** on **`SegmentedControl.List`**—not for a single button or lone on/off control |
|
|
212
|
+
| Toggle pressed state _(conditional)_ | **`aria-pressed`** on a variant button for a standalone on/off control, or [Toolbar](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-toolbar--docs) per toolbar specs—not for one-shot actions (Save, Delete, Open) |
|
|
213
|
+
| Menu trigger _(conditional)_ | **`Menu`** + **`Menu.Target`** (or **`Menu.ContextTarget`**) as the button—do not hand-wire `aria-haspopup` / `aria-expanded` without the Menu model; see [Menu accessibility](/components/popups/menu/#accessibility) |
|
|
214
|
+
| Related button groups _(conditional)_ | Semantic grouping (`<ul>` / `<li>` or `<fieldset>` / `<legend>`) when several buttons share one question or legend; each control still needs its own accessible name |
|
|
215
|
+
| Disabled _(conditional)_ | Native **`disabled`** on the variant button when the spec marks the action unavailable |
|
|
216
|
+
| Navigation _(conditional)_ | [Hyperlink](https://workday.github.io/canvas-kit/?path=/docs/components-hyperlink--docs) instead of a variant button when the action is navigation |
|
|
217
|
+
| Programmatic focus _(conditional)_ | `ref` on the variant button and `focus()` only when the product must move focus after an action—omit by default |
|
|
218
|
+
|
|
219
|
+
**Summary for code generation:**
|
|
220
|
+
|
|
221
|
+
- **REQUIRED:** variant button with a non-empty accessible name (visible text for text buttons; for
|
|
222
|
+
icon-only, **`Tooltip`** with `type="label"` preferred, or **`aria-label`** when the spec says not
|
|
223
|
+
to use a tooltip)
|
|
224
|
+
- **CONDITIONAL:** **`icon`**; icon-only naming; **`disabled`**; **`aria-pressed`** for toggle
|
|
225
|
+
specs; **`Menu`** for menus; **`Hyperlink`** for navigation; grouping markup; programmatic focus
|
|
226
|
+
via `ref`
|
|
227
|
+
|
|
228
|
+
### Anti-Patterns
|
|
229
|
+
|
|
230
|
+
Do **not** generate code that does the following (see **Accessibility Requirements** above for what
|
|
231
|
+
to supply instead):
|
|
232
|
+
|
|
233
|
+
- Use a `<div>` or `<span>` with `onClick` instead of a variant button—use **`PrimaryButton`**, **`SecondaryButton`**, **`TertiaryButton`**, or **`DeleteButton`** so keyboard and assistive technology get native `<button>` behavior
|
|
234
|
+
- Add `role="button"` on variant buttons—the control is already a `<button>`
|
|
235
|
+
- Use a variant button (or `type="submit"` without an intentional form action) for URL
|
|
236
|
+
navigation—use
|
|
237
|
+
[Hyperlink](https://workday.github.io/canvas-kit/?path=/docs/components-hyperlink--docs)
|
|
238
|
+
- Leave icon-only buttons without a name—prefer **`Tooltip`** with `type="label"`, or
|
|
239
|
+
**`aria-label`** when the spec says not to use a tooltip; do not rely on the icon graphic alone
|
|
240
|
+
- Use **`Tooltip`** with `type="muted"` on icon-only buttons—muted tooltips do not set an accessible
|
|
241
|
+
name
|
|
242
|
+
- Use **`aria-label`** on icon-only buttons when the spec allows tooltips—prefer **`Tooltip`** with
|
|
243
|
+
`type="label"` unless the spec explicitly says not to use a tooltip
|
|
244
|
+
- Set `aria-haspopup` or `aria-expanded` on a variant button without **`Menu`**—use
|
|
245
|
+
**`Menu.Target`** so open state stays in sync with the menu model
|
|
246
|
+
- Set **`aria-pressed`** on one-shot actions (Save, Delete, Open)—see **Toggle pressed state** in the
|
|
247
|
+
requirements table
|
|
248
|
+
- Use **`SegmentedControl`** for a single option or a lone on/off control—see **Mutually exclusive
|
|
249
|
+
group** in the requirements table
|
|
250
|
+
- Add `aria-hidden` or change the **`role`** on **`icon`** when visible button text already conveys
|
|
251
|
+
meaning—Canvas Kit icons are presentational.
|
|
252
|
+
- Use **`aria-disabled`** instead of **`disabled`**—variant buttons map unavailability to the
|
|
253
|
+
native **`disabled`** attribute
|
|
254
|
+
- Duplicate menu ARIA that **`Menu.Target`** already applies
|
|
157
255
|
|
|
158
256
|
## Component API
|
|
159
257
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "17.0.0-alpha.
|
|
3
|
+
"version": "17.0.0-alpha.0631-next.0",
|
|
4
4
|
"description": "Documentation components of Canvas Kit components",
|
|
5
5
|
"author": "Workday, Inc. (https://www.workday.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"@stackblitz/sdk": "^1.11.0",
|
|
48
48
|
"@storybook/csf": "0.0.1",
|
|
49
49
|
"@workday/canvas-expressive-icons-web": "1.0.2",
|
|
50
|
-
"@workday/canvas-kit-labs-react": "^17.0.0-alpha.
|
|
51
|
-
"@workday/canvas-kit-preview-react": "^17.0.0-alpha.
|
|
52
|
-
"@workday/canvas-kit-react": "^17.0.0-alpha.
|
|
53
|
-
"@workday/canvas-kit-styling": "^17.0.0-alpha.
|
|
50
|
+
"@workday/canvas-kit-labs-react": "^17.0.0-alpha.0631-next.0",
|
|
51
|
+
"@workday/canvas-kit-preview-react": "^17.0.0-alpha.0631-next.0",
|
|
52
|
+
"@workday/canvas-kit-react": "^17.0.0-alpha.0631-next.0",
|
|
53
|
+
"@workday/canvas-kit-styling": "^17.0.0-alpha.0631-next.0",
|
|
54
54
|
"@workday/canvas-system-icons-web": "^5.0.3",
|
|
55
55
|
"@workday/canvas-tokens-web": "^4.4.0",
|
|
56
56
|
"markdown-to-jsx": "^7.2.0",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"mkdirp": "^1.0.3",
|
|
64
64
|
"typescript": "5.0"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "cca2de38ec1c9736ce2d71f962e522a4861b82c2"
|
|
67
67
|
}
|