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

Add AriaRole type to help select valid aria roles #168538

Merged
merged 1 commit into from Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 74 additions & 0 deletions src/vs/base/browser/ui/aria/aria.ts
Expand Up @@ -93,3 +93,77 @@ function insertMessage(target: HTMLElement, msg: string): void {
target.style.visibility = 'hidden';
target.style.visibility = 'visible';
}

// Copied from @types/react which original came from https://www.w3.org/TR/wai-aria-1.1/#role_definitions
export type AriaRole =
| 'alert'
| 'alertdialog'
| 'application'
| 'article'
| 'banner'
| 'button'
| 'cell'
| 'checkbox'
| 'columnheader'
| 'combobox'
| 'complementary'
| 'contentinfo'
| 'definition'
| 'dialog'
| 'directory'
| 'document'
| 'feed'
| 'figure'
| 'form'
| 'grid'
| 'gridcell'
| 'group'
| 'heading'
| 'img'
| 'link'
| 'list'
| 'listbox'
| 'listitem'
| 'log'
| 'main'
| 'marquee'
| 'math'
| 'menu'
| 'menubar'
| 'menuitem'
| 'menuitemcheckbox'
| 'menuitemradio'
| 'navigation'
| 'none'
| 'note'
| 'option'
| 'presentation'
| 'progressbar'
| 'radio'
| 'radiogroup'
| 'region'
| 'row'
| 'rowgroup'
| 'rowheader'
| 'scrollbar'
| 'search'
| 'searchbox'
| 'separator'
| 'slider'
| 'spinbutton'
| 'status'
| 'switch'
| 'tab'
| 'table'
| 'tablist'
| 'tabpanel'
| 'term'
| 'textbox'
| 'timer'
| 'toolbar'
| 'tooltip'
| 'tree'
| 'treegrid'
| 'treeitem'
| (string & {}) // Prevent type collapsing to `string`
;
5 changes: 3 additions & 2 deletions src/vs/base/browser/ui/list/listView.ts
Expand Up @@ -22,6 +22,7 @@ import { RangeMap, shift } from 'vs/base/browser/ui/list/rangeMap';
import { IRow, RowCache } from 'vs/base/browser/ui/list/rowCache';
import { IObservableValue } from 'vs/base/common/observableValue';
import { BugIndicatingError } from 'vs/base/common/errors';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';

