Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added aria-live to the tab bar to improve screen reader accessibility. #627

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion packages/commands/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,24 @@ export class CommandRegistry {
this._startTimer();
}

/**
* Add a dialog to a command
*
* @param id - The id of the command of interest.
*
* @param args - The arguments for the command.
*
* @returns A private ICommand or undefined of the dialog string
* or `an empty sting` if the command does not have a dialog.
*/
commandDialog(
id: string,
args: ReadonlyPartialJSONObject = JSONExt.emptyObject
): string {
let cmd = this._commands.get(id);
return cmd?.commandDialog.call(undefined, args) ?? '';
}

/**
* Start or restart the pending timeout.
*/
Expand Down Expand Up @@ -904,6 +922,17 @@ export namespace CommandRegistry {
* The default value is `() => true`.
*/
isVisible?: CommandFunc<boolean>;

/**
* A function which sets the command dialog text.
*
* #### Notes
* This function sets a string which the screen reader will
* read aloud. This will be a description of the command executed.
*
* The default value is an empty string.
*/
commandDialog? : string | CommandFunc<string>
}

/**
Expand Down Expand Up @@ -1311,6 +1340,7 @@ namespace Private {
readonly isToggled: CommandFunc<boolean>;
readonly isToggleable: boolean;
readonly isVisible: CommandFunc<boolean>;
readonly commandDialog : CommandFunc<string>;
}

/**
Expand Down Expand Up @@ -1345,7 +1375,8 @@ namespace Private {
isEnabled: options.isEnabled || trueFunc,
isToggled: options.isToggled || falseFunc,
isToggleable: options.isToggleable || !!options.isToggled,
isVisible: options.isVisible || trueFunc
isVisible: options.isVisible || trueFunc,
commandDialog: asFunc(options.commandDialog, emptyStringFunc)
};
}

Expand Down
14 changes: 14 additions & 0 deletions packages/virtualdom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,11 @@ export type ElementSpecialAttrs = {
*/
readonly className?: string;

/**
* The dialog text for the command dialog.
*/
readonly dialogText?: string;

/**
* The JS-safe name for the HTML `for` attribute.
*/
Expand Down Expand Up @@ -1058,6 +1063,7 @@ export namespace h {
export const dfn: IFactory = h.bind(undefined, 'dfn');
export const div: IFactory = h.bind(undefined, 'div');
export const dl: IFactory = h.bind(undefined, 'dl');
export const dialog: IFactory = h.bind(undefined, 'dialog');
export const dt: IFactory = h.bind(undefined, 'dt');
export const em: IFactory = h.bind(undefined, 'em');
export const embed: IFactory = h.bind(undefined, 'embed');
Expand Down Expand Up @@ -1490,6 +1496,7 @@ namespace Private {
key: true,
className: true,
htmlFor: true,
dialogText: true,
dataset: true,
style: true
};
Expand All @@ -1515,6 +1522,13 @@ namespace Private {
element.setAttribute('class', attrs.className);
}

// Set the aria live and ID for the command dialog
if (attrs.dialogText !== undefined) {
element.setAttribute('aria-live', 'assertive');
element.setAttribute('role', 'alert')
element.setAttribute("id", `${attrs.dialogText}`.trim())
}

// Add the element `for` attribute.
if (attrs.htmlFor !== undefined) {
element.setAttribute('for', attrs.htmlFor);
Expand Down
25 changes: 24 additions & 1 deletion packages/widgets/src/commandpalette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,11 @@ export namespace CommandPalette {
*/
readonly command: string;

/**
* The description of the command for the screen reader.
*/
readonly commandDialog: string;

/**
* The arguments for the command.
*/
Expand Down Expand Up @@ -786,6 +791,7 @@ export namespace CommandPalette {
role: 'menuitemcheckbox',
'aria-checked': `${data.item.isToggled}`
},
this.renderItemAlert(data),
this.renderItemIcon(data),
this.renderItemContent(data),
this.renderItemShortcut(data)
Expand All @@ -797,6 +803,7 @@ export namespace CommandPalette {
dataset,
role: 'menuitem'
},
this.renderItemAlert(data),
this.renderItemIcon(data),
this.renderItemContent(data),
this.renderItemShortcut(data)
Expand Down Expand Up @@ -853,7 +860,7 @@ export namespace CommandPalette {
*/
renderItemLabel(data: IItemRenderData): VirtualElement {
let content = this.formatItemLabel(data);
return h.div({ className: 'lm-CommandPalette-itemLabel' }, content);
return h.div({ className: 'lm-CommandPalette-itemLabel', 'aria-live': "assertive", "aria-label": `${content}`, 'id': `${content}`.toLowerCase().replace(/ /g, '') }, content);
m158261 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand All @@ -868,6 +875,11 @@ export namespace CommandPalette {
return h.div({ className: 'lm-CommandPalette-itemCaption' }, content);
}

renderItemAlert(data: IItemRenderData): VirtualElement {
let content = this.formatAlertDialog(data);
return h.dialog({ dialogText: ` ${content} `})
}

/**
* Render the shortcut for a command palette item.
*
Expand Down Expand Up @@ -997,6 +1009,10 @@ export namespace CommandPalette {
formatItemCaption(data: IItemRenderData): h.Child {
return data.item.caption;
}

formatAlertDialog(data: IItemRenderData): h.Child {
return data.item.commandDialog;
}
}

/**
Expand Down Expand Up @@ -1462,6 +1478,13 @@ namespace Private {
*/
readonly rank: number;

/**
* The command dialog text for the command item.
*/
get commandDialog(): string {
return this._commands.commandDialog(this.command, this.args);
}

/**
* The display label for the command item.
*/
Expand Down
Loading