mirror of
https://github.com/google/blockly.git
synced 2026-06-17 00:25:14 +02:00
feat!: announce toasts via shared ARIA live region (#9672)
* feat: announce toasts via shared ARIA live region * chore: add extra space
This commit is contained in:
@@ -45,7 +45,7 @@ export interface ToastOptions {
|
||||
* How prominently/interrupting the readout of the toast should be for
|
||||
* screenreaders. Corresponds to aria-live and defaults to polite.
|
||||
*/
|
||||
assertiveness?: Toast.Assertiveness;
|
||||
assertiveness?: aria.LiveRegionAssertiveness;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,15 +89,13 @@ export class Toast {
|
||||
const {
|
||||
message,
|
||||
duration = 5,
|
||||
assertiveness = Toast.Assertiveness.POLITE,
|
||||
assertiveness = aria.LiveRegionAssertiveness.POLITE,
|
||||
} = options;
|
||||
|
||||
const toast = document.createElement('div');
|
||||
workspace.getInjectionDiv().appendChild(toast);
|
||||
toast.dataset.toastId = options.id;
|
||||
toast.className = CLASS_NAME;
|
||||
aria.setRole(toast, aria.Role.STATUS);
|
||||
aria.setState(toast, aria.State.LIVE, assertiveness);
|
||||
|
||||
const messageElement = toast.appendChild(document.createElement('div'));
|
||||
messageElement.className = MESSAGE_CLASS_NAME;
|
||||
@@ -157,6 +155,11 @@ export class Toast {
|
||||
toast.addEventListener('mouseleave', setToastTimeout);
|
||||
setToastTimeout();
|
||||
|
||||
aria.announceDynamicAriaState(message, {
|
||||
assertiveness,
|
||||
role: aria.Role.STATUS,
|
||||
});
|
||||
|
||||
return toast;
|
||||
}
|
||||
|
||||
@@ -174,17 +177,6 @@ export class Toast {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for how aggressively toasts should be read out by screenreaders.
|
||||
* Values correspond to those for aria-live.
|
||||
*/
|
||||
export namespace Toast {
|
||||
export enum Assertiveness {
|
||||
ASSERTIVE = 'assertive',
|
||||
POLITE = 'polite',
|
||||
}
|
||||
}
|
||||
|
||||
Css.register(`
|
||||
.${CLASS_NAME} {
|
||||
font-size: 1.2rem;
|
||||
|
||||
@@ -14,6 +14,7 @@ suite('Toasts', function () {
|
||||
setup(function () {
|
||||
sharedTestSetup.call(this);
|
||||
this.workspace = Blockly.inject('blocklyDiv', {});
|
||||
this.liveRegion = document.getElementById('blocklyAriaAnnounce');
|
||||
this.toastIsVisible = (message) => {
|
||||
const toast = this.workspace
|
||||
.getInjectionDiv()
|
||||
@@ -97,16 +98,20 @@ suite('Toasts', function () {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('default to polite assertiveness', function () {
|
||||
test('toast announces message with status role and polite assertiveness', function () {
|
||||
const message = 'texas toast';
|
||||
Blockly.Toast.show(this.workspace, {message, id: 'test'});
|
||||
const toast = this.workspace
|
||||
.getInjectionDiv()
|
||||
.querySelector('.blocklyToast');
|
||||
|
||||
this.clock.tick(11);
|
||||
|
||||
assert.include(this.liveRegion.textContent, message);
|
||||
assert.equal(
|
||||
toast.getAttribute('aria-live'),
|
||||
Blockly.Toast.Assertiveness.POLITE,
|
||||
this.liveRegion.getAttribute('role'),
|
||||
Blockly.utils.aria.Role.STATUS,
|
||||
);
|
||||
assert.equal(
|
||||
this.liveRegion.getAttribute('aria-live'),
|
||||
Blockly.utils.aria.LiveRegionAssertiveness.POLITE,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -115,15 +120,26 @@ suite('Toasts', function () {
|
||||
Blockly.Toast.show(this.workspace, {
|
||||
message,
|
||||
id: 'test',
|
||||
assertiveness: Blockly.Toast.Assertiveness.ASSERTIVE,
|
||||
assertiveness: Blockly.utils.aria.LiveRegionAssertiveness.ASSERTIVE,
|
||||
});
|
||||
|
||||
this.clock.tick(11);
|
||||
|
||||
assert.equal(
|
||||
this.liveRegion.getAttribute('aria-live'),
|
||||
Blockly.utils.aria.LiveRegionAssertiveness.ASSERTIVE,
|
||||
);
|
||||
});
|
||||
|
||||
test('toast is not itself a live region', function () {
|
||||
const message = 'texas toast';
|
||||
Blockly.Toast.show(this.workspace, {message, id: 'test'});
|
||||
|
||||
const toast = this.workspace
|
||||
.getInjectionDiv()
|
||||
.querySelector('.blocklyToast');
|
||||
|
||||
assert.equal(
|
||||
toast.getAttribute('aria-live'),
|
||||
Blockly.Toast.Assertiveness.ASSERTIVE,
|
||||
);
|
||||
assert.isNull(toast.getAttribute('aria-live'));
|
||||
assert.notEqual(toast.getAttribute('role'), Blockly.utils.aria.Role.STATUS);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user