interface IItem<T> {
readonly id: string;
Expand Down Expand Up @@ -49,7 +50,7 @@ export interface IListViewDragAndDrop<T> extends IListDragAndDrop<T> {
export interface IListViewAccessibilityProvider<T> {
getSetSize?(element: T, index: number, listLength: number): number;
getPosInSet?(element: T, index: number): number;
getRole?(element: T): string | undefined;
getRole?(element: T): AriaRole | undefined;
isChecked?(element: T): boolean | IObservableValue<boolean> | undefined;
}

Expand Down Expand Up @@ -179,7 +180,7 @@ class ListViewAccessibilityProvider<T> implements Required<IListViewAccessibilit

readonly getSetSize: (element: any, index: number, listLength: number) => number;
readonly getPosInSet: (element: any, index: number) => number;
readonly getRole: (element: T) => string | undefined;
readonly getRole: (element: T) => AriaRole | undefined;
readonly isChecked: (element: T) => boolean | IObservableValue<boolean> | undefined;

constructor(accessibilityProvider?: IListViewAccessibilityProvider<T>) {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/base/browser/ui/list/listWidget.ts
Expand Up @@ -8,7 +8,7 @@ import { createStyleSheet, Dimension, EventHelper } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Gesture } from 'vs/base/browser/touch';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { alert, AriaRole } from 'vs/base/browser/ui/aria/aria';
import { CombinedSpliceable } from 'vs/base/browser/ui/list/splice';
import { ScrollableElementChangeOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import { binarySearch, firstOrDefault, range } from 'vs/base/common/arrays';
Expand Down Expand Up @@ -782,7 +782,7 @@ export interface IStyleController {
export interface IListAccessibilityProvider<T> extends IListViewAccessibilityProvider<T> {
getAriaLabel(element: T): string | null;
getWidgetAriaLabel(): string;
getWidgetRole?(): string;
getWidgetRole?(): AriaRole;
getAriaLevel?(element: T): number | undefined;
onDidChangeActiveDescendant?: Event<void>;
getActiveDescendantId?(element: T): string | undefined;
Expand Down
3 changes: 2 additions & 1 deletion src/vs/base/parts/quickinput/browser/quickInputList.ts
Expand Up @@ -6,6 +6,7 @@
import * as dom from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';
import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
Expand Down Expand Up @@ -865,7 +866,7 @@ class QuickInputAccessibilityProvider implements IListAccessibilityProvider<List
: element.saneAriaLabel;
}

getWidgetRole() {
getWidgetRole(): AriaRole {
return 'listbox';
}

Expand Down
Expand Up @@ -20,6 +20,7 @@ import { assertIsDefined, assertAllDefined } from 'vs/base/common/types';
import { Codicon } from 'vs/base/common/codicons';
import { NotificationFocusedContext } from 'vs/workbench/common/contextkeys';
import { Disposable } from 'vs/base/common/lifecycle';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';

export interface INotificationsListOptions extends IListOptions<INotificationViewItem> {
widgetAriaLabel?: string;
Expand Down Expand Up @@ -105,7 +106,7 @@ export class NotificationsList extends Disposable {
getWidgetAriaLabel(): string {
return options.widgetAriaLabel ?? localize('notificationsList', "Notifications List");
},
getRole(): string {
getRole(): AriaRole {
return 'dialog'; // https://github.com/microsoft/vscode/issues/82728
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/browser/parts/views/treeView.ts
Expand Up @@ -67,6 +67,7 @@ import { CodeDataTransfers } from 'vs/platform/dnd/browser/dnd';
import { addExternalEditorsDropData, toVSDataTransfer } from 'vs/editor/browser/dnd';
import { CheckboxStateHandler, TreeItemCheckbox } from 'vs/workbench/browser/parts/views/checkbox';
import { setTimeout0 } from 'vs/base/common/platform';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';

export class TreeViewPane extends ViewPane {

Expand Down Expand Up @@ -646,7 +647,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
return buildAriaLabel;
}
},
getRole(element: ITreeItem): string | undefined {
getRole(element: ITreeItem): AriaRole | undefined {
return element.accessibilityInformation?.role ?? 'treeitem';
},
getWidgetAriaLabel(): string {
Expand Down
Expand Up @@ -30,6 +30,7 @@ import { ILanguageConfigurationService } from 'vs/editor/common/languages/langua
import { ILanguageService } from 'vs/editor/common/languages/language';
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';

// --- VIEW MODEL

Expand Down Expand Up @@ -285,7 +286,7 @@ export class BulkEditAccessibilityProvider implements IListAccessibilityProvider
return localize('bulkEdit', "Bulk Edit");
}

getRole(_element: BulkEditElement): string {
getRole(_element: BulkEditElement): AriaRole {
return 'checkbox';
}

Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/debug/browser/breakpointsView.ts
Expand Up @@ -7,6 +7,7 @@ import * as dom from 'vs/base/browser/dom';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Gesture } from 'vs/base/browser/touch';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';
import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { IListContextMenuEvent, IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
Expand Down Expand Up @@ -1010,7 +1011,7 @@ class BreakpointsAccessibilityProvider implements IListAccessibilityProvider<Bre
return localize('breakpoints', "Breakpoints");
}

getRole() {
getRole(): AriaRole {
return 'checkbox';
}

Expand Down
5 changes: 3 additions & 2 deletions src/vs/workbench/contrib/debug/browser/callStackView.ts
Expand Up @@ -5,6 +5,7 @@

import * as dom from 'vs/base/browser/dom';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
Expand Down Expand Up @@ -1042,12 +1043,12 @@ class CallStackAccessibilityProvider implements IListAccessibilityProvider<CallS
return localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel' }, "Debug Call Stack");
}

getWidgetRole(): string {
getWidgetRole(): AriaRole {
// Use treegrid as a role since each element can have additional actions inside #146210
return 'treegrid';
}

getRole(_element: CallStackItem): string | undefined {
getRole(_element: CallStackItem): AriaRole | undefined {
return 'row';
}

Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/timeline/browser/timelinePane.ts
Expand Up @@ -53,6 +53,7 @@ import { IHoverDelegate, IHoverDelegateOptions } from 'vs/base/browser/ui/iconLa
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { AriaRole } from 'vs/base/browser/ui/aria/aria';

const ItemHeight = 22;

Expand Down Expand Up @@ -914,7 +915,7 @@ export class TimelinePane extends ViewPane {
}
return element.accessibilityInformation ? element.accessibilityInformation.label : localize('timeline.aria.item', "{0}: {1}", element.relativeTimeFullWord ?? '', element.label);
},
getRole(element: TreeElement): string {
getRole(element: TreeElement): AriaRole {
if (isLoadMoreCommand(element)) {
return 'treeitem';
}
Expand Down