@workday/canvas-kit-docs 14.0.0-alpha.1185-next.0 → 14.0.0-alpha.1190-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/react/_examples/mdx/AccessibilityOverview.mdx +18 -0
- package/dist/mdx/react/_examples/mdx/AriaLiveRegions.mdx +3 -3
- package/dist/mdx/react/_examples/mdx/Headers.mdx +9 -14
- package/dist/mdx/react/_examples/mdx/SidePanel.mdx +0 -2
- package/dist/mdx/react/_examples/mdx/TablesAdvanced.mdx +68 -37
- package/dist/mdx/react/_examples/mdx/examples/Table/WithColumnHeaderFilters.tsx +202 -0
- package/dist/mdx/react/_examples/mdx/examples/Table/WithSelectableRows.tsx +2 -2
- package/dist/mdx/react/_examples/mdx/examples/Table/WithSortableColumnHeaders.tsx +2 -2
- package/dist/mdx/react/button/button/Button.mdx +14 -1
- package/dist/mdx/tokens/TokenMigrationCodemod.mdx +3 -3
- 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": "13.2.
|
|
22
|
-
"@workday/canvas-kit-preview-react": "13.2.
|
|
23
|
-
"@workday/canvas-kit-react": "13.2.
|
|
24
|
-
"@workday/canvas-kit-react-fonts": "^13.2.
|
|
25
|
-
"@workday/canvas-kit-styling": "13.2.
|
|
21
|
+
"@workday/canvas-kit-labs-react": "13.2.12",
|
|
22
|
+
"@workday/canvas-kit-preview-react": "13.2.12",
|
|
23
|
+
"@workday/canvas-kit-react": "13.2.12",
|
|
24
|
+
"@workday/canvas-kit-react-fonts": "^13.2.12",
|
|
25
|
+
"@workday/canvas-kit-styling": "13.2.12",
|
|
26
26
|
"@workday/canvas-system-icons-web": "3.0.22",
|
|
27
27
|
"@workday/canvas-tokens-web": "2.0.0"
|
|
28
28
|
},
|
|
@@ -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": "13.2.
|
|
22
|
-
"@workday/canvas-kit-preview-react": "13.2.
|
|
23
|
-
"@workday/canvas-kit-react": "13.2.
|
|
24
|
-
"@workday/canvas-kit-react-fonts": "^13.2.
|
|
25
|
-
"@workday/canvas-kit-styling": "13.2.
|
|
21
|
+
"@workday/canvas-kit-labs-react": "13.2.12",
|
|
22
|
+
"@workday/canvas-kit-preview-react": "13.2.12",
|
|
23
|
+
"@workday/canvas-kit-react": "13.2.12",
|
|
24
|
+
"@workday/canvas-kit-react-fonts": "^13.2.12",
|
|
25
|
+
"@workday/canvas-kit-styling": "13.2.12",
|
|
26
26
|
"@workday/canvas-system-icons-web": "3.0.22",
|
|
27
27
|
"@workday/canvas-tokens-web": "2.0.0"
|
|
28
28
|
},
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
|
@@ -72,9 +72,9 @@ of error conditions. As forms increase in complexity, live regions on each error
|
|
|
72
72
|
increasingly distracting and disruptive to the experience, especially if users are trying to first
|
|
73
73
|
understand the information that is required of them to complete the task.
|
|
74
74
|
|
|
75
|
-
**Note:** The `<AriaLiveRegion>` component is used inside of the `Hint` to ensure the live
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
**Note:** The `<AriaLiveRegion>` component is used inside of the `Hint` to ensure the live region
|
|
76
|
+
remains in the browser DOM at all times. The `Hint` is only rendered in the DOM when it contains
|
|
77
|
+
content, so it will not work reliably as a live region for screen readers using the
|
|
78
78
|
`as={AriaLiveRegion}` prop.
|
|
79
79
|
|
|
80
80
|
<ExampleCodeBlock code={TextInputWithLiveError} />
|
|
@@ -4,23 +4,22 @@ import {Basic as PageHeaderBasic} from './examples/PageHeader';
|
|
|
4
4
|
import {Basic as GlobalHeaderBasic} from './examples/GlobalHeader';
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
# Canvas Kit Examples
|
|
8
|
-
|
|
9
7
|
## Global Header
|
|
10
8
|
|
|
11
9
|
Developers building internal Workday applications will likely not need to create this component.
|
|
12
10
|
However, if you're building components to be used outside of Workday, this is a helpful reference
|
|
13
11
|
for building a global navigation header that looks like our internal `GlobalHeader`.
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
### Tooltip usage
|
|
16
14
|
|
|
17
|
-
- The `default` variant Tooltip is used on all of the icon buttons, which will automatically set
|
|
18
|
-
|
|
19
|
-
- The `describe` variant Tooltip is used instead on the "MENU" button because this is a text
|
|
20
|
-
|
|
21
|
-
ensure that the visible button text "MENU" is not
|
|
15
|
+
- The `default` variant `<Tooltip>` is used on all of the icon buttons, which will automatically set
|
|
16
|
+
the `aria-label` of the child component to the `title` prop string.
|
|
17
|
+
- The `describe` variant `<Tooltip>` is used instead on the "MENU" button because this is a text
|
|
18
|
+
button. This variant will instead set `aria-describedby` to the child component referencing the
|
|
19
|
+
the tooltip's text "Global Navigation" to ensure that the visible button text "MENU" is not
|
|
20
|
+
overriden by an `aria-label`.
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
### Count badge usage
|
|
24
23
|
|
|
25
24
|
When `<CountBadge>` is used as a sibling component for button, the `aria-describedby` property is
|
|
26
25
|
set on the button referencing the `id` value of the `<CountBadge>`. This practice helps support
|
|
@@ -38,8 +37,4 @@ enhancements to support live, real-time announcements for screen readers:
|
|
|
38
37
|
- When the `<CountBadge>` is updated, then screen readers can automatically describe (in real-time)
|
|
39
38
|
the name of the live region, "Notifications" and the text updated inside of it, "1 new".
|
|
40
39
|
|
|
41
|
-
<ExampleCodeBlock code={GlobalHeaderBasic} />
|
|
42
|
-
|
|
43
|
-
## Page Header
|
|
44
|
-
|
|
45
|
-
<ExampleCodeBlock code={PageHeaderBasic} />
|
|
40
|
+
<ExampleCodeBlock code={GlobalHeaderBasic} />
|
|
@@ -3,8 +3,6 @@ import WithNavigation from './examples/SidePanelWithNavigation';
|
|
|
3
3
|
import WithOverlay from './examples/SidePanelWithOverlay';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
# Canvas Kit Examples
|
|
7
|
-
|
|
8
6
|
## Side Panel As Navigation
|
|
9
7
|
|
|
10
8
|
This example demonstrates SidePanel as a navigation system that can be reduced into a "compact view"
|
|
@@ -3,17 +3,19 @@ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
|
|
|
3
3
|
import SelectableRows from './examples/Table/WithSelectableRows';
|
|
4
4
|
import ExpandableRows from './examples/Table/WithExpandableRows';
|
|
5
5
|
import SortableColumnHeaders from './examples/Table/WithSortableColumnHeaders';
|
|
6
|
+
import FilterableColumnHeaders from './examples/Table/WithColumnHeaderFilters';
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
## Advanced Table Examples
|
|
9
10
|
|
|
10
|
-
Out of the box, `Table` is a lightweight component with a high degree of flexibility, but
|
|
11
|
-
functionality outside of providing a basic table layout. This
|
|
11
|
+
Out of the box, `Table` is a lightweight compound component with a high degree of flexibility, but
|
|
12
|
+
not much functionality outside of providing a basic table layout. This flexibility lets developers
|
|
12
13
|
implement common features, such as selecting rows and sorting columns, on top of `Table` to meet
|
|
13
|
-
their specific application needs.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
their specific application needs.
|
|
15
|
+
|
|
16
|
+
The Workday Accessibility Team has researched and developed the following examples below to
|
|
17
|
+
demonstrate how to build these accessible table patterns. We've listed the specific considerations
|
|
18
|
+
and decisions we've made for each of the examples.
|
|
17
19
|
|
|
18
20
|
### Expandable Rows
|
|
19
21
|
|
|
@@ -21,32 +23,32 @@ Expandable Rows combines the likes of an accordion with tabular data tables. Col
|
|
|
21
23
|
buttons with 2 states, a collapsed and expanded state. A new row that spans the entire width of the
|
|
22
24
|
table is added to the table just after the expanded row.
|
|
23
25
|
|
|
24
|
-
- The `aria-expanded` property is added to the button to communicate this state to screen
|
|
25
|
-
users.
|
|
26
|
+
- The `aria-expanded` property is added to the chevron button to communicate this state to screen
|
|
27
|
+
reader users.
|
|
26
28
|
- A Canvas accessible `Tooltip` component is used to assign names to each icon button based on the
|
|
27
|
-
most useful value in the row. In this example, we combined the car make and model
|
|
28
|
-
allows everyone to view the name of the
|
|
29
|
-
keyboard.
|
|
29
|
+
most useful value in the row. In this example, we combined the car make (in column 1) and model
|
|
30
|
+
(in column 2) together. This allows everyone to view the name of the icon buttons by hovering the
|
|
31
|
+
mouse or focusing with the keyboard.
|
|
30
32
|
- The expanded row uses `colspan` to span the entire width of the table and support screen readers.
|
|
31
33
|
This space provides flexibility to show headings, lists, and other structured content for the
|
|
32
34
|
table row above.
|
|
33
|
-
- There is no explicit relationship between a row of cells
|
|
35
|
+
- There is no explicit relationship between a row of cells and the spanned content below it. The
|
|
34
36
|
spanned content is assumed to belong to the row of cells above it, based on established accordion
|
|
35
37
|
patterns and logical reading order of content rendered to the screen.
|
|
36
|
-
- Outlining hierarchy in
|
|
38
|
+
- Outlining hierarchy with additional nested rows in the table is not supported for screen readers
|
|
39
|
+
in this example.
|
|
37
40
|
|
|
38
41
|
<ExampleCodeBlock code={ExpandableRows} />
|
|
39
42
|
|
|
40
43
|
### Selectable Rows
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Here is what we did about it:
|
|
45
|
+
Using a `Checkbox` labeled "Select All" inside of a column header can be a confusing experience for
|
|
46
|
+
screen reader users. Screen readers will automatically announce the "Select All" label in the column
|
|
47
|
+
header each time users are reading any of the Check boxes in the first column. For instance, the
|
|
48
|
+
`Checkbox` in row 4 is definitely not going to select all of the rows. Here is what we did about it:
|
|
47
49
|
|
|
48
50
|
- We intentionally rendered row 1, column 1 as a standard `<td>` element so screen readers won't
|
|
49
|
-
automatically announce "Select All" while reading cells in column 1.
|
|
51
|
+
automatically announce the "Select All" label while reading cells in column 1.
|
|
50
52
|
- Our research found that VoiceOver (MacOS v12.7, Safari v17.1) persistently announce "Select All"
|
|
51
53
|
despite using the `<td>` element because of the optional `<thead>` element in the table. We
|
|
52
54
|
omitted the optional `<thead>` and `<tbody>` elements from this example for that reason.
|
|
@@ -60,25 +62,54 @@ Here is what we did about it:
|
|
|
60
62
|
|
|
61
63
|
<ExampleCodeBlock code={SelectableRows} />
|
|
62
64
|
|
|
65
|
+
### Filterable Column Headers
|
|
66
|
+
|
|
67
|
+
In this example, we demonstrate using the `Popup` component in each column header allowing users to
|
|
68
|
+
search and filter the data on the table. The `Popup` component relies on React Portals to render the
|
|
69
|
+
popup elements at the bottom of the browser's DOM presenting 2 key challenges for accessibility:
|
|
70
|
+
|
|
71
|
+
1. Keyboard focus order of the elements in the popup,
|
|
72
|
+
2. Screen readers' reading order of the content rendered in the browser.
|
|
73
|
+
|
|
74
|
+
Here's what we did about it:
|
|
75
|
+
|
|
76
|
+
- Canvas Kit includes a `usePopupModel` hook, with quite a few additional hooks developers can add
|
|
77
|
+
to their models. In particular, the `useFocusRedirect` hook manages keyboard focus between the
|
|
78
|
+
`<Popup.Target>` button and the popup content.
|
|
79
|
+
- The `useInitialFocus` hook allows developers to specify which element receives keyboard focus when
|
|
80
|
+
the popup appears. In this example, we auto-focused the search input field.
|
|
81
|
+
- To address the reading order of content, we set the `aria-owns` property onto the parent
|
|
82
|
+
`<Table.Header>` component (`<th>` DOM element) with 2 unique `id` values. The first `id` refers
|
|
83
|
+
to the `<Popup.Target>` button and the second refers to the `<Popup.Card>` container element. This
|
|
84
|
+
manually reassigns the column header's `<Popup.Target>` button and the `Popup` contents as
|
|
85
|
+
siblings in the browser's accessibility tree hierarchy. Screen readers **should** read the column
|
|
86
|
+
header buttons and the popup content in sequential order even though they are not siblings in the
|
|
87
|
+
DOM.
|
|
88
|
+
- The `type='description'` variant of the Canvas `Tooltip` is used to communicate the filtered state
|
|
89
|
+
of the column header, and assigned to the accessible description of the column header
|
|
90
|
+
`<TertiaryButton>` component.
|
|
91
|
+
- The Canvas `AriaLiveRegion` component is used to render the "X of Y items" status inside the table
|
|
92
|
+
caption. This enables screen readers to automatically describe the filter state changes of the
|
|
93
|
+
table content to users in real time. We recommend validating whether this use of a live region is
|
|
94
|
+
well supported for your screen reader and browser combinations first.
|
|
95
|
+
|
|
96
|
+
<ExampleCodeBlock code={FilterableColumnHeaders} />
|
|
97
|
+
|
|
63
98
|
### Sortable Column Headers
|
|
64
99
|
|
|
65
|
-
The challenge in this example is
|
|
66
|
-
headers
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
the tabular data below.
|
|
80
|
-
- The `aria-sort` property may not reliably provide the current sort state of the column to users
|
|
81
|
-
focused on the tabular data in the table. It may be more reliable to use an `aria-label` string on
|
|
82
|
-
the button that describes the column name and sort state together.
|
|
100
|
+
The challenge in this example is to provide all of the necessary information about the interactive
|
|
101
|
+
column headers, the sort state of the column, and instructions about how the table will be sorted
|
|
102
|
+
without giving too much information to users while reading the data cells below.
|
|
103
|
+
|
|
104
|
+
- The `aria-sort` property has been added to each of the `<Table.Header>` components (`<th>` DOM
|
|
105
|
+
element) and updated to `ascending` or `descending` to reflect the current sort state. We
|
|
106
|
+
recommend validating whether this property is well supported for your screen reader and browser
|
|
107
|
+
combinations first.
|
|
108
|
+
- A `<TertiaryButton>` describing the column name is used inside of the `<Table.Header>` component.
|
|
109
|
+
- The `description` variant of the Canvas `Tooltip` component is applied to the button in the column
|
|
110
|
+
header and applied to the accessible description of the button with the `aria-description`
|
|
111
|
+
property. This is used to describe how the column will be sorted when pressed and screen readers
|
|
112
|
+
will only read this description while focusing on the column headers, not while reading the data
|
|
113
|
+
cells below.
|
|
83
114
|
|
|
84
115
|
<ExampleCodeBlock code={SortableColumnHeaders} />
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {AriaLiveRegion, createComponent, useUniqueId} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {Flex} from '@workday/canvas-kit-react/layout';
|
|
5
|
+
import {FormField} from '@workday/canvas-kit-react/form-field';
|
|
6
|
+
import {InputGroup, TextInput} from '@workday/canvas-kit-react/text-input';
|
|
7
|
+
import {
|
|
8
|
+
Popup,
|
|
9
|
+
usePopupModel,
|
|
10
|
+
useCloseOnOutsideClick,
|
|
11
|
+
useCloseOnEscape,
|
|
12
|
+
useInitialFocus,
|
|
13
|
+
useReturnFocus,
|
|
14
|
+
useFocusRedirect,
|
|
15
|
+
} from '@workday/canvas-kit-react/popup';
|
|
16
|
+
import {PrimaryButton, TertiaryButton} from '@workday/canvas-kit-react/button';
|
|
17
|
+
import {Table} from '@workday/canvas-kit-react/table';
|
|
18
|
+
import {Text} from '@workday/canvas-kit-react/text';
|
|
19
|
+
import {SystemIcon} from '@workday/canvas-kit-react/icon';
|
|
20
|
+
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
21
|
+
import {createStyles} from '@workday/canvas-kit-styling';
|
|
22
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
23
|
+
import {filterIcon, searchIcon} from '@workday/canvas-system-icons-web';
|
|
24
|
+
|
|
25
|
+
interface CountryData {
|
|
26
|
+
country: string;
|
|
27
|
+
capital: string;
|
|
28
|
+
population: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const countryData: CountryData[] = [
|
|
32
|
+
{country: 'Australia', capital: 'Canberra', population: 25690000},
|
|
33
|
+
{country: 'Bahamas', capital: 'Nassau', population: 407906},
|
|
34
|
+
{country: 'Canada', capital: 'Ottawa', population: 38250000},
|
|
35
|
+
{country: 'Fiji', capital: 'Suva', population: 924610},
|
|
36
|
+
{country: 'Ghana', capital: 'Accra', population: 32830000},
|
|
37
|
+
{country: 'Hong Kong', capital: 'City of Victoria', population: 7413000},
|
|
38
|
+
{country: 'India', capital: 'New Delhi', population: 1408000000},
|
|
39
|
+
{country: 'Ireland', capital: 'Dublin', population: 5033000},
|
|
40
|
+
{country: 'Jamaica', capital: 'Kingston', population: 2828000},
|
|
41
|
+
{country: 'Kenya', capital: 'Nairobi', population: 53010000},
|
|
42
|
+
{country: 'Micronesia', capital: 'Palikir', population: 113131},
|
|
43
|
+
{country: 'New Zealand', capital: 'Wellington', population: 5123000},
|
|
44
|
+
{country: 'Philippines', capital: 'Manila', population: 113900000},
|
|
45
|
+
{country: 'Puerto Rico', capital: 'San Juan', population: 3264000},
|
|
46
|
+
{country: 'Samoa', capital: 'Apia', population: 218764},
|
|
47
|
+
{country: 'Singapore', capital: 'Singapore', population: 5454000},
|
|
48
|
+
{country: 'Tanzania', capital: 'Dodoma', population: 63590000},
|
|
49
|
+
{country: 'United Kingdom', capital: 'London', population: 67330000},
|
|
50
|
+
{country: 'United States', capital: 'Washington, D.C.', population: 331900000},
|
|
51
|
+
{country: 'Zimbabwe', capital: 'Harare', population: 15990000},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const textStyles = createStyles({
|
|
55
|
+
paddingInlineStart: system.space.x3,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
interface FilterableColumnHeaderProps {
|
|
59
|
+
label: string;
|
|
60
|
+
onFilter: (filterObject: {filterText: string; column: string}) => void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const FilterableColumnHeader = createComponent('th')({
|
|
64
|
+
displayName: 'FilterableColumnHeader',
|
|
65
|
+
Component: ({label, onFilter}: FilterableColumnHeaderProps, ref) => {
|
|
66
|
+
const [inputVal, setInputVal] = React.useState('');
|
|
67
|
+
const targetId = useUniqueId();
|
|
68
|
+
const popupId = useUniqueId();
|
|
69
|
+
const initialFocusRef = React.useRef(null);
|
|
70
|
+
const filterPopupModel = usePopupModel({
|
|
71
|
+
initialFocusRef,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
useCloseOnOutsideClick(filterPopupModel);
|
|
75
|
+
useCloseOnEscape(filterPopupModel);
|
|
76
|
+
useInitialFocus(filterPopupModel);
|
|
77
|
+
useFocusRedirect(filterPopupModel);
|
|
78
|
+
useReturnFocus(filterPopupModel);
|
|
79
|
+
|
|
80
|
+
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
81
|
+
const newVal = e.target.value;
|
|
82
|
+
setInputVal(newVal);
|
|
83
|
+
onFilter({filterText: newVal, column: label.toLowerCase()});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Table.Header scope="col" aria-owns={targetId + ' ' + popupId}>
|
|
88
|
+
<Popup model={filterPopupModel}>
|
|
89
|
+
<Tooltip title={`Filter${inputVal !== '' ? `ed: "${inputVal}"` : ''}`} type="description">
|
|
90
|
+
<Popup.Target
|
|
91
|
+
as={TertiaryButton}
|
|
92
|
+
id={targetId}
|
|
93
|
+
icon={inputVal === '' ? searchIcon : filterIcon}
|
|
94
|
+
iconPosition="end"
|
|
95
|
+
>
|
|
96
|
+
{label}
|
|
97
|
+
</Popup.Target>
|
|
98
|
+
</Tooltip>
|
|
99
|
+
<Popup.Popper>
|
|
100
|
+
<Popup.Card id={popupId}>
|
|
101
|
+
<Popup.Heading>Filter</Popup.Heading>
|
|
102
|
+
<Popup.Body>
|
|
103
|
+
<FormField>
|
|
104
|
+
<FormField.Label>{label}</FormField.Label>
|
|
105
|
+
<FormField.Input as={InputGroup}>
|
|
106
|
+
<InputGroup.InnerStart>
|
|
107
|
+
<SystemIcon icon={searchIcon} />
|
|
108
|
+
</InputGroup.InnerStart>
|
|
109
|
+
<InputGroup.Input
|
|
110
|
+
as={TextInput}
|
|
111
|
+
type="search"
|
|
112
|
+
ref={initialFocusRef}
|
|
113
|
+
onChange={handleChange}
|
|
114
|
+
value={inputVal}
|
|
115
|
+
/>
|
|
116
|
+
</FormField.Input>
|
|
117
|
+
</FormField>
|
|
118
|
+
</Popup.Body>
|
|
119
|
+
<Flex>
|
|
120
|
+
<Popup.CloseButton as={PrimaryButton}>Done</Popup.CloseButton>
|
|
121
|
+
</Flex>
|
|
122
|
+
</Popup.Card>
|
|
123
|
+
</Popup.Popper>
|
|
124
|
+
</Popup>
|
|
125
|
+
</Table.Header>
|
|
126
|
+
);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
function filterTableData(data: CountryData[], filters: CountryData) {
|
|
131
|
+
return data.filter(item => {
|
|
132
|
+
for (const key in filters) {
|
|
133
|
+
if (filters.hasOwnProperty(key) && filters[key]) {
|
|
134
|
+
const filterText = filters[key].toLowerCase();
|
|
135
|
+
const itemValue = String(item[key]).toLowerCase();
|
|
136
|
+
if (!itemValue.includes(filterText)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export default () => {
|
|
146
|
+
const [filteredData, setFilteredData] = React.useState(countryData);
|
|
147
|
+
const [colFilters, setColFilters] = React.useState<CountryData>({
|
|
148
|
+
country: '',
|
|
149
|
+
capital: '',
|
|
150
|
+
population: '',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
React.useEffect(() => {
|
|
154
|
+
setFilteredData(filterTableData(countryData, colFilters));
|
|
155
|
+
}, [colFilters]);
|
|
156
|
+
|
|
157
|
+
let typingDelay: NodeJS.Timeout;
|
|
158
|
+
function handleColFilters({filterText, column}) {
|
|
159
|
+
clearTimeout(typingDelay);
|
|
160
|
+
typingDelay = setTimeout(() => {
|
|
161
|
+
setColFilters(prev => {
|
|
162
|
+
const newState = {...prev, [column]: filterText};
|
|
163
|
+
return newState;
|
|
164
|
+
});
|
|
165
|
+
}, 400);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<Table maxHeight="40rem">
|
|
170
|
+
<Table.Caption>
|
|
171
|
+
Population Listed by Country (2021)
|
|
172
|
+
<AriaLiveRegion cs={textStyles}>
|
|
173
|
+
{filteredData.length} of {countryData.length} items
|
|
174
|
+
</AriaLiveRegion>
|
|
175
|
+
</Table.Caption>
|
|
176
|
+
<Table.Head>
|
|
177
|
+
<Table.Row>
|
|
178
|
+
<FilterableColumnHeader label="Country" onFilter={handleColFilters} />
|
|
179
|
+
<FilterableColumnHeader label="Capital" onFilter={handleColFilters} />
|
|
180
|
+
<FilterableColumnHeader label="Population" onFilter={handleColFilters} />
|
|
181
|
+
</Table.Row>
|
|
182
|
+
</Table.Head>
|
|
183
|
+
<Table.Body>
|
|
184
|
+
{filteredData.map(item => {
|
|
185
|
+
return (
|
|
186
|
+
<Table.Row key={item.country}>
|
|
187
|
+
<Table.Header scope="row">
|
|
188
|
+
<Text cs={textStyles}>{item.country}</Text>
|
|
189
|
+
</Table.Header>
|
|
190
|
+
<Table.Cell>
|
|
191
|
+
<Text cs={textStyles}>{item.capital}</Text>
|
|
192
|
+
</Table.Cell>
|
|
193
|
+
<Table.Cell>
|
|
194
|
+
<Text cs={textStyles}>{item.population.toLocaleString()}</Text>
|
|
195
|
+
</Table.Cell>
|
|
196
|
+
</Table.Row>
|
|
197
|
+
);
|
|
198
|
+
})}
|
|
199
|
+
</Table.Body>
|
|
200
|
+
</Table>
|
|
201
|
+
);
|
|
202
|
+
};
|
|
@@ -45,9 +45,9 @@ const SelectableRow = createComponent('tr')({
|
|
|
45
45
|
<Checkbox checked={rowData.checked} onChange={onSelect} />
|
|
46
46
|
</Tooltip>
|
|
47
47
|
</Table.Cell>
|
|
48
|
-
<Table.
|
|
48
|
+
<Table.Header cs={tableCellStyles} scope="row">
|
|
49
49
|
{rowData.name}
|
|
50
|
-
</Table.
|
|
50
|
+
</Table.Header>
|
|
51
51
|
<Table.Cell cs={tableCellStyles}>{rowData.amount}</Table.Cell>
|
|
52
52
|
</Table.Row>
|
|
53
53
|
);
|
|
@@ -124,7 +124,7 @@ const getSortIcon = (sortOrder?: SortOrder) => {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
const SortableColumnHeader = createComponent('th')({
|
|
128
128
|
displayName: 'SortableColumnHeader',
|
|
129
129
|
Component: (
|
|
130
130
|
{label, sortOrder, onSortAction, children, ...elemProps}: SortableColumnHeaderProps,
|
|
@@ -132,7 +132,7 @@ export default createComponent('th')({
|
|
|
132
132
|
) => {
|
|
133
133
|
return (
|
|
134
134
|
<Table.Header ref={ref} scope="col" aria-sort={sortOrder} {...elemProps}>
|
|
135
|
-
<Tooltip type="
|
|
135
|
+
<Tooltip type="description" title={`Sort ${getNextSortOrder(sortOrder)}`}>
|
|
136
136
|
<TertiaryButton
|
|
137
137
|
icon={getSortIcon(sortOrder)}
|
|
138
138
|
iconPosition="end"
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
SymbolDoc,
|
|
5
5
|
SymbolDescription,
|
|
6
6
|
} from '@workday/canvas-kit-docs';
|
|
7
|
+
import { Pill } from '@workday/canvas-kit-preview-react/pill';
|
|
8
|
+
import { accessibilityIcon } from '@workday/canvas-system-icons-web';
|
|
7
9
|
|
|
8
10
|
import Primary from './examples/Primary';
|
|
9
11
|
import PrimaryInverse from './examples/PrimaryInverse';
|
|
@@ -94,7 +96,7 @@ or view the example below.
|
|
|
94
96
|
|
|
95
97
|
### Theme Overrides
|
|
96
98
|
|
|
97
|
-
The most common way to theme our buttons is to pass a `theme` object at the root level of the application via the `CanvasProvider`. In the example below, our buttons use our `brand.action.**` tokens with the fallback being `brand.primary.**`.
|
|
99
|
+
The most common way to theme our buttons is to pass a `theme` object at the root level of the application via the `CanvasProvider`. In the example below, our buttons use our `brand.action.**` tokens with the fallback being `brand.primary.**`.
|
|
98
100
|
|
|
99
101
|
> **Caution:** Setting `--cnvs-brand-action**` tokens at the `:root` CSS will override all `PrimaryButton` theme colors set at the `CanvasProvider` level.
|
|
100
102
|
|
|
@@ -102,6 +104,13 @@ The most common way to theme our buttons is to pass a `theme` object at the root
|
|
|
102
104
|
|
|
103
105
|
<ExampleCodeBlock code={ThemeOverrides} />
|
|
104
106
|
|
|
107
|
+
## Accessibility
|
|
108
|
+
|
|
109
|
+
<Pill className='sb-unstyled'>
|
|
110
|
+
<Pill.Icon icon={accessibilityIcon} />
|
|
111
|
+
<Pill.Label>WAI-ARIA Reference</Pill.Label>
|
|
112
|
+
</Pill>
|
|
113
|
+
|
|
105
114
|
### Accessible Use of the `as` Prop
|
|
106
115
|
|
|
107
116
|
Like many of our components, Buttons accept an `as` prop, which lets you change the underlying
|
|
@@ -109,6 +118,10 @@ semantic element - usually an `<a>`, or a `<button>`. This should be done with c
|
|
|
109
118
|
best accessibility. Generally, `<button>` elements should be used for actions, and `<a>` elements
|
|
110
119
|
should be used for navigation.
|
|
111
120
|
|
|
121
|
+
### Role
|
|
122
|
+
|
|
123
|
+
By default buttons have a `role` of `button`. If you wish to use buttons in the context of a form, the role should be set to type `submit`.
|
|
124
|
+
|
|
112
125
|
## Component API
|
|
113
126
|
|
|
114
127
|
<SymbolDoc name="PrimaryButton" fileName="/react/" />
|
|
@@ -34,15 +34,15 @@ The codemod requires the following packages to be installed:
|
|
|
34
34
|
You can run the codemod using npx:
|
|
35
35
|
|
|
36
36
|
```sh
|
|
37
|
-
npx @workday/canvas-
|
|
37
|
+
npx @workday/canvas-kit-codemod v13.2 [path]
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Or install the package and run it directly. But remember to uninstall the package after you have
|
|
41
41
|
completed the upgrade.
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
yarn add @workday/canvas-
|
|
45
|
-
canvas-
|
|
44
|
+
yarn add @workday/canvas-kit-codemod
|
|
45
|
+
canvas-kit-codemod v13.2 [path]
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
> Note: These codemods only work on .js, .jsx, .ts, and .tsx extensions. You may need to make some
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.1190-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",
|
|
@@ -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.0-alpha.
|
|
49
|
-
"@workday/canvas-kit-preview-react": "^14.0.0-alpha.
|
|
50
|
-
"@workday/canvas-kit-react": "^14.0.0-alpha.
|
|
51
|
-
"@workday/canvas-kit-styling": "^14.0.0-alpha.
|
|
48
|
+
"@workday/canvas-kit-labs-react": "^14.0.0-alpha.1190-next.0",
|
|
49
|
+
"@workday/canvas-kit-preview-react": "^14.0.0-alpha.1190-next.0",
|
|
50
|
+
"@workday/canvas-kit-react": "^14.0.0-alpha.1190-next.0",
|
|
51
|
+
"@workday/canvas-kit-styling": "^14.0.0-alpha.1190-next.0",
|
|
52
52
|
"@workday/canvas-system-icons-web": "^3.0.35",
|
|
53
53
|
"@workday/canvas-tokens-web": "3.0.0-alpha.10",
|
|
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": "152cb8d23c62761fd6e0af7b99c871907d986134"
|
|
65
65
|
}
|