@workday/canvas-kit-docs 11.1.8 → 11.1.9
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.
|
@@ -42,10 +42,20 @@ messages on their first day back.
|
|
|
42
42
|
|
|
43
43
|
### Notification Badge
|
|
44
44
|
|
|
45
|
-
Notifications are a major use case for `CountBadge`.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
Notifications are a major use case for `CountBadge`. When the `CountBadge` value is updated in
|
|
46
|
+
real-time, screen readers must be supported with an `AriaLiveRegion` that will automatically
|
|
47
|
+
describe the change in the number of notifications. If the web app only updates `CountBadge` as part
|
|
48
|
+
of another screen update, then this use of `AriaLiveRegion` is unnecessary and not recommended.
|
|
49
|
+
|
|
50
|
+
#### Notes on accessibility for the example below
|
|
51
|
+
|
|
52
|
+
- `Tooltip` is set on the `SecondaryButton` automatically applying the `aria-label` to the button.
|
|
53
|
+
- `aria-describedby` property is conditionally set on the `SecondaryButton` when greater than zero
|
|
54
|
+
referencing a unique `id` for the `CountBadge` value .
|
|
55
|
+
- `AriaLiveRegion` is used around the `CountBadge`, enabling screen readers to monitor changes in
|
|
56
|
+
value.
|
|
57
|
+
- `aria-label` string is conditionally set on `AriaLiveRegion` when greater than zero, describing
|
|
58
|
+
"New notification"
|
|
49
59
|
|
|
50
60
|
<ExampleCodeBlock code={NotificationBadge} />
|
|
51
61
|
|
|
@@ -54,17 +64,6 @@ the Accessibility guidance below this example for aditional information.
|
|
|
54
64
|
Count Badge supports custom styling via the `cs` prop. For more information, check our
|
|
55
65
|
["How To Customize Styles"](https://workday.github.io/canvas-kit/?path=/docs/styling-how-to-customize-styles--page).
|
|
56
66
|
|
|
57
|
-
## Accessibility
|
|
58
|
-
|
|
59
|
-
A common use case for `CountBadge` is displaying notifications, but there are other situations where
|
|
60
|
-
they will have live-updated values. There are several accessibility concerns you'll want to keep in
|
|
61
|
-
mind:
|
|
62
|
-
|
|
63
|
-
- The button should have an aria-label that updates with the count
|
|
64
|
-
- The elements inside the button should have `aria-hidden`
|
|
65
|
-
- The live region should be outside the button
|
|
66
|
-
- The live region should be visually hidden and only contain text
|
|
67
|
-
|
|
68
67
|
## Component API
|
|
69
68
|
|
|
70
69
|
<SymbolDoc name="CountBadge" fileName="/react/" />
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import {CountBadge} from '@workday/canvas-kit-react/badge';
|
|
3
3
|
import {SecondaryButton, TertiaryButton} from '@workday/canvas-kit-react/button';
|
|
4
|
-
import {
|
|
4
|
+
import {AriaLiveRegion, useUniqueId} from '@workday/canvas-kit-react/common';
|
|
5
5
|
import {createStyles, cssVar} from '@workday/canvas-kit-styling';
|
|
6
6
|
import {notificationsIcon} from '@workday/canvas-system-icons-web';
|
|
7
7
|
import {base, system} from '@workday/canvas-tokens-web';
|
|
8
|
+
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
9
|
+
import {Flex} from '@workday/canvas-kit-react/layout';
|
|
8
10
|
|
|
9
11
|
function negate(value: string, fallback?: string) {
|
|
10
12
|
return `calc(${cssVar(value, fallback)} * -1)`;
|
|
@@ -12,16 +14,13 @@ function negate(value: string, fallback?: string) {
|
|
|
12
14
|
|
|
13
15
|
const container = createStyles({
|
|
14
16
|
boxSizing: 'border-box',
|
|
15
|
-
display: 'flex',
|
|
16
17
|
flexDirection: 'column',
|
|
17
18
|
gap: system.space.x4,
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
const controls = createStyles({
|
|
21
22
|
boxSizing: 'border-box',
|
|
22
|
-
|
|
23
|
-
display: 'flex',
|
|
24
|
-
gap: system.space.x1,
|
|
23
|
+
gap: system.space.x2,
|
|
25
24
|
padding: system.space.x1,
|
|
26
25
|
});
|
|
27
26
|
|
|
@@ -33,40 +32,46 @@ const notificationContainerStyles = createStyles({
|
|
|
33
32
|
const countBadgeStyles = createStyles({
|
|
34
33
|
boxSizing: 'border-box',
|
|
35
34
|
position: 'absolute',
|
|
36
|
-
top: negate(system.space.
|
|
35
|
+
top: negate(system.space.x1),
|
|
37
36
|
insetInlineEnd: negate(system.space.x1),
|
|
38
37
|
});
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
// Testing notes (Aug. 30, 2024):
|
|
40
|
+
// Windows 11
|
|
41
|
+
// JAWS 2024 + Chrome / Edge: "New notifications" once, then only the count change "2"
|
|
42
|
+
// JAWS 2024 + FF: "New notifications" once, then describes nothing
|
|
43
|
+
// NVDA + Chrome / Edge: Consistently describes "{X} New notifications"
|
|
44
|
+
// NVDA + FF: Consistently describes count value only "{X}"
|
|
45
|
+
// macOS v14.6.1
|
|
46
|
+
// VoiceOver + Chrome / Safari: Consistently describes "New notifications {X}"
|
|
42
47
|
export function NotificationBadge() {
|
|
43
48
|
const [count, setCount] = React.useState(4);
|
|
49
|
+
const badgeID = useUniqueId();
|
|
44
50
|
|
|
45
51
|
return (
|
|
46
|
-
<
|
|
47
|
-
<
|
|
52
|
+
<Flex cs={container}>
|
|
53
|
+
<Flex cs={controls}>
|
|
48
54
|
<TertiaryButton size="small" onClick={() => setCount(count + 1)}>
|
|
49
55
|
Add Notification
|
|
50
56
|
</TertiaryButton>
|
|
51
57
|
<TertiaryButton size="small" onClick={() => setCount(0)}>
|
|
52
58
|
Clear
|
|
53
59
|
</TertiaryButton>
|
|
54
|
-
</
|
|
55
|
-
<
|
|
60
|
+
</Flex>
|
|
61
|
+
<Flex>
|
|
56
62
|
<span className={notificationContainerStyles}>
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
</div>
|
|
63
|
+
<Tooltip title="Notifications">
|
|
64
|
+
<SecondaryButton
|
|
65
|
+
size="medium"
|
|
66
|
+
icon={notificationsIcon}
|
|
67
|
+
aria-describedby={!!count ? badgeID : undefined}
|
|
68
|
+
/>
|
|
69
|
+
</Tooltip>
|
|
70
|
+
<AriaLiveRegion aria-label={!!count ? 'New notifications' : undefined}>
|
|
71
|
+
{!!count && <CountBadge id={badgeID} count={count} limit={100} cs={countBadgeStyles} />}
|
|
72
|
+
</AriaLiveRegion>
|
|
68
73
|
</span>
|
|
69
|
-
</
|
|
70
|
-
</
|
|
74
|
+
</Flex>
|
|
75
|
+
</Flex>
|
|
71
76
|
);
|
|
72
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "11.1.
|
|
3
|
+
"version": "11.1.9",
|
|
4
4
|
"description": "Documentation components of Canvas Kit components",
|
|
5
5
|
"author": "Workday, Inc. (https://www.workday.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@emotion/styled": "^11.6.0",
|
|
46
46
|
"@storybook/csf": "0.0.1",
|
|
47
|
-
"@workday/canvas-kit-labs-react": "^11.1.
|
|
48
|
-
"@workday/canvas-kit-preview-react": "^11.1.
|
|
49
|
-
"@workday/canvas-kit-react": "^11.1.
|
|
50
|
-
"@workday/canvas-kit-styling": "^11.1.
|
|
47
|
+
"@workday/canvas-kit-labs-react": "^11.1.9",
|
|
48
|
+
"@workday/canvas-kit-preview-react": "^11.1.9",
|
|
49
|
+
"@workday/canvas-kit-react": "^11.1.9",
|
|
50
|
+
"@workday/canvas-kit-styling": "^11.1.9",
|
|
51
51
|
"@workday/canvas-system-icons-web": "^3.0.0",
|
|
52
52
|
"@workday/canvas-tokens-web": "^2.0.0",
|
|
53
53
|
"markdown-to-jsx": "^7.2.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"mkdirp": "^1.0.3",
|
|
60
60
|
"typescript": "4.2"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "c81e8e0bef16f336966043e58a3c119dbab19617"
|
|
63
63
|
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import React, {useState} from 'react';
|
|
2
|
-
import {AccessibleHide, AriaLiveRegion, useUniqueId} from '@workday/canvas-kit-react/common';
|
|
3
|
-
import {notificationsIcon, inboxIcon, assistantIcon} from '@workday/canvas-system-icons-web';
|
|
4
|
-
import {space} from '@workday/canvas-kit-react/tokens';
|
|
5
|
-
import {SecondaryButton, TertiaryButton} from '@workday/canvas-kit-react/button';
|
|
6
|
-
import {Flex} from '@workday/canvas-kit-react/layout';
|
|
7
|
-
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
8
|
-
import {CountBadge} from '@workday/canvas-kit-react/badge';
|
|
9
|
-
|
|
10
|
-
const MyTasksLiveBadge = ({cnt}) => {
|
|
11
|
-
// use tooltip to assign name,
|
|
12
|
-
// use AriaLiveRegion inside button,
|
|
13
|
-
// assign name to live region referencing the button,
|
|
14
|
-
// use BadgeCount inside live region,
|
|
15
|
-
// use AccessibleHide to create invisible word "new" after badge
|
|
16
|
-
// use aria-describedby on button, referencing live region container to set description
|
|
17
|
-
// Safari + VO => not working at all
|
|
18
|
-
// JAWS 2024 + Chrome / Edge => works as expected :)
|
|
19
|
-
// NVDA + Chrome / Edge => works as expected :)
|
|
20
|
-
// Firefox => isn't announcing description on focus, only announces "X New" live (missing button name)
|
|
21
|
-
const badgeID = useUniqueId();
|
|
22
|
-
const myTasksID = useUniqueId();
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<Tooltip title="My Tasks">
|
|
26
|
-
<TertiaryButton icon={inboxIcon} id={myTasksID} aria-describedby={badgeID}>
|
|
27
|
-
<AriaLiveRegion id={badgeID} aria-labelledby={myTasksID}>
|
|
28
|
-
<CountBadge count={cnt} />
|
|
29
|
-
<AccessibleHide>New</AccessibleHide>
|
|
30
|
-
</AriaLiveRegion>
|
|
31
|
-
</TertiaryButton>
|
|
32
|
-
</Tooltip>
|
|
33
|
-
);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// use AriaLiveRegion around the button,
|
|
37
|
-
// use Tooltip to assign the name of the button,
|
|
38
|
-
// make sure Tooltip title string includes count value
|
|
39
|
-
// Chrome + VO => Announces name "notifications X new" and innerText 'X'
|
|
40
|
-
// Safari + VO => Works as expected :)
|
|
41
|
-
// JAWS 2024 => Announces full button name twice (previous state, then new state)
|
|
42
|
-
// JAWS 2024 + Firefox => Works as expected :)
|
|
43
|
-
// NVDA (All Browsers) => Atomic property isn't working, only announcing number change, announces twice
|
|
44
|
-
const NotificationsLiveBadge = ({cnt}) => (
|
|
45
|
-
<AriaLiveRegion>
|
|
46
|
-
<Tooltip title={`Notifications ${cnt} new`}>
|
|
47
|
-
<TertiaryButton icon={notificationsIcon}>
|
|
48
|
-
<CountBadge count={cnt} />
|
|
49
|
-
</TertiaryButton>
|
|
50
|
-
</Tooltip>
|
|
51
|
-
</AriaLiveRegion>
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const AssistantLiveBadge = ({cnt}) => {
|
|
55
|
-
// use AriaLiveRegion around the button
|
|
56
|
-
// use muted type Tooltip (avoid using aria-label to name button)
|
|
57
|
-
// use AccessibleHide inside of button to compose name
|
|
58
|
-
// Chrome + VO => announces twice
|
|
59
|
-
// Safari + VO => works as expected :)
|
|
60
|
-
const lbl = 'Workday Assistant';
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<AriaLiveRegion>
|
|
64
|
-
<Tooltip title={lbl} type="muted">
|
|
65
|
-
<TertiaryButton icon={assistantIcon}>
|
|
66
|
-
<AccessibleHide>{lbl}</AccessibleHide>
|
|
67
|
-
<CountBadge count={cnt} />
|
|
68
|
-
<AccessibleHide>New</AccessibleHide>
|
|
69
|
-
</TertiaryButton>
|
|
70
|
-
</Tooltip>
|
|
71
|
-
</AriaLiveRegion>
|
|
72
|
-
);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export default () => {
|
|
76
|
-
const [counter, setCounter] = useState(0);
|
|
77
|
-
const [notifications, setNotifications] = useState(0);
|
|
78
|
-
const [assistant, setAssistant] = useState(0);
|
|
79
|
-
|
|
80
|
-
const handleAddTask = () => setCounter(prev => prev + 1);
|
|
81
|
-
const handleAddNotification = () => setNotifications(prev => prev + 1);
|
|
82
|
-
const handleAssistant = () => setAssistant(prev => prev + 1);
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<>
|
|
86
|
-
<Flex padding={space.s} gap={space.s} as="header">
|
|
87
|
-
<AssistantLiveBadge cnt={assistant} />
|
|
88
|
-
<NotificationsLiveBadge cnt={notifications} />
|
|
89
|
-
<MyTasksLiveBadge cnt={counter} />
|
|
90
|
-
</Flex>
|
|
91
|
-
<Flex padding={space.s} gap={space.s} as="main">
|
|
92
|
-
<SecondaryButton onClick={handleAssistant}>Add a Message</SecondaryButton>
|
|
93
|
-
<SecondaryButton onClick={handleAddNotification}>Add a Notification</SecondaryButton>
|
|
94
|
-
<SecondaryButton onClick={handleAddTask}>Add an item to My Tasks</SecondaryButton>
|
|
95
|
-
</Flex>
|
|
96
|
-
</>
|
|
97
|
-
);
|
|
98
|
-
};
|