@workday/canvas-kit-docs 14.0.0 → 14.0.2
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/es6/mdx/accessibility/examples/AriaLiveRegions/FilterListWithLiveStatus.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/FilterListWithLiveStatus.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/FilterListWithLiveStatus.js +43 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/HiddenLiveRegion.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/HiddenLiveRegion.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/HiddenLiveRegion.js +27 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/IconButtonsWithLiveBadges.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/IconButtonsWithLiveBadges.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/IconButtonsWithLiveBadges.js +51 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/TextInputWithLiveError.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/TextInputWithLiveError.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/TextInputWithLiveError.js +19 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/VisibleLiveRegion.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/VisibleLiveRegion.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/AriaLiveRegions/VisibleLiveRegion.js +36 -0
- package/dist/es6/mdx/accessibility/examples/GlobalHeader.d.ts +8 -0
- package/dist/es6/mdx/accessibility/examples/GlobalHeader.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/GlobalHeader.js +149 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/BreadcrumbNavRegion.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/BreadcrumbNavRegion.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/BreadcrumbNavRegion.js +12 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/FullPageDemo.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/FullPageDemo.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/FullPageDemo.js +40 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/LandmarkRegions.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/LandmarkRegions.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/PageStructure/LandmarkRegions.js +22 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithNavigation.d.ts +3 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithNavigation.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithNavigation.js +100 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithOverlay.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithOverlay.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/SidePanelWithOverlay.js +31 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithColumnHeaderFilters.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithColumnHeaderFilters.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithColumnHeaderFilters.js +101 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithExpandableRows.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithExpandableRows.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithExpandableRows.js +115 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithFormFields.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithFormFields.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithFormFields.js +79 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSelectableRows.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSelectableRows.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSelectableRows.js +89 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSortableColumnHeaders.d.ts +2 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSortableColumnHeaders.d.ts.map +1 -0
- package/dist/es6/mdx/accessibility/examples/Table/WithSortableColumnHeaders.js +114 -0
- package/dist/mdx/accessibility/AccessibilityOverview.mdx +167 -0
- package/dist/mdx/accessibility/AccessibilityTesting.mdx +10 -0
- package/dist/mdx/{react/_examples/mdx → accessibility}/Headers.mdx +0 -1
- package/dist/mdx/accessibility/PageStructure.mdx +58 -0
- package/dist/mdx/{react/_examples/mdx → accessibility}/SidePanel.mdx +1 -6
- package/dist/mdx/{react/_examples/mdx → accessibility}/TablesAdvanced.mdx +11 -0
- package/dist/mdx/accessibility/WindowsHighContrastThemes.mdx +97 -0
- package/dist/mdx/react/layout/examples/Grid/Basic.tsx +41 -60
- package/package.json +6 -6
- package/dist/mdx/react/_examples/mdx/AccessibilityOverview.mdx +0 -18
- package/dist/mdx/react/_examples/mdx/examples/AriaLiveRegions/FilterListWithLiveStatus.tsx +0 -73
- package/dist/mdx/react/_examples/mdx/examples/AriaLiveRegions/HiddenLiveRegion.tsx +0 -46
- package/dist/mdx/react/_examples/mdx/examples/AriaLiveRegions/IconButtonsWithLiveBadges.tsx +0 -98
- package/dist/mdx/react/_examples/mdx/examples/AriaLiveRegions/TextInputWithLiveError.tsx +0 -31
- package/dist/mdx/react/_examples/mdx/examples/AriaLiveRegions/VisibleLiveRegion.tsx +0 -61
- package/dist/mdx/react/_examples/mdx/examples/GlobalHeader.tsx +0 -295
- package/dist/mdx/react/_examples/mdx/examples/SidePanelWithNavigation.tsx +0 -168
- package/dist/mdx/react/_examples/mdx/examples/SidePanelWithOverlay.tsx +0 -46
- package/dist/mdx/react/_examples/mdx/examples/Table/WithColumnHeaderFilters.tsx +0 -202
- package/dist/mdx/react/_examples/mdx/examples/Table/WithExpandableRows.tsx +0 -216
- package/dist/mdx/react/_examples/mdx/examples/Table/WithSelectableRows.tsx +0 -156
- package/dist/mdx/react/_examples/mdx/examples/Table/WithSortableColumnHeaders.tsx +0 -213
- package/dist/mdx/react/_examples/mdx/examples/common/FilterListWithLiveStatus.tsx +0 -68
- package/dist/mdx/react/_examples/mdx/examples/common/HiddenLiveRegion.tsx +0 -33
- package/dist/mdx/react/_examples/mdx/examples/common/IconButtonsWithLiveBadges.tsx +0 -98
- package/dist/mdx/react/_examples/mdx/examples/common/TextInputWithLiveError.tsx +0 -28
- package/dist/mdx/react/_examples/mdx/examples/common/VisibleLiveRegion.tsx +0 -44
- /package/dist/mdx/{react/_examples/mdx → accessibility}/AriaLiveRegions.mdx +0 -0
- /package/dist/mdx/react/_examples/{examples/Tooltips → mdx/examples}/ListOfUploadedFiles.tsx +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { createComponent } from '@workday/canvas-kit-react/common';
|
|
4
|
+
import { Table } from '@workday/canvas-kit-react/table';
|
|
5
|
+
import { Tooltip } from '@workday/canvas-kit-react/tooltip';
|
|
6
|
+
import { TertiaryButton } from '@workday/canvas-kit-react/button';
|
|
7
|
+
import { Text } from '@workday/canvas-kit-react/text';
|
|
8
|
+
import { sortDownIcon, sortUpIcon } from '@workday/canvas-system-icons-web';
|
|
9
|
+
import { createStyles } from '@workday/canvas-kit-styling';
|
|
10
|
+
import { system } from '@workday/canvas-tokens-web';
|
|
11
|
+
const countryData = [
|
|
12
|
+
{ country: 'Australia', capital: 'Canberra', population: 25690000 },
|
|
13
|
+
{ country: 'Bahamas', capital: 'Nassau', population: 407906 },
|
|
14
|
+
{ country: 'Canada', capital: 'Ottawa', population: 38250000 },
|
|
15
|
+
{ country: 'Fiji', capital: 'Suva', population: 924610 },
|
|
16
|
+
{ country: 'Ghana', capital: 'Accra', population: 32830000 },
|
|
17
|
+
{ country: 'Hong Kong', capital: 'City of Victoria', population: 7413000 },
|
|
18
|
+
{ country: 'India', capital: 'New Delhi', population: 1408000000 },
|
|
19
|
+
{ country: 'Ireland', capital: 'Dublin', population: 5033000 },
|
|
20
|
+
{ country: 'Jamaica', capital: 'Kingston', population: 2828000 },
|
|
21
|
+
{ country: 'Kenya', capital: 'Nairobi', population: 53010000 },
|
|
22
|
+
{ country: 'Micronesia', capital: 'Palikir', population: 113131 },
|
|
23
|
+
{ country: 'New Zealand', capital: 'Wellington', population: 5123000 },
|
|
24
|
+
{ country: 'Philippines', capital: 'Manila', population: 113900000 },
|
|
25
|
+
{ country: 'Puerto Rico', capital: 'San Juan', population: 3264000 },
|
|
26
|
+
{ country: 'Samoa', capital: 'Apia', population: 218764 },
|
|
27
|
+
{ country: 'Singapore', capital: 'Singapore', population: 5454000 },
|
|
28
|
+
{ country: 'Tanzania', capital: 'Dodoma', population: 63590000 },
|
|
29
|
+
{ country: 'United Kingdom', capital: 'London', population: 67330000 },
|
|
30
|
+
{ country: 'United States', capital: 'Washington, D.C.', population: 331900000 },
|
|
31
|
+
{ country: 'Zimbabwe', capital: 'Harare', population: 15990000 },
|
|
32
|
+
];
|
|
33
|
+
const initialHeaderRowState = {
|
|
34
|
+
column1SortDirection: 'ascending',
|
|
35
|
+
column2SortDirection: 'none',
|
|
36
|
+
column3SortDirection: 'none',
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Given the current sort order, return the next sort order
|
|
40
|
+
*/
|
|
41
|
+
function getNextSortOrder(sortOrder) {
|
|
42
|
+
return sortOrder === 'ascending' ? 'descending' : 'ascending';
|
|
43
|
+
}
|
|
44
|
+
function headerRowReducer(state, action) {
|
|
45
|
+
switch (action.column) {
|
|
46
|
+
case 'Country':
|
|
47
|
+
if (state.column1SortDirection === 'ascending') {
|
|
48
|
+
action.payload.sort((a, b) => b.country.localeCompare(a.country));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
action.payload.sort((a, b) => a.country.localeCompare(b.country));
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...initialHeaderRowState,
|
|
55
|
+
column1SortDirection: getNextSortOrder(state.column1SortDirection),
|
|
56
|
+
};
|
|
57
|
+
case 'Capital':
|
|
58
|
+
if (state.column2SortDirection === 'ascending') {
|
|
59
|
+
action.payload.sort((a, b) => b.capital.localeCompare(a.capital));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
action.payload.sort((a, b) => a.capital.localeCompare(b.capital));
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
...initialHeaderRowState,
|
|
66
|
+
column2SortDirection: getNextSortOrder(state.column2SortDirection),
|
|
67
|
+
};
|
|
68
|
+
case 'Population':
|
|
69
|
+
if (state.column3SortDirection === 'ascending') {
|
|
70
|
+
action.payload.sort((a, b) => b.population - a.population);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
action.payload.sort((a, b) => a.population - b.population);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
...initialHeaderRowState,
|
|
77
|
+
column3SortDirection: getNextSortOrder(state.column3SortDirection),
|
|
78
|
+
};
|
|
79
|
+
default:
|
|
80
|
+
return initialHeaderRowState;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const getSortIcon = (sortOrder) => {
|
|
84
|
+
if (sortOrder === 'ascending') {
|
|
85
|
+
return sortUpIcon;
|
|
86
|
+
}
|
|
87
|
+
else if (sortOrder === 'descending') {
|
|
88
|
+
return sortDownIcon;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const SortableColumnHeader = createComponent('th')({
|
|
95
|
+
displayName: 'SortableColumnHeader',
|
|
96
|
+
Component: ({ label, sortOrder, onSortAction, children, ...elemProps }, ref) => {
|
|
97
|
+
return (_jsx(Table.Header, { ref: ref, scope: "col", "aria-sort": sortOrder, ...elemProps, children: _jsx(Tooltip, { type: "description", title: `Sort ${getNextSortOrder(sortOrder)}`, children: _jsx(TertiaryButton, { icon: getSortIcon(sortOrder), iconPosition: "end", onClick: () => onSortAction(label), children: children }) }) }));
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const textStyles = createStyles({
|
|
101
|
+
paddingInlineStart: system.space.x3,
|
|
102
|
+
});
|
|
103
|
+
export const SortableColumnHeaders = () => {
|
|
104
|
+
const [headerRowState, headerRowDispatch] = React.useReducer(headerRowReducer, initialHeaderRowState);
|
|
105
|
+
function sortColumnHandler(columnName) {
|
|
106
|
+
headerRowDispatch({
|
|
107
|
+
column: columnName,
|
|
108
|
+
payload: countryData,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return (_jsxs(Table, { maxHeight: "40rem", children: [_jsx(Table.Caption, { children: "Population Listed by Country (2021)" }), _jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(SortableColumnHeader, { label: "Country", sortOrder: headerRowState.column1SortDirection, onSortAction: sortColumnHandler, children: "Country" }), _jsx(SortableColumnHeader, { label: "Capital", sortOrder: headerRowState.column2SortDirection, onSortAction: sortColumnHandler, children: "Capital" }), _jsx(SortableColumnHeader, { label: "Population", sortOrder: headerRowState.column3SortDirection, onSortAction: sortColumnHandler, children: "Population" })] }) }), _jsx(Table.Body, { children: countryData.map(item => {
|
|
112
|
+
return (_jsxs(Table.Row, { children: [_jsx(Table.Header, { scope: "row", children: _jsx(Text, { cs: textStyles, children: item.country }) }), _jsx(Table.Cell, { children: _jsx(Text, { cs: textStyles, children: item.capital }) }), _jsx(Table.Cell, { children: _jsx(Text, { cs: textStyles, children: item.population.toLocaleString() }) })] }, item.country));
|
|
113
|
+
}) })] }));
|
|
114
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
## Canvas Kit Accessibility
|
|
2
|
+
|
|
3
|
+
Canvas Kit is built with accessibility in mind and we continuously strive to provide a robust set of
|
|
4
|
+
accessible components that are easy to customize for your needs. Core concepts and key investments
|
|
5
|
+
made by the Canvas Kit development team are introduced in the sections below and throughout this
|
|
6
|
+
guide.
|
|
7
|
+
|
|
8
|
+
## Read Me First
|
|
9
|
+
|
|
10
|
+
**No ARIA is better than Bad ARIA.**
|
|
11
|
+
[Read Me First | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/)
|
|
12
|
+
|
|
13
|
+
Accessible Rich Internet Applications (ARIA) is like CSS styling for assistive technologies. Unlike
|
|
14
|
+
CSS however, ARIA mistakes and gaps in support are not clearly visible to designers and developers.
|
|
15
|
+
Canvas Kit components are built with semantic HTML and include as much of the required ARIA as
|
|
16
|
+
possible according to the [WAI-ARIA 1.2 specification](https://www.w3.org/TR/wai-aria-1.2/)
|
|
17
|
+
recommended by the W3C and the patterns found in the ARIA Authoring Practices Guide. (APG)
|
|
18
|
+
|
|
19
|
+
## The Accessibility Tree
|
|
20
|
+
|
|
21
|
+
The Accessibility Tree is created by the web browser from the semantic information provided in the
|
|
22
|
+
document object model (DOM). It's like a simplified outline containing only the most important
|
|
23
|
+
information: the elements on the page, what they are (e.g., a button, a link, a heading), and what
|
|
24
|
+
they do. This tree is what a screen reader uses to tell a person what's on the page and how to
|
|
25
|
+
interact with it.
|
|
26
|
+
|
|
27
|
+
- `name:` a.k.a. “Label” describes the purpose of an element. (E.g. text fields provided for first
|
|
28
|
+
name, last name, and street address.)
|
|
29
|
+
- `role:` describes what an element is and how it can be used. (E.g. a text field, radio button
|
|
30
|
+
group, or single checkbox.)
|
|
31
|
+
- `state:` describes the current state of an element. (E.g. whether a text field is empty or
|
|
32
|
+
displaying text.)
|
|
33
|
+
|
|
34
|
+
Further reading:
|
|
35
|
+
[Full accessibility tree in Chrome DevTools](https://developer.chrome.com/blog/full-accessibility-tree#main-content)
|
|
36
|
+
|
|
37
|
+
## Accessible Names and Descriptions
|
|
38
|
+
|
|
39
|
+
Giving an element an **accessible name** is like giving it a label. It's a short phrase, like
|
|
40
|
+
"Search" or "Submit," that a screen reader uses to tell a person what an item is. This helps a user
|
|
41
|
+
understand the element's purpose and tell it apart from other items on the page. Some items, like
|
|
42
|
+
buttons and links, are required to have an accessible name. You can also add an **accessible
|
|
43
|
+
description** if you need to provide more information. This could be instructions for a form field
|
|
44
|
+
or a longer explanation of what a button does. A screen reader will read the name first, and then
|
|
45
|
+
the description, giving the user all the information they need to understand and use the element.
|
|
46
|
+
|
|
47
|
+
To make a website accessible to everyone, follow these five cardinal rules for naming web elements:
|
|
48
|
+
always **prefer visible text and native techniques** like HTML labels, which are simpler and more
|
|
49
|
+
reliable. You should also **avoid browser fallback** like the title attribute or placeholder values.
|
|
50
|
+
The names themselves should be **brief and useful**. Lastly, you should always **heed warnings and
|
|
51
|
+
test thoroughly** to ensure everything works correctly.
|
|
52
|
+
|
|
53
|
+
### Naming Priority (Simplified):
|
|
54
|
+
|
|
55
|
+
1. `aria-labelledby` (unique id)
|
|
56
|
+
2. `aria-label` (string)
|
|
57
|
+
3. `<label>` and `for` attribute with unique `id` (for input)
|
|
58
|
+
4. `placeholder` (for input)
|
|
59
|
+
5. `alt` (for images)
|
|
60
|
+
6. `text content` (between opening and closing tags)
|
|
61
|
+
7. `title` (string)
|
|
62
|
+
|
|
63
|
+
Further reading:
|
|
64
|
+
[Providing Accessible Names and Descriptions | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/)
|
|
65
|
+
|
|
66
|
+
## `<AccessibleHide>` Component
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
<AccessibleHide>
|
|
70
|
+
This text is hidden using CSS and still available to screen readers.
|
|
71
|
+
</AccessibleHide>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## `<AriaLiveRegion>` Component
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
/**
|
|
78
|
+
* This component includes:
|
|
79
|
+
* aria-atomic="true"
|
|
80
|
+
* aria-live="polite"
|
|
81
|
+
* role="status"
|
|
82
|
+
*/
|
|
83
|
+
<AriaLiveRegion>
|
|
84
|
+
When this text is updated, screen readers will announce it automatically in live time.
|
|
85
|
+
</AriaLiveRegion>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Check out our [Aria Live Region Examples](?path=/docs/guides-accessibility-aria-live-regions--docs)
|
|
89
|
+
for more detailed information about this topic.
|
|
90
|
+
|
|
91
|
+
Sometimes, things change on a webpage without the whole page reloading. Think of a live sports score
|
|
92
|
+
that updates every few seconds or a search result that appears as you type. For users of screen
|
|
93
|
+
readers, these changes can be missed because the screen reader doesn't know to look for them. This
|
|
94
|
+
is where **ARIA live regions** come in. An ARIA live region is a special area on a webpage that
|
|
95
|
+
tells a screen reader to pay close attention to it. When the content in this area changes, the
|
|
96
|
+
screen reader automatically announces the update to the user. This ensures that everyone, including
|
|
97
|
+
those using assistive technology, is kept aware of important, real-time changes on the page.
|
|
98
|
+
|
|
99
|
+
## `useUniqueId()` Hook
|
|
100
|
+
|
|
101
|
+
This handy utility function is useful anytime a unique ID is needed for assigning labels,
|
|
102
|
+
descriptions, or for anything else in the web application.
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
/**
|
|
106
|
+
* This example demonstrates using 'aria-labelledby' on the table container
|
|
107
|
+
* instead of using HTML <caption> to assign a name for the table.
|
|
108
|
+
*/
|
|
109
|
+
const tableHeadingId = useUniqueId();
|
|
110
|
+
...
|
|
111
|
+
<Heading id={tableHeadingId}> Pizza Toppings </Heading>
|
|
112
|
+
...
|
|
113
|
+
<Table aria-labelledby={tableHeadingId}>
|
|
114
|
+
/* table rows */
|
|
115
|
+
</Table>
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
[Components > Containers > Table > Basic With Heading](?path=/story/components-containers-table--basic-with-heading)
|
|
121
|
+
|
|
122
|
+
## `px2rem()` Function
|
|
123
|
+
|
|
124
|
+
This is another handy utility function that will convert pixel units into relative units. While
|
|
125
|
+
using the [Canvas Token System](?path=/docs/guides-tokens-migration-overview--docs) is **strongly
|
|
126
|
+
recommended** first, this is a nice tool for using relative units if a space token isn't feasible.
|
|
127
|
+
|
|
128
|
+
Further reading: [Canvas Kit Styling Utilities](?path=/docs/styling-utilities--docs)
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
/**
|
|
132
|
+
* This example demonstrates the main content region
|
|
133
|
+
* of the grid to have a height of 800px.
|
|
134
|
+
*/
|
|
135
|
+
const gridLayoutStyles = createStyles({
|
|
136
|
+
...
|
|
137
|
+
gridTemplateRows: `auto ${px2rem(800)} auto`,
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
[Guides > Accessibility > Page Structure](?path=/docs/guides-accessibility-page-structure--docs)
|
|
143
|
+
|
|
144
|
+
## Responsiveness and Reflow
|
|
145
|
+
|
|
146
|
+
**WCAG v2.2 success criterion 1.4.10 Reflow states:**
|
|
147
|
+
|
|
148
|
+
> _“Content can be presented without loss of information or functionality, and without requiring
|
|
149
|
+
> scrolling in two dimensions for vertical scrolling content at a width equivalent to 320 CSS pixels
|
|
150
|
+
> and horizontal scrolling content at a height equivalent to 256 CSS pixels. ”_
|
|
151
|
+
|
|
152
|
+
Of course, there are exceptions to this guideline, including tables that do not apply. (Source:
|
|
153
|
+
[Understanding Success Criterion 1.4.10 Reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html))
|
|
154
|
+
In general, we have 2 key recommendations for satisfying this guideline:
|
|
155
|
+
|
|
156
|
+
1. Do not specify a minimum width greater than `320px` to avoid unnecessary horizontal scroll.
|
|
157
|
+
2. Do not use any sticky headers or footers at the smallest responsive breakpoints.
|
|
158
|
+
|
|
159
|
+
### How we test against this guideline:
|
|
160
|
+
|
|
161
|
+
Set the browser viewport to `1280px x 1024px` and increase browser zoom to 400%. This is
|
|
162
|
+
mathetmatically equivalent to a width of 320 pixels and a height of 256 pixels required by the
|
|
163
|
+
guideline.
|
|
164
|
+
|
|
165
|
+
- Evaluate whether any horizontal scroll isn't necessary in the application.
|
|
166
|
+
- Evaluate whether there is any loss of function due to sticky content.
|
|
167
|
+
- Look for clipping, overlapping, or otherwise unreadable text.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
|
|
2
|
+
import WithFormFields from './examples/Table/WithFormFields';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## Table with form field components
|
|
6
|
+
|
|
7
|
+
- Using `aria-labelledby` id references on the form field inputs to the column header name
|
|
8
|
+
- Testing form fields as table row headers
|
|
9
|
+
|
|
10
|
+
<ExampleCodeBlock code={WithFormFields} />
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
|
|
2
|
+
import LandmarkRegaions from './examples/PageStructure/LandmarkRegions';
|
|
3
|
+
import FullPageDemo from './examples/PageStructure/FullPageDemo';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Making Webpages Easy to Use for Everyone
|
|
7
|
+
|
|
8
|
+
Making a webpage easy to understand is important for everyone, especially for people with
|
|
9
|
+
disabilities. We do this by giving the page a clear and meaningful structure. This guide explains
|
|
10
|
+
how to use landmark regions, headings, lists, and tables to organize a page.
|
|
11
|
+
|
|
12
|
+
### Organizing Your Page with Landmark Regions
|
|
13
|
+
|
|
14
|
+
Imagine a webpage is like a house. It has different rooms for different purposes; a kitchen, a
|
|
15
|
+
bedroom, a living room, and so on. A good webpage is set up the same way. It has different sections,
|
|
16
|
+
like a header at the top, a main content area, and a footer at the bottom.
|
|
17
|
+
|
|
18
|
+
These sections are called landmark regions. They act like signs that tell a screen reader user where
|
|
19
|
+
they are on the page.
|
|
20
|
+
|
|
21
|
+
A screen reader user can quickly jump to a specific section, like the main content, without having
|
|
22
|
+
to listen to the whole page.
|
|
23
|
+
|
|
24
|
+
The most common landmark regions are:
|
|
25
|
+
|
|
26
|
+
- `<header>`: The top of the page.
|
|
27
|
+
- `<nav>`: The main navigation menu.
|
|
28
|
+
- `<main>`: The most important content on the page.
|
|
29
|
+
- `<footer>`: The bottom of the page.
|
|
30
|
+
|
|
31
|
+
All the content on the page should be inside one of these landmark regions. If you have two
|
|
32
|
+
navigation sections, make sure to give them different names so a screen reader can tell them apart.
|
|
33
|
+
For example, a global navigation region should be distinguishable from a bread crumb navigation
|
|
34
|
+
region.
|
|
35
|
+
|
|
36
|
+
<ExampleCodeBlock code={LandmarkRegaions} />
|
|
37
|
+
|
|
38
|
+
### Using Headings to Outline Your Content
|
|
39
|
+
|
|
40
|
+
Headings are like the chapters and subheadings in a book. They create a clear outline for the page.
|
|
41
|
+
Just like you can scan a book's table of contents to see what it's about, a screen reader user can
|
|
42
|
+
get a list of all the headings on a page to understand its structure.
|
|
43
|
+
|
|
44
|
+
- Start your page's main content with a single `<h1>` heading. This is the most important title on
|
|
45
|
+
the page.
|
|
46
|
+
- Use other headings (`<h2>`, `<h3>`, etc.) to create a clear order. Don't skip levels if possible.
|
|
47
|
+
For example, don't jump straight from an `<h1>` to an `<h4>` heading unless the content design
|
|
48
|
+
hierarchy leaves no other options.
|
|
49
|
+
- The heading levels should match how important the text looks on the page. The biggest, boldest
|
|
50
|
+
titles should be `<h1>`, and so on.
|
|
51
|
+
|
|
52
|
+
## Full Page Demo
|
|
53
|
+
|
|
54
|
+
Further reading:
|
|
55
|
+
[Examples > Page Header](?path=/docs/guides-accessibility-examples-page-header--docs) and
|
|
56
|
+
[Examples > Side Panel Navigation](?path=/docs/guides-accessibility-examples-side-panel-navigation--docs)
|
|
57
|
+
|
|
58
|
+
<ExampleCodeBlock code={FullPageDemo} />
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
|
|
2
2
|
import WithNavigation from './examples/SidePanelWithNavigation';
|
|
3
|
-
import WithOverlay from './examples/SidePanelWithOverlay';
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
## Side Panel As Navigation
|
|
@@ -22,8 +21,4 @@ wide range of support for accessibility.
|
|
|
22
21
|
- In the compact view, the `<Tooltip>` component is used to provide an accessible name to the icon
|
|
23
22
|
button menu targets
|
|
24
23
|
|
|
25
|
-
<ExampleCodeBlock code={WithNavigation} />
|
|
26
|
-
|
|
27
|
-
## Side Panel With Overlay
|
|
28
|
-
|
|
29
|
-
<ExampleCodeBlock code={WithOverlay} />
|
|
24
|
+
<ExampleCodeBlock code={WithNavigation} />
|
|
@@ -8,6 +8,17 @@ import FilterableColumnHeaders from './examples/Table/WithColumnHeaderFilters';
|
|
|
8
8
|
|
|
9
9
|
## Advanced Table Examples
|
|
10
10
|
|
|
11
|
+
Tables should only be used to organize data that has a clear relationship between rows and columns,
|
|
12
|
+
like a calendar or a schedule. Never use a table just for page layout.
|
|
13
|
+
|
|
14
|
+
When you use the proper HTML table markup, a screen reader can help a user navigate the table. It
|
|
15
|
+
will automatically read the column and row headers as they move through the data, so they always
|
|
16
|
+
know what information they're looking at.
|
|
17
|
+
|
|
18
|
+
- All tables should have a clear header and a descriptive title.
|
|
19
|
+
- Keep your tables simple. If a table is too complex, it might be better to break it up into several
|
|
20
|
+
smaller tables or use a different format.
|
|
21
|
+
|
|
11
22
|
Out of the box, `Table` is a lightweight compound component with a high degree of flexibility, but
|
|
12
23
|
not much functionality outside of providing a basic table layout. This flexibility lets developers
|
|
13
24
|
implement common features, such as selecting rows and sorting columns, on top of `Table` to meet
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {Flex} from '@workday/canvas-kit-react/layout';
|
|
2
|
+
import {px2rem} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
import iconBefore from './assets/icons-before-whcm.png';
|
|
5
|
+
import iconAfter from './assets/icons-after-whcm.png';
|
|
6
|
+
import checkMark from './assets/checkmarks.png';
|
|
7
|
+
import checkMarkWhcm from './assets/checkmarks-whcm.png';
|
|
8
|
+
import borderOutline from './assets/border-outline-dialog-tooltip-3.png';
|
|
9
|
+
import buttonFocus from './assets/button-focus-2.png';
|
|
10
|
+
import menuFocus from './assets/menu-focus.png';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Supporting Windows 11 High Contrast Desktop Themes
|
|
14
|
+
|
|
15
|
+
High-contrast themes in Windows 11 are crucial for accessibility. High contrast themes overwrite CSS
|
|
16
|
+
colors including `color`, `backgroundColor`, and `boxShadow`, while `border` and `outline`
|
|
17
|
+
properties retain their settings. To ensure your UI is compatible, follow these best practices for
|
|
18
|
+
improved visibility.
|
|
19
|
+
|
|
20
|
+
Further reading:
|
|
21
|
+
[Change color contrast in Windows](https://support.microsoft.com/en-us/windows/change-color-contrast-in-windows-fedc744c-90ac-69df-aed5-c8a90125e696)
|
|
22
|
+
|
|
23
|
+
### Focus Indicators:
|
|
24
|
+
|
|
25
|
+
Since Canvas Kit components rely on `boxShadow` for the keyboard focus state, it won’t be visible in
|
|
26
|
+
high contrast themes. We’ve added a `2px solid transparent` CSS `outline` to ensure a focus
|
|
27
|
+
indicator remains visible. Use `outlineOffset` to add space between the element and the outline for
|
|
28
|
+
aesthetics. We’ve used a `2px` offset on components like
|
|
29
|
+
[BaseButton](https://github.com/Workday/canvas-kit/blob/master/modules/react/button/lib/BaseButton.tsx)
|
|
30
|
+
to match the visual design of the `boxShadow` in the system. A `-2px` negative offset is used for
|
|
31
|
+
focusable components inside popup containers like the `<Menu>` component to ensure the focus
|
|
32
|
+
indicator isn’t clipped off the edge. (For example:
|
|
33
|
+
[MenuItem](https://github.com/Workday/canvas-kit/blob/master/modules/react/menu/lib/MenuItem.tsx).)
|
|
34
|
+
|
|
35
|
+
<Flex justifyContent="space-evenly" paddingBottom={system.space.x4}>
|
|
36
|
+
<img src={buttonFocus} alt="Primary button with outline offset 2 pixels" />
|
|
37
|
+
<img src={menuFocus} alt="Menu item with outline offset -2 pixels" />
|
|
38
|
+
</Flex>
|
|
39
|
+
|
|
40
|
+
### Boundary Borders and Outlines:
|
|
41
|
+
|
|
42
|
+
If content needs to be grouped with a boundary in high contrast themes, using a `transparent` CSS
|
|
43
|
+
`outline` can be useful because it won’t cause alignment problems on the page. We’ve done this to
|
|
44
|
+
draw boundaries in components that don't have any focus state like
|
|
45
|
+
[ModalCard](https://github.com/Workday/canvas-kit/blob/master/modules/react/modal/lib/ModalCard.tsx)
|
|
46
|
+
and
|
|
47
|
+
[TooltipContainer](https://github.com/Workday/canvas-kit/blob/master/modules/react/tooltip/lib/TooltipContainer.tsx).
|
|
48
|
+
|
|
49
|
+
<Flex justifyContent="center">
|
|
50
|
+
<figure margin="0">
|
|
51
|
+
<img src={borderOutline} alt="" />
|
|
52
|
+
<figcaption style={{width: px2rem(300)}}>
|
|
53
|
+
CSS outlines appear in high contrast mode around dialog containers and tooltips
|
|
54
|
+
</figcaption>
|
|
55
|
+
</figure>
|
|
56
|
+
</Flex>
|
|
57
|
+
|
|
58
|
+
### Images:
|
|
59
|
+
|
|
60
|
+
`<img>` elements, which are for images like JPEGs or PNGs, are not affected by high contrast themes.
|
|
61
|
+
If you use a meaningful image with a transparent background, it could become difficult to see
|
|
62
|
+
against some background colors. Be careful when using such images for conveying information to
|
|
63
|
+
users.
|
|
64
|
+
|
|
65
|
+
<Flex justifyContent="space-evenly" paddingBottom={system.space.x4}>
|
|
66
|
+
<img src={checkMark} alt="Check mark images highly visible on white background" />
|
|
67
|
+
<img src={checkMarkWhcm} alt="Check mark images have poor contrast on dark background" />
|
|
68
|
+
</Flex>
|
|
69
|
+
|
|
70
|
+
### SVG Icons
|
|
71
|
+
|
|
72
|
+
The colors inside `<svg>` elements usually don't change with high contrast themes, which can make
|
|
73
|
+
them hard to see on some backgrounds. We’ve used a media query to set the icon `fill` and `color`
|
|
74
|
+
properties to `currentColor` ensuring the icon uses the correct color from the user's preferred high
|
|
75
|
+
contrast theme.
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
// for Windows high contrast desktop themes
|
|
79
|
+
'@media (prefers-contrast: more)': {
|
|
80
|
+
'.wd-icon-fill, .wd-icon-accent': {
|
|
81
|
+
color: 'currentColor',
|
|
82
|
+
fill: 'currentColor',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<Flex justifyContent='space-evenly'>
|
|
88
|
+
<figure margin='0'>
|
|
89
|
+
<img src={iconBefore} alt="" />
|
|
90
|
+
<figcaption style={{width: px2rem(370)}}>Before: The mail icon color has poor contrast on dark backgrounds</figcaption>
|
|
91
|
+
</figure>
|
|
92
|
+
|
|
93
|
+
<figure margin='0'>
|
|
94
|
+
<img src={iconAfter} alt="" />
|
|
95
|
+
<figcaption style={{width: px2rem(370)}}>After: The mail icon inherits the theme's current color for best contrast</figcaption>
|
|
96
|
+
</figure>
|
|
97
|
+
</Flex>
|
|
@@ -1,69 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
fontWeight: type.properties.fontWeights.bold,
|
|
1
|
+
import {Grid} from '@workday/canvas-kit-react/layout';
|
|
2
|
+
import {Heading} from '@workday/canvas-kit-react/text';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
|
|
5
|
+
|
|
6
|
+
const containerStyles = createStyles({
|
|
7
|
+
gridTemplateAreas:
|
|
8
|
+
"'Header Header Header Header' 'SideBar BodyContent BodyContent BodyContent' 'Footer Footer Footer Footer'",
|
|
9
|
+
gridGap: system.space.x4,
|
|
10
|
+
gridTemplateColumns: '3fr 9fr',
|
|
11
|
+
gridTemplateRows: `auto ${px2rem(300)} auto`,
|
|
13
12
|
});
|
|
14
13
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<Grid as="header" gridArea="Header" depth={1} {...props} {...borderPadProps}>
|
|
22
|
-
{children}
|
|
23
|
-
</Grid>
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const BodyContent = ({children, ...props}: GridProps) => (
|
|
27
|
-
<Grid as="main" gridArea="BodyContent" depth={1} {...props} {...borderPadProps}>
|
|
28
|
-
{children}
|
|
29
|
-
</Grid>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const SideBar = ({children, ...props}: GridProps) => (
|
|
33
|
-
<Grid as="aside" gridArea="SideBar" depth={1} {...props} {...borderPadProps}>
|
|
34
|
-
{children}
|
|
35
|
-
</Grid>
|
|
36
|
-
);
|
|
14
|
+
const gridStyles = createStyles({
|
|
15
|
+
backgroundColor: system.color.bg.primary.default,
|
|
16
|
+
borderRadius: system.shape.x1,
|
|
17
|
+
boxShadow: system.depth[1],
|
|
18
|
+
padding: system.space.x4,
|
|
19
|
+
});
|
|
37
20
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
);
|
|
21
|
+
const headingStyles = createStyles({
|
|
22
|
+
margin: system.space.zero,
|
|
23
|
+
...system.type.heading.small,
|
|
24
|
+
});
|
|
43
25
|
|
|
44
26
|
export default () => {
|
|
45
|
-
const parentCont = {
|
|
46
|
-
gridTemplateAreas:
|
|
47
|
-
"'Header Header Header Header' 'SideBar BodyContent BodyContent BodyContent' 'Footer Footer Footer Footer'",
|
|
48
|
-
gridGap: 's',
|
|
49
|
-
gridTemplateColumns: '3fr 9fr',
|
|
50
|
-
gridTemplateRows: 'auto 300px auto',
|
|
51
|
-
};
|
|
52
27
|
return (
|
|
53
|
-
<Grid
|
|
54
|
-
<Grid {
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
</
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
28
|
+
<Grid cs={containerStyles}>
|
|
29
|
+
<Grid as="header" gridArea="Header" cs={gridStyles}>
|
|
30
|
+
<Heading variant="inverse" size="small" cs={headingStyles}>
|
|
31
|
+
Page Header
|
|
32
|
+
</Heading>
|
|
33
|
+
</Grid>
|
|
34
|
+
<Grid as="nav" gridArea="SideBar" cs={gridStyles}>
|
|
35
|
+
<Heading variant="inverse" size="small" cs={headingStyles}>
|
|
36
|
+
Navigation
|
|
37
|
+
</Heading>
|
|
38
|
+
</Grid>
|
|
39
|
+
<Grid as="main" gridArea="BodyContent" cs={gridStyles}>
|
|
40
|
+
<Heading variant="inverse" size="small" cs={headingStyles}>
|
|
41
|
+
Main Content
|
|
42
|
+
</Heading>
|
|
43
|
+
</Grid>
|
|
44
|
+
<Grid as="footer" gridArea="Footer" cs={gridStyles}>
|
|
45
|
+
<Heading variant="inverse" size="small" cs={headingStyles}>
|
|
46
|
+
Page Footer
|
|
47
|
+
</Heading>
|
|
67
48
|
</Grid>
|
|
68
49
|
</Grid>
|
|
69
50
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.2",
|
|
4
4
|
"description": "Documentation components of Canvas Kit components",
|
|
5
5
|
"author": "Workday, Inc. (https://www.workday.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"@emotion/styled": "^11.6.0",
|
|
46
46
|
"@stackblitz/sdk": "^1.11.0",
|
|
47
47
|
"@storybook/csf": "0.0.1",
|
|
48
|
-
"@workday/canvas-kit-labs-react": "^14.0.
|
|
49
|
-
"@workday/canvas-kit-preview-react": "^14.0.
|
|
50
|
-
"@workday/canvas-kit-react": "^14.0.
|
|
51
|
-
"@workday/canvas-kit-styling": "^14.0.
|
|
48
|
+
"@workday/canvas-kit-labs-react": "^14.0.2",
|
|
49
|
+
"@workday/canvas-kit-preview-react": "^14.0.2",
|
|
50
|
+
"@workday/canvas-kit-react": "^14.0.2",
|
|
51
|
+
"@workday/canvas-kit-styling": "^14.0.2",
|
|
52
52
|
"@workday/canvas-system-icons-web": "^3.0.36",
|
|
53
53
|
"@workday/canvas-tokens-web": "^3.0.0",
|
|
54
54
|
"markdown-to-jsx": "^7.2.0",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"mkdirp": "^1.0.3",
|
|
62
62
|
"typescript": "5.0"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "c57ff7b71c46b677f04e665ddf925cd40e036a5d"
|
|
65
65
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
## Accessibility Overview Coming Soon!
|
|
2
|
-
|
|
3
|
-
Canvas Kit is built with accessibility in mind. We continuously strive to provide a robust set of
|
|
4
|
-
accessible components that are easy to customize for your specific needs.
|
|
5
|
-
|
|
6
|
-
## What you can expect
|
|
7
|
-
|
|
8
|
-
- Introduction to the accessibility tree
|
|
9
|
-
- Introduction to the accessible name and description calculation
|
|
10
|
-
- Supporting Windows 11 high contrast desktop themes
|
|
11
|
-
- Responsiveness and reflow
|
|
12
|
-
- Introduction to ARIA live regions
|
|
13
|
-
|
|
14
|
-
### Bigger and better examples
|
|
15
|
-
|
|
16
|
-
- Page layouts with landmark regions and structured content headings
|
|
17
|
-
- Cards, clickable cards, and lists of cards
|
|
18
|
-
- Forms and error handling
|