diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 1a8ac09277c..d42777bec4b 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -41,9 +41,11 @@ export interface IListViewDragAndDrop extends IListDragAndDrop { getDragElements(element: T): T[]; } -export interface IAriaSetProvider { +export interface IAriaProvider { getSetSize(element: T, index: number, listLength: number): number; getPosInSet(element: T, index: number): number; + getRole?(element: T): string; + isChecked?(element: T): boolean; } export interface IListViewOptions { @@ -54,7 +56,7 @@ export interface IListViewOptions { readonly supportDynamicHeights?: boolean; readonly mouseSupport?: boolean; readonly horizontalScrolling?: boolean; - readonly ariaSetProvider?: IAriaSetProvider; + readonly ariaProvider?: IAriaProvider; } const DefaultOptions = { @@ -174,7 +176,7 @@ export class ListView implements ISpliceable, IDisposable { private setRowLineHeight: boolean; private supportDynamicHeights: boolean; private horizontalScrolling: boolean; - private ariaSetProvider: IAriaSetProvider; + private ariaProvider: IAriaProvider; private scrollWidth: number | undefined; private canUseTranslate3d: boolean | undefined = undefined; @@ -227,7 +229,7 @@ export class ListView implements ISpliceable, IDisposable { this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling); DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling); - this.ariaSetProvider = options.ariaSetProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 }; + this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 }; this.rowsContainer = document.createElement('div'); this.rowsContainer.className = 'monaco-list-rows'; @@ -566,7 +568,12 @@ export class ListView implements ISpliceable, IDisposable { if (!item.row) { item.row = this.cache.alloc(item.templateId); - item.row!.domNode!.setAttribute('role', 'treeitem'); + const role = this.ariaProvider.getRole ? this.ariaProvider.getRole(item.element) : 'treeitem'; + item.row!.domNode!.setAttribute('role', role); + const checked = this.ariaProvider.isChecked ? this.ariaProvider.isChecked(item.element) : undefined; + if (typeof checked !== 'undefined') { + item.row!.domNode!.setAttribute('aria-checked', String(checked)); + } } if (!item.row.domNode!.parentElement) { @@ -634,8 +641,8 @@ export class ListView implements ISpliceable, IDisposable { item.row!.domNode!.setAttribute('data-index', `${index}`); item.row!.domNode!.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false'); - item.row!.domNode!.setAttribute('aria-setsize', String(this.ariaSetProvider.getSetSize(item.element, index, this.length))); - item.row!.domNode!.setAttribute('aria-posinset', String(this.ariaSetProvider.getPosInSet(item.element, index))); + item.row!.domNode!.setAttribute('aria-setsize', String(this.ariaProvider.getSetSize(item.element, index, this.length))); + item.row!.domNode!.setAttribute('aria-posinset', String(this.ariaProvider.getPosInSet(item.element, index))); item.row!.domNode!.setAttribute('id', this.getElementDomId(index)); DOM.toggleClass(item.row!.domNode!, 'drop-target', item.dropTarget); diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 55ac74bc01c..0e0a4df34bc 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -17,7 +17,7 @@ import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardE import { Event, Emitter, EventBufferer } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole } from './list'; -import { ListView, IListViewOptions, IListViewDragAndDrop, IAriaSetProvider } from './listView'; +import { ListView, IListViewOptions, IListViewDragAndDrop, IAriaProvider } from './listView'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; @@ -831,7 +831,7 @@ export interface IListOptions extends IListStyles { readonly supportDynamicHeights?: boolean; readonly mouseSupport?: boolean; readonly horizontalScrolling?: boolean; - readonly ariaSetProvider?: IAriaSetProvider; + readonly ariaProvider?: IAriaProvider; } export interface IListStyles { diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index dad7d26545a..a034736f2f5 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -153,7 +153,7 @@ function asListOptions(modelProvider: () => ITreeModel(options?: IAsyncDataTreeOpt e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T) ) ), - ariaSetProvider: undefined + ariaProvider: undefined }; } diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 38fe05f0eb0..e0fa0e6c9f3 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -76,7 +76,13 @@ export class BreakpointsView extends ViewletPanel { ], { identityProvider: { getId: (element: IEnablement) => element.getId() }, multipleSelectionSupport: false, - keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IEnablement) => e } + keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IEnablement) => e }, + ariaProvider: { + getSetSize: (_: IEnablement, index: number, listLength: number) => listLength, + getPosInSet: (_: IEnablement, index: number) => index, + getRole: (breakpoint: IEnablement) => 'checkbox', + isChecked: (breakpoint: IEnablement) => breakpoint.enabled + } }) as WorkbenchList; CONTEXT_BREAKPOINTS_FOCUSED.bindTo(this.list.contextKeyService);