@workday/canvas-kit-docs 16.2.0-0622-next.0 → 16.2.0-0634-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/docs.js +8701 -3060
- package/dist/es6/lib/specs.js +17 -17
- 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/preview-react/tabs/examples/OverflowTabs.tsx +7 -2
- package/dist/mdx/react/action-bar/ActionBar.mdx +139 -7
- package/dist/mdx/react/button/button/Button.mdx +138 -40
- package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +7 -2
- package/package.json +6 -6
package/dist/es6/lib/specs.js
CHANGED
|
@@ -6667,7 +6667,7 @@ module.exports = {specifications: [
|
|
|
6667
6667
|
},
|
|
6668
6668
|
{
|
|
6669
6669
|
"type": "it",
|
|
6670
|
-
"name": "should not show the \"More\"
|
|
6670
|
+
"name": "should not show the \"More\" overflow tab"
|
|
6671
6671
|
},
|
|
6672
6672
|
{
|
|
6673
6673
|
"type": "it",
|
|
@@ -6687,7 +6687,7 @@ module.exports = {specifications: [
|
|
|
6687
6687
|
"children": [
|
|
6688
6688
|
{
|
|
6689
6689
|
"type": "it",
|
|
6690
|
-
"name": "should focus
|
|
6690
|
+
"name": "should move focus out of the tablist to the next focusable (width control)"
|
|
6691
6691
|
}
|
|
6692
6692
|
]
|
|
6693
6693
|
}
|
|
@@ -6703,11 +6703,11 @@ module.exports = {specifications: [
|
|
|
6703
6703
|
},
|
|
6704
6704
|
{
|
|
6705
6705
|
"type": "it",
|
|
6706
|
-
"name": "should show the \"More\"
|
|
6706
|
+
"name": "should show the \"More\" overflow tab"
|
|
6707
6707
|
},
|
|
6708
6708
|
{
|
|
6709
6709
|
"type": "it",
|
|
6710
|
-
"name": "should show
|
|
6710
|
+
"name": "should show visible content tabs plus the More overflow tab"
|
|
6711
6711
|
},
|
|
6712
6712
|
{
|
|
6713
6713
|
"type": "it",
|
|
@@ -6719,11 +6719,11 @@ module.exports = {specifications: [
|
|
|
6719
6719
|
"children": [
|
|
6720
6720
|
{
|
|
6721
6721
|
"type": "describe",
|
|
6722
|
-
"name": "when the
|
|
6722
|
+
"name": "when the Right Arrow key is pressed until the More overflow tab",
|
|
6723
6723
|
"children": [
|
|
6724
6724
|
{
|
|
6725
6725
|
"type": "it",
|
|
6726
|
-
"name": "should focus on the \"More\"
|
|
6726
|
+
"name": "should focus on the \"More\" overflow tab"
|
|
6727
6727
|
}
|
|
6728
6728
|
]
|
|
6729
6729
|
}
|
|
@@ -6731,7 +6731,7 @@ module.exports = {specifications: [
|
|
|
6731
6731
|
},
|
|
6732
6732
|
{
|
|
6733
6733
|
"type": "describe",
|
|
6734
|
-
"name": "when the \"More\"
|
|
6734
|
+
"name": "when the \"More\" overflow tab is clicked",
|
|
6735
6735
|
"children": [
|
|
6736
6736
|
{
|
|
6737
6737
|
"type": "it",
|
|
@@ -6751,7 +6751,7 @@ module.exports = {specifications: [
|
|
|
6751
6751
|
},
|
|
6752
6752
|
{
|
|
6753
6753
|
"type": "it",
|
|
6754
|
-
"name": "should move focus
|
|
6754
|
+
"name": "should move focus to the Sixth Tab"
|
|
6755
6755
|
}
|
|
6756
6756
|
]
|
|
6757
6757
|
}
|
|
@@ -6769,7 +6769,7 @@ module.exports = {specifications: [
|
|
|
6769
6769
|
},
|
|
6770
6770
|
{
|
|
6771
6771
|
"type": "it",
|
|
6772
|
-
"name": "should show the \"More\"
|
|
6772
|
+
"name": "should show the \"More\" overflow tab"
|
|
6773
6773
|
},
|
|
6774
6774
|
{
|
|
6775
6775
|
"type": "it",
|
|
@@ -6777,11 +6777,11 @@ module.exports = {specifications: [
|
|
|
6777
6777
|
},
|
|
6778
6778
|
{
|
|
6779
6779
|
"type": "it",
|
|
6780
|
-
"name": "should show
|
|
6780
|
+
"name": "should show 2 content tabs plus the More overflow tab (3 total)"
|
|
6781
6781
|
},
|
|
6782
6782
|
{
|
|
6783
6783
|
"type": "describe",
|
|
6784
|
-
"name": "when the \"More\"
|
|
6784
|
+
"name": "when the \"More\" overflow tab is clicked",
|
|
6785
6785
|
"children": [
|
|
6786
6786
|
{
|
|
6787
6787
|
"type": "it",
|
|
@@ -6789,7 +6789,7 @@ module.exports = {specifications: [
|
|
|
6789
6789
|
},
|
|
6790
6790
|
{
|
|
6791
6791
|
"type": "it",
|
|
6792
|
-
"name": "should have the
|
|
6792
|
+
"name": "should have the third Tab as the first menu item"
|
|
6793
6793
|
}
|
|
6794
6794
|
]
|
|
6795
6795
|
}
|
|
@@ -6805,7 +6805,7 @@ module.exports = {specifications: [
|
|
|
6805
6805
|
},
|
|
6806
6806
|
{
|
|
6807
6807
|
"type": "it",
|
|
6808
|
-
"name": "should show the \"More\"
|
|
6808
|
+
"name": "should show the \"More\" overflow tab"
|
|
6809
6809
|
},
|
|
6810
6810
|
{
|
|
6811
6811
|
"type": "it",
|
|
@@ -6813,11 +6813,11 @@ module.exports = {specifications: [
|
|
|
6813
6813
|
},
|
|
6814
6814
|
{
|
|
6815
6815
|
"type": "it",
|
|
6816
|
-
"name": "should show
|
|
6816
|
+
"name": "should show only the More overflow tab (1 tab when all content tabs overflow)"
|
|
6817
6817
|
},
|
|
6818
6818
|
{
|
|
6819
6819
|
"type": "describe",
|
|
6820
|
-
"name": "when the \"More\"
|
|
6820
|
+
"name": "when the \"More\" overflow tab is clicked",
|
|
6821
6821
|
"children": [
|
|
6822
6822
|
{
|
|
6823
6823
|
"type": "it",
|
|
@@ -6825,7 +6825,7 @@ module.exports = {specifications: [
|
|
|
6825
6825
|
},
|
|
6826
6826
|
{
|
|
6827
6827
|
"type": "it",
|
|
6828
|
-
"name": "should have
|
|
6828
|
+
"name": "should have focus on the first menu item (First Tab)"
|
|
6829
6829
|
}
|
|
6830
6830
|
]
|
|
6831
6831
|
}
|
|
@@ -6837,7 +6837,7 @@ module.exports = {specifications: [
|
|
|
6837
6837
|
"children": [
|
|
6838
6838
|
{
|
|
6839
6839
|
"type": "it",
|
|
6840
|
-
"name": "should not show the \"More\"
|
|
6840
|
+
"name": "should not show the \"More\" overflow tab"
|
|
6841
6841
|
},
|
|
6842
6842
|
{
|
|
6843
6843
|
"type": "it",
|
|
@@ -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.8",
|
|
22
|
+
"@workday/canvas-kit-preview-react": "16.1.8",
|
|
23
|
+
"@workday/canvas-kit-react": "16.1.8",
|
|
24
|
+
"@workday/canvas-kit-react-fonts": "^16.1.8",
|
|
25
|
+
"@workday/canvas-kit-styling": "16.1.8",
|
|
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.8",
|
|
23
|
+
"@workday/canvas-kit-preview-react": "16.1.8",
|
|
24
|
+
"@workday/canvas-kit-react": "16.1.8",
|
|
25
|
+
"@workday/canvas-kit-react-fonts": "^16.1.8",
|
|
26
|
+
"@workday/canvas-kit-styling": "16.1.8",
|
|
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
|
|
|
@@ -3,6 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import {Tabs, useTabsModel} from '@workday/canvas-kit-preview-react/tabs';
|
|
4
4
|
import {Box} from '@workday/canvas-kit-react/layout';
|
|
5
5
|
import {SegmentedControl} from '@workday/canvas-kit-react/segmented-control';
|
|
6
|
+
import {Heading} from '@workday/canvas-kit-react/text';
|
|
6
7
|
import {px2rem} from '@workday/canvas-kit-styling';
|
|
7
8
|
import {system} from '@workday/canvas-tokens-web';
|
|
8
9
|
|
|
@@ -42,13 +43,17 @@ export default () => {
|
|
|
42
43
|
</Tabs.Menu.Popper>
|
|
43
44
|
<Tabs.Panels>
|
|
44
45
|
{(item: MyTabItem) => (
|
|
45
|
-
<Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>
|
|
46
|
+
<Tabs.Panel tabIndex={-1} cs={{marginBlockStart: system.gap.lg}}>
|
|
47
|
+
{item.contents}
|
|
48
|
+
</Tabs.Panel>
|
|
46
49
|
)}
|
|
47
50
|
</Tabs.Panels>
|
|
48
51
|
</Tabs>
|
|
49
52
|
</Box>
|
|
50
53
|
<hr />
|
|
51
|
-
<
|
|
54
|
+
<Heading size="small" as="h4">
|
|
55
|
+
Change Tabs container size
|
|
56
|
+
</Heading>
|
|
52
57
|
<SegmentedControl onSelect={data => setContainerWidth(data.id)}>
|
|
53
58
|
<SegmentedControl.List aria-label="container width control">
|
|
54
59
|
<SegmentedControl.Item data-id="100%">100%</SegmentedControl.Item>
|
|
@@ -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
|
|
|
@@ -3,6 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import {Box} from '@workday/canvas-kit-react/layout';
|
|
4
4
|
import {SegmentedControl} from '@workday/canvas-kit-react/segmented-control';
|
|
5
5
|
import {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';
|
|
6
|
+
import {Heading} from '@workday/canvas-kit-react/text';
|
|
6
7
|
import {px2rem} from '@workday/canvas-kit-styling';
|
|
7
8
|
import {system} from '@workday/canvas-tokens-web';
|
|
8
9
|
|
|
@@ -43,13 +44,17 @@ export default () => {
|
|
|
43
44
|
</Tabs.Menu.Popper>
|
|
44
45
|
<Tabs.Panels>
|
|
45
46
|
{(item: MyTabItem) => (
|
|
46
|
-
<Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>
|
|
47
|
+
<Tabs.Panel tabIndex={-1} cs={{marginBlockStart: system.gap.lg}}>
|
|
48
|
+
{item.contents}
|
|
49
|
+
</Tabs.Panel>
|
|
47
50
|
)}
|
|
48
51
|
</Tabs.Panels>
|
|
49
52
|
</Tabs>
|
|
50
53
|
</Box>
|
|
51
54
|
<hr />
|
|
52
|
-
<
|
|
55
|
+
<Heading size="small" as="h4">
|
|
56
|
+
Change Tabs container size
|
|
57
|
+
</Heading>
|
|
53
58
|
<SegmentedControl onSelect={data => setContainerWidth(data.id)}>
|
|
54
59
|
<SegmentedControl.List aria-label="container width control">
|
|
55
60
|
<SegmentedControl.Item data-id="100%">100%</SegmentedControl.Item>
|