diff --git a/modules/react/_examples/stories/examples/AriaLiveRegions/IconButtonsWithLiveBadges.tsx b/modules/react/_examples/stories/examples/AriaLiveRegions/IconButtonsWithLiveBadges.tsx
deleted file mode 100644
index 4f326d7660..0000000000
--- a/modules/react/_examples/stories/examples/AriaLiveRegions/IconButtonsWithLiveBadges.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, {useState} from 'react';
-import {AccessibleHide, AriaLiveRegion, useUniqueId} from '@workday/canvas-kit-react/common';
-import {notificationsIcon, inboxIcon, assistantIcon} from '@workday/canvas-system-icons-web';
-import {space} from '@workday/canvas-kit-react/tokens';
-import {SecondaryButton, TertiaryButton} from '@workday/canvas-kit-react/button';
-import {Flex} from '@workday/canvas-kit-react/layout';
-import {Tooltip} from '@workday/canvas-kit-react/tooltip';
-import {CountBadge} from '@workday/canvas-kit-react/badge';
-
-const MyTasksLiveBadge = ({cnt}) => {
- // use tooltip to assign name,
- // use AriaLiveRegion inside button,
- // assign name to live region referencing the button,
- // use BadgeCount inside live region,
- // use AccessibleHide to create invisible word "new" after badge
- // use aria-describedby on button, referencing live region container to set description
- // Safari + VO => not working at all
- // JAWS 2024 + Chrome / Edge => works as expected :)
- // NVDA + Chrome / Edge => works as expected :)
- // Firefox => isn't announcing description on focus, only announces "X New" live (missing button name)
- const badgeID = useUniqueId();
- const myTasksID = useUniqueId();
-
- return (
-
-
-
-
- New
-
-
-
- );
-};
-
-// use AriaLiveRegion around the button,
-// use Tooltip to assign the name of the button,
-// make sure Tooltip title string includes count value
-// Chrome + VO => Announces name "notifications X new" and innerText 'X'
-// Safari + VO => Works as expected :)
-// JAWS 2024 => Announces full button name twice (previous state, then new state)
-// JAWS 2024 + Firefox => Works as expected :)
-// NVDA (All Browsers) => Atomic property isn't working, only announcing number change, announces twice
-const NotificationsLiveBadge = ({cnt}) => (
-
-
-
-
-
-
-
-);
-
-const AssistantLiveBadge = ({cnt}) => {
- // use AriaLiveRegion around the button
- // use muted type Tooltip (avoid using aria-label to name button)
- // use AccessibleHide inside of button to compose name
- // Chrome + VO => announces twice
- // Safari + VO => works as expected :)
- const lbl = 'Workday Assistant';
-
- return (
-
-
-
- {lbl}
-
- New
-
-
-
- );
-};
-
-export const IconButtonsWithLiveBadges = () => {
- const [counter, setCounter] = useState(0);
- const [notifications, setNotifications] = useState(0);
- const [assistant, setAssistant] = useState(0);
-
- const handleAddTask = () => setCounter(prev => prev + 1);
- const handleAddNotification = () => setNotifications(prev => prev + 1);
- const handleAssistant = () => setAssistant(prev => prev + 1);
-
- return (
- <>
-
-
-
-
-
-
- Add a Message
- Add a Notification
- Add an item to My Tasks
-
- >
- );
-};
diff --git a/modules/react/badge/stories/CountBadge.stories.mdx b/modules/react/badge/stories/CountBadge.stories.mdx
index 7294f2caa2..3684815382 100644
--- a/modules/react/badge/stories/CountBadge.stories.mdx
+++ b/modules/react/badge/stories/CountBadge.stories.mdx
@@ -43,10 +43,20 @@ messages on their first day back.
### Notification Badge
-Notifications are a major use case for `CountBadge`. Remember that any `CountBadge` with a
-live-updating value should be announced to screen readers with an `aria-live` region and an
-`aria-label` on the button to provide additional context, as in the example below. Please also read
-the Accessibility guidance below this example for aditional information.
+Notifications are a major use case for `CountBadge`. When the `CountBadge` value is updated in
+real-time, screen readers must be supported with an `AriaLiveRegion` that will automatically
+describe the change in the number of notifications. If the web app only updates `CountBadge` as part
+of another screen update, then this use of `AriaLiveRegion` is unnecessary and not recommended.
+
+#### Notes on accessibility for the example below
+
+- `Tooltip` is set on the `SecondaryButton` automatically applying the `aria-label` to the button.
+- `aria-describedby` property is conditionally set on the `SecondaryButton` when greater than zero
+ referencing a unique `id` for the `CountBadge` value .
+- `AriaLiveRegion` is used around the `CountBadge`, enabling screen readers to monitor changes in
+ value.
+- `aria-label` string is conditionally set on `AriaLiveRegion` when greater than zero, describing
+ "New notification"
@@ -55,17 +65,6 @@ the Accessibility guidance below this example for aditional information.
Count Badge supports custom styling via the `cs` prop. For more information, check our
["How To Customize Styles"](https://workday.github.io/canvas-kit/?path=/docs/styling-how-to-customize-styles--page).
-## Accessibility
-
-A common use case for `CountBadge` is displaying notifications, but there are other situations where
-they will have live-updated values. There are several accessibility concerns you'll want to keep in
-mind:
-
-- The button should have an aria-label that updates with the count
-- The elements inside the button should have `aria-hidden`
-- The live region should be outside the button
-- The live region should be visually hidden and only contain text
-
## Component API
diff --git a/modules/react/badge/stories/examples/NotificationBadge.tsx b/modules/react/badge/stories/examples/NotificationBadge.tsx
index 6a6cda7ad8..a5135d1a92 100644
--- a/modules/react/badge/stories/examples/NotificationBadge.tsx
+++ b/modules/react/badge/stories/examples/NotificationBadge.tsx
@@ -1,10 +1,12 @@
import * as React from 'react';
import {CountBadge} from '@workday/canvas-kit-react/badge';
import {SecondaryButton, TertiaryButton} from '@workday/canvas-kit-react/button';
-import {accessibleHide} from '@workday/canvas-kit-react/common';
+import {AriaLiveRegion, useUniqueId} from '@workday/canvas-kit-react/common';
import {createStyles, cssVar} from '@workday/canvas-kit-styling';
import {notificationsIcon} from '@workday/canvas-system-icons-web';
import {base, system} from '@workday/canvas-tokens-web';
+import {Tooltip} from '@workday/canvas-kit-react/tooltip';
+import {Flex} from '@workday/canvas-kit-react/layout';
function negate(value: string, fallback?: string) {
return `calc(${cssVar(value, fallback)} * -1)`;
@@ -12,16 +14,13 @@ function negate(value: string, fallback?: string) {
const container = createStyles({
boxSizing: 'border-box',
- display: 'flex',
flexDirection: 'column',
gap: system.space.x4,
});
const controls = createStyles({
boxSizing: 'border-box',
- borderBottom: `solid 1px ${cssVar(base.soap400)}`,
- display: 'flex',
- gap: system.space.x1,
+ gap: system.space.x2,
padding: system.space.x1,
});
@@ -33,40 +32,46 @@ const notificationContainerStyles = createStyles({
const countBadgeStyles = createStyles({
boxSizing: 'border-box',
position: 'absolute',
- top: negate(system.space.x4),
+ top: negate(system.space.x1),
insetInlineEnd: negate(system.space.x1),
});
-const accessibleHideStyles = createStyles(accessibleHide);
-
+// Testing notes (Aug. 30, 2024):
+// Windows 11
+// JAWS 2024 + Chrome / Edge: "New notifications" once, then only the count change "2"
+// JAWS 2024 + FF: "New notifications" once, then describes nothing
+// NVDA + Chrome / Edge: Consistently describes "{X} New notifications"
+// NVDA + FF: Consistently describes count value only "{X}"
+// macOS v14.6.1
+// VoiceOver + Chrome / Safari: Consistently describes "New notifications {X}"
export function NotificationBadge() {
const [count, setCount] = React.useState(4);
+ const badgeID = useUniqueId();
return (
-
-
+
+
setCount(count + 1)}>
Add Notification
setCount(0)}>
Clear
-
-
+
+
-
- {!!count && (
-
- )}
-
- New notifications
-
+
+
+
+
+ {!!count && }
+
-
-
+
+
);
}