Skip to content

Commit e15d3a8

Browse files
authored
Add aria-labelledby and move button up (#4609)
* Add aria-labelledby and move button up * Update entry
1 parent 359ce8e commit e15d3a8

File tree

4 files changed

+72
-20
lines changed

4 files changed

+72
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2626

2727
- Fixes [#4558](https://github.com/microsoft/BotFramework-WebChat/issues/4558). In high contrast mode, "Retry" link button should use link color as defined by [CSS System Colors](https://w3c.github.io/csswg-drafts/css-color/#css-system-colors), by [@beyackle2](https://github.com/beyackle2) in PR [#4537](https://github.com/microsoft/BotFramework-WebChat/pull/4537)
2828
- Fixes [#4566](https://github.com/microsoft/BotFramework-WebChat/issues/4566). For YouTube and Vimeo `<iframe>`, add `sandbox="allow-same-origin allow-scripts"`, by [@compulim](https://github.com/compulim) in PR [#4567](https://github.com/microsoft/BotFramework-WebChat/pull/4567)
29+
- Fixes [#4561](https://github.com/microsoft/BotFramework-WebChat/issues/4561). Header title of keyboard help dialog should be the `aria-labelledby` of the dialog and close button should be the first element of the header, by [@compulim](https://github.com/compulim) in PR [#4609](https://github.com/microsoft/BotFramework-WebChat/pull/4609)
2930

3031
### Changed
3132

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" src="/test-harness.js"></script>
6+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
7+
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
8+
</head>
9+
<body>
10+
<div id="webchat"></div>
11+
<script>
12+
run(async function () {
13+
const store = testHelpers.createStore();
14+
15+
const directLine = testHelpers.createDirectLineEmulator(store);
16+
17+
WebChat.renderWebChat({ directLine, store }, document.getElementById('webchat'));
18+
19+
await pageConditions.uiConnected();
20+
21+
// SETUP: The focus should be on `document.body` initially.
22+
await pageConditions.focusOn(document.body, 'document body');
23+
24+
// WHEN: TAB key is pressed.
25+
await host.sendTab();
26+
27+
// THEN: It should focus on the close button.
28+
await pageConditions.focusOn(pageElements.keyboardHelpScreenCloseButton(), 'keyboard help screen close button');
29+
30+
// THEN: The keyboard help screen dialog should have either `aria-label` or `aria-labelledby` saying "Keyboard controls".
31+
const dialogElement = pageElements.keyboardHelpScreenCloseButton().closest('[role="dialog"]');
32+
33+
const ariaLabel = dialogElement.getAttribute('aria-label') || document.getElementById(dialogElement.getAttribute('aria-labelledby'))?.innerText;
34+
35+
expect(ariaLabel).toBe('Keyboard controls');
36+
});
37+
</script>
38+
</body>
39+
</html>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */
2+
3+
describe('keyboard help screen', () => {
4+
test('should have a label', () => runHTML('accessibility.keyboardHelp.ariaLabel'));
5+
});

packages/component/src/Transcript/KeyboardHelp.tsx

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { FC } from 'react';
77

88
import useFocus from '../hooks/useFocus';
99
import useStyleSet from '../hooks/useStyleSet';
10+
import useUniqueId from '../hooks/internal/useUniqueId';
1011

1112
const { useLocalizer } = hooks;
1213

@@ -37,6 +38,7 @@ const KeyboardHelp: FC<{}> = () => {
3738
const [{ keyboardHelp: keyboardHelpStyleSet }] = useStyleSet();
3839
const [shown, setShown] = useState(false);
3940
const focus = useFocus();
41+
const headerLabelId = useUniqueId('webchat__keyboard-help__header');
4042
const localize = useLocalizer();
4143

4244
const chatHistoryAccessItemsInMessageBody = localize('KEYBOARD_HELP_CHAT_HISTORY_ACCESS_ITEMS_IN_MESSAGE_BODY');
@@ -84,6 +86,7 @@ const KeyboardHelp: FC<{}> = () => {
8486
<div
8587
// When the dialog is not shown, "aria-hidden" helps to prevent scan mode from able to scan the content of the dialog.
8688
aria-hidden={!shown}
89+
aria-labelledby={headerLabelId}
8790
className={classNames('webchat__keyboard-help', keyboardHelpStyleSet + '', {
8891
// Instead of using "hidden" attribute, we are using CSS to hide the dialog.
8992
// - When using "hidden", the close button will not be tabbable because it is pseudo removed from the DOM
@@ -96,27 +99,31 @@ const KeyboardHelp: FC<{}> = () => {
9699
>
97100
<div className="webchat__keyboard-help__box">
98101
<header>
99-
<h2 className="webchat__keyboard-help__header">{header}</h2>
100-
</header>
101-
<button
102-
aria-label={closeButtonAlt}
103-
className="webchat__keyboard-help__close-button"
104-
onClick={handleCloseButtonClick}
105-
onFocus={handleCloseButtonFocus}
106-
onKeyDown={handleCloseButtonKeyDown}
107-
type="button"
108-
>
109-
<svg
110-
className="webchat__keyboard-help__close-button_image"
111-
// "focusable" attribute is only available in IE11 and "tabIndex={-1}" does not work.
112-
focusable={false}
113-
role="presentation"
114-
viewBox="0 0 2048 2048"
115-
xmlns="http://www.w3.org/2000/svg"
102+
<button
103+
aria-label={closeButtonAlt}
104+
className="webchat__keyboard-help__close-button"
105+
onClick={handleCloseButtonClick}
106+
onFocus={handleCloseButtonFocus}
107+
onKeyDown={handleCloseButtonKeyDown}
108+
type="button"
116109
>
117-
<path d="M2048 136l-888 888 888 888-136 136-888-888-888 888L0 1912l888-888L0 136 136 0l888 888L1912 0l136 136z" />
118-
</svg>
119-
</button>
110+
<svg
111+
className="webchat__keyboard-help__close-button_image"
112+
// "focusable" attribute is only available in IE11 and "tabIndex={-1}" does not work.
113+
focusable={false}
114+
role="presentation"
115+
viewBox="0 0 2048 2048"
116+
xmlns="http://www.w3.org/2000/svg"
117+
>
118+
<path d="M2048 136l-888 888 888 888-136 136-888-888-888 888L0 1912l888-888L0 136 136 0l888 888L1912 0l136 136z" />
119+
</svg>
120+
</button>
121+
{/* "id" attribute is required when using "aria-labelledby". */}
122+
{/* eslint-disable-next-line react/forbid-dom-props */}
123+
<h2 className="webchat__keyboard-help__header" id={headerLabelId}>
124+
{header}
125+
</h2>
126+
</header>
120127
<article className="webchat__keyboard-help__section">
121128
<header>
122129
<h3 className="webchat__keyboard-help__sub-header">{chatWindowHeader}</h3>

0 commit comments

Comments
 (0)