未验证 提交 aa0b9cd1 编写于 作者: I Isidor Nikolic 提交者: GitHub

Merge pull request #95877 from microsoft/isidorn/listWidgetAriaLabel

list: accessibility 
......@@ -78,6 +78,10 @@ class PagedAccessibilityProvider<T> implements IListAccessibilityProvider<number
private accessibilityProvider: IListAccessibilityProvider<T>
) { }
getWidgetAriaLabel(): string {
return this.accessibilityProvider.getWidgetAriaLabel();
}
getAriaLabel(index: number): string | null {
const model = this.modelProvider();
......
......@@ -688,6 +688,8 @@ export interface IStyleController {
export interface IListAccessibilityProvider<T> extends IListViewAccessibilityProvider<T> {
getAriaLabel(element: T): string | null;
getWidgetAriaLabel(): string;
getWidgetRole?(): string;
getAriaLevel?(element: T): number | undefined;
onDidChangeActiveDescendant?: Event<void>;
getActiveDescendantId?(element: T): string | undefined;
......@@ -820,8 +822,6 @@ export interface IListOptions<T> {
readonly automaticKeyboardNavigation?: boolean;
readonly keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider<T>;
readonly keyboardNavigationDelegate?: IKeyboardNavigationDelegate;
readonly ariaRole?: string;
readonly ariaLabel?: string;
readonly keyboardSupport?: boolean;
readonly multipleSelectionSupport?: boolean;
readonly multipleSelectionController?: IMultipleSelectionController<T>;
......@@ -1106,6 +1106,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private styleController: IStyleController;
private typeLabelController?: TypeLabelController<T>;
private accessibilityProvider?: IListAccessibilityProvider<T>;
private _ariaLabel: string = '';
protected readonly disposables = new DisposableStore();
......@@ -1184,7 +1185,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
renderers: IListRenderer<any /* TODO@joao */, any>[],
private _options: IListOptions<T> = DefaultOptions
) {
this.selection = new SelectionTrait(this._options.ariaRole !== 'listbox');
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
this.selection = new SelectionTrait(role !== 'listbox');
this.focus = new Trait('focused');
mixin(_options, defaultStyles, false);
......@@ -1209,7 +1211,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
};
this.view = new ListView(container, virtualDelegate, renderers, viewOptions);
this.view.domNode.setAttribute('role', _options.ariaRole ?? 'list');
this.view.domNode.setAttribute('role', role);
if (_options.styleController) {
this.styleController = _options.styleController(this.view.domId);
......@@ -1250,8 +1252,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this.onDidChangeFocus(this._onFocusChange, this, this.disposables);
this.onDidChangeSelection(this._onSelectionChange, this, this.disposables);
if (_options.ariaLabel) {
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", _options.ariaLabel));
if (this.accessibilityProvider) {
this.ariaLabel = this.accessibilityProvider.getWidgetAriaLabel();
}
if (_options.multipleSelectionSupport) {
this.view.domNode.setAttribute('aria-multiselectable', 'true');
......@@ -1354,6 +1356,15 @@ export class List<T> implements ISpliceable<T>, IDisposable {
return this.view.lastVisibleIndex;
}
get ariaLabel(): string {
return this._ariaLabel;
}
set ariaLabel(value: string) {
this._ariaLabel = value;
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", value));
}
domFocus(): void {
this.view.domNode.focus();
}
......
......@@ -20,6 +20,7 @@ import { ISelectBoxDelegate, ISelectOptionItem, ISelectBoxOptions, ISelectBoxSty
import { isMacintosh } from 'vs/base/common/platform';
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
import { IContentActionHandler } from 'vs/base/browser/formattedTextRenderer';
import { localize } from 'vs/nls';
const $ = dom.$;
......@@ -720,12 +721,20 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.listRenderer = new SelectListRenderer();
this.selectList = new List('SelectBoxCustom', this.selectDropDownListContainer, this, [this.listRenderer], {
ariaLabel: this.selectBoxOptions.ariaLabel,
useShadows: false,
verticalScrollMode: ScrollbarVisibility.Visible,
keyboardSupport: false,
mouseSupport: false
mouseSupport: false,
accessibilityProvider: {
getAriaLabel: (element) => element.text,
getWidgetAriaLabel: () => localize('selectBox', "Select Box"),
getRole: () => 'option',
getWidgetRole: () => 'listbox'
}
});
if (this.selectBoxOptions.ariaLabel) {
this.selectList.ariaLabel = this.selectBoxOptions.ariaLabel;
}
// SetUp list keyboard controller - control navigation, disabled items, focus
const onSelectDropDownKeyDown = Event.chain(domEvent(this.selectDropDownListContainer, 'keydown'))
......
......@@ -189,6 +189,10 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element);
},
getWidgetAriaLabel() {
return options.accessibilityProvider!.getWidgetAriaLabel();
},
getWidgetRole: options.accessibilityProvider && options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',
getAriaLevel(node) {
return node.depth;
},
......@@ -202,8 +206,7 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(node.element);
}
},
enableKeyboardNavigation: options.simpleKeyboardNavigation,
ariaRole: 'tree'
enableKeyboardNavigation: options.simpleKeyboardNavigation
};
}
......@@ -1454,6 +1457,14 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
return node.element;
}
get ariaLabel(): string {
return this.view.ariaLabel;
}
set ariaLabel(value: string) {
this.view.ariaLabel = value;
}
domFocus(): void {
this.view.domFocus();
}
......
......@@ -242,6 +242,10 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element as T);
},
getWidgetAriaLabel() {
return options.accessibilityProvider!.getWidgetAriaLabel();
},
getWidgetRole: options.accessibilityProvider!.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',
getAriaLevel: options.accessibilityProvider!.getAriaLevel && (node => {
return options.accessibilityProvider!.getAriaLevel!(node.element as T);
}),
......@@ -266,7 +270,6 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
)
),
ariaRole: 'tree',
additionalScrollHeight: options.additionalScrollHeight
};
}
......@@ -442,6 +445,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.lastVisibleElement!.element as T;
}
get ariaLabel(): string {
return this.tree.ariaLabel;
}
set ariaLabel(value: string) {
this.tree.ariaLabel = value;
}
domFocus(): void {
this.tree.domFocus();
}
......
......@@ -27,6 +27,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
import { IQuickInputOptions } from 'vs/base/parts/quickinput/browser/quickInput';
import { IListOptions, List, IListStyles, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { localize } from 'vs/nls';
const $ = dom.$;
......@@ -286,8 +287,7 @@ export class QuickInputList {
setRowLineHeight: false,
multipleSelectionSupport: false,
horizontalScrolling: false,
accessibilityProvider,
ariaRole: 'listbox'
accessibilityProvider
} as IListOptions<ListElement>);
this.list.getHTMLElement().id = id;
this.disposables.push(this.list);
......@@ -714,10 +714,18 @@ function compareEntries(elementA: ListElement, elementB: ListElement, lookFor: s
class QuickInputAccessibilityProvider implements IListAccessibilityProvider<ListElement> {
getWidgetAriaLabel(): string {
return localize('quickInput', "Quick Input");
}
getAriaLabel(element: ListElement): string | null {
return element.saneAriaLabel;
}
getWidgetRole() {
return 'listbox';
}
getRole() {
return 'option';
}
......
......@@ -42,6 +42,12 @@ export class OutlineNavigationLabelProvider implements IKeyboardNavigationLabelP
export class OutlineAccessibilityProvider implements IListAccessibilityProvider<OutlineItem> {
constructor(private readonly ariaLabel: string) { }
getWidgetAriaLabel(): string {
return this.ariaLabel;
}
getAriaLabel(element: OutlineItem): string | null {
if (element instanceof OutlineGroup) {
return element.label;
......
......@@ -215,6 +215,10 @@ export class OneReferenceRenderer implements ITreeRenderer<OneReference, FuzzySc
export class AccessibilityProvider implements IListAccessibilityProvider<FileReferences | OneReference> {
getWidgetAriaLabel(): string {
return localize('treeAriaLabel', "References");
}
getAriaLabel(element: FileReferences | OneReference): string | null {
return element.ariaMessage;
}
......
......@@ -311,7 +311,6 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
// tree
this._treeContainer = dom.append(containerElement, dom.$('div.ref-tree.inline'));
const treeOptions: IWorkbenchAsyncDataTreeOptions<TreeElement, FuzzyScore> = {
ariaLabel: nls.localize('treeAriaLabel', "References"),
keyboardSupport: this._defaultTreeKeyboardSupport,
accessibilityProvider: new AccessibilityProvider(),
keyboardNavigationLabelProvider: this._instantiationService.createInstance(StringRepresentationProvider),
......
......@@ -607,7 +607,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
useShadows: false,
openController: { shouldOpen: () => false },
mouseSupport: false,
ariaRole: 'listbox',
accessibilityProvider: {
getRole: () => 'option',
getAriaLabel: (item: CompletionItem) => {
......@@ -623,7 +622,9 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
} else {
return textLabel;
}
}
},
getWidgetAriaLabel: () => nls.localize('suggest', "Suggest"),
getWidgetRole: () => 'listbox'
}
});
......
......@@ -31,6 +31,7 @@ import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvid
import { IFileIconTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IModeService } from 'vs/editor/common/services/modeService';
import { localize } from 'vs/nls';
export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker {
return element instanceof FileElement
......@@ -276,6 +277,10 @@ class FileNavigationLabelProvider implements IKeyboardNavigationLabelProvider<IW
class FileAccessibilityProvider implements IListAccessibilityProvider<IWorkspaceFolder | IFileStat> {
getWidgetAriaLabel(): string {
return localize('breadcrumbs', "Breadcrumbs");
}
getAriaLabel(element: IWorkspaceFolder | IFileStat): string | null {
return element.name;
}
......@@ -475,7 +480,7 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker {
sorter: this._outlineComparator,
identityProvider: new OutlineIdentityProvider(),
keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(),
accessibilityProvider: new OutlineAccessibilityProvider(),
accessibilityProvider: new OutlineAccessibilityProvider(localize('breadcrumbs', "Breadcrumbs")),
filter: this._instantiationService.createInstance(OutlineFilter, 'breadcrumbs')
}
);
......
......@@ -157,10 +157,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente
notificationsToolBar.push(hideAllAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(hideAllAction) });
// Notifications List
this.notificationsList = this.instantiationService.createInstance(NotificationsList, this.notificationsCenterContainer, {
ariaLabel: localize('notificationsList', "Notifications List")
});
this.notificationsList = this.instantiationService.createInstance(NotificationsList, this.notificationsCenterContainer, {});
this.container.appendChild(this.notificationsCenterContainer);
}
......
......@@ -97,6 +97,9 @@ export class NotificationsList extends Themable {
}
return localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", element.message.raw, element.source);
},
getWidgetAriaLabel(): string {
return localize('notificationsList', "Notifications List");
}
}
}
......
......@@ -17,7 +17,6 @@ import { widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { NotificationsToastsVisibleContext, INotificationsToastController } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { localize } from 'vs/nls';
import { Severity, NotificationsFilter } from 'vs/platform/notification/common/notification';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
......@@ -171,7 +170,6 @@ export class NotificationsToasts extends Themable implements INotificationsToast
// Create toast with item and show
const notificationList = this.instantiationService.createInstance(NotificationsList, notificationToast, {
ariaRole: 'dialog', // https://github.com/microsoft/vscode/issues/82728
ariaLabel: localize('notificationsToast', "Notification Toast"),
verticalScrollMode: ScrollbarVisibility.Hidden
});
itemDisposables.add(notificationList);
......
......@@ -418,6 +418,7 @@ export class TreeView extends Disposable implements ITreeView {
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.id }, () => task));
const aligner = new Aligner(this.themeService);
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner);
const widgetAriaLabel = this._title;
this.tree = this._register(this.instantiationService.createInstance(Tree, this.id, this.treeContainer, new TreeViewDelegate(), [renderer],
dataSource, {
......@@ -425,9 +426,11 @@ export class TreeView extends Disposable implements ITreeView {
accessibilityProvider: {
getAriaLabel(element: ITreeItem): string {
return element.tooltip ? element.tooltip : element.label ? element.label.label : '';
},
getWidgetAriaLabel(): string {
return widgetAriaLabel;
}
},
ariaLabel: this._title,
keyboardNavigationLabelProvider: {
getKeyboardNavigationLabel: (item: ITreeItem) => {
return item.label ? item.label.label : (item.resourceUri ? basename(URI.revive(item.resourceUri)) : undefined);
......
......@@ -276,6 +276,10 @@ export class BulkEditAccessibilityProvider implements IListAccessibilityProvider
constructor(@ILabelService private readonly _labelService: ILabelService) { }
getWidgetAriaLabel(): string {
return localize('bulkEdit', "Bulk Edit");
}
getRole(_element: BulkEditElement): string {
return 'checkbox';
}
......
......@@ -201,7 +201,6 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
sorter: new callHTree.Sorter(),
accessibilityProvider: new callHTree.AccessibilityProvider(() => this._direction),
identityProvider: new callHTree.IdentityProvider(() => this._direction),
ariaLabel: localize('tree.aria', "Call Hierarchy"),
expandOnlyOnTwistieClick: true,
overrideStyles: {
listBackground: peekView.peekViewResultsBackground
......
......@@ -147,6 +147,10 @@ export class AccessibilityProvider implements IListAccessibilityProvider<Call> {
public getDirection: () => CallHierarchyDirection
) { }
getWidgetAriaLabel(): string {
return localize('tree.aria', "Call Hierarchy");
}
getAriaLabel(element: Call): string | null {
if (this.getDirection() === CallHierarchyDirection.CallsFrom) {
return localize('from', "calls from {0}", element.item.name);
......
......@@ -201,9 +201,11 @@ export class CommentsList extends WorkbenchAsyncDataTree<any, any> {
);
}
return '';
},
getWidgetAriaLabel(): string {
return COMMENTS_VIEW_TITLE;
}
},
ariaLabel: COMMENTS_VIEW_TITLE,
keyboardSupport: true,
identityProvider: {
getId: (element: any) => {
......
......@@ -623,6 +623,10 @@ class BreakpointsAccessibilityProvider implements IListAccessibilityProvider<Bre
constructor(private readonly debugService: IDebugService) { }
getWidgetAriaLabel(): string {
return nls.localize('breakpoints', "Breakpoints");
}
getRole() {
return 'checkbox';
}
......
......@@ -180,7 +180,6 @@ export class CallStackView extends ViewPane {
new ShowMoreRenderer(this.themeService)
], this.dataSource, {
accessibilityProvider: new CallStackAccessibilityProvider(),
ariaLabel: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel' }, "Debug Call Stack"),
identityProvider: {
getId: (element: CallStackItem) => {
if (typeof element === 'string') {
......@@ -813,6 +812,11 @@ class CallStackDataSource implements IAsyncDataSource<IDebugModel, CallStackItem
}
class CallStackAccessibilityProvider implements IListAccessibilityProvider<CallStackItem> {
getWidgetAriaLabel(): string {
return nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel' }, "Debug Call Stack");
}
getAriaLabel(element: CallStackItem): string {
if (element instanceof Thread) {
return nls.localize('threadAriaLabel', "Thread {0}, callstack, debug", (<Thread>element).name);
......
......@@ -105,7 +105,6 @@ export class DebugHoverWidget implements IContentWidget {
this.tree = <WorkbenchAsyncDataTree<IExpression, IExpression, any>>this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'DebugHover', this.treeContainer, new DebugHoverDelegate(), [this.instantiationService.createInstance(VariablesRenderer)],
dataSource, {
ariaLabel: nls.localize('treeAriaLabel', "Debug Hover"),
accessibilityProvider: new DebugHoverAccessibilityProvider(),
mouseSupport: false,
horizontalScrolling: true,
......@@ -336,6 +335,11 @@ export class DebugHoverWidget implements IContentWidget {
}
class DebugHoverAccessibilityProvider implements IListAccessibilityProvider<IExpression> {
getWidgetAriaLabel(): string {
return nls.localize('treeAriaLabel', "Debug Hover");
}
getAriaLabel(element: IExpression): string {
return nls.localize('variableAriaLabel', "{0} value {1}, variables, debug", element.name, element.value);
}
......
......@@ -473,7 +473,6 @@ export class LoadedScriptsView extends ViewPane {
},
filter: this.filter,
accessibilityProvider: new LoadedSciptsAccessibilityProvider(),
ariaLabel: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'loadedScriptsAriaLabel' }, "Debug Loaded Scripts"),
overrideStyles: {
listBackground: this.getBackgroundColor()
}
......@@ -711,6 +710,10 @@ class LoadedScriptsRenderer implements ICompressibleTreeRenderer<BaseTreeItem, F
class LoadedSciptsAccessibilityProvider implements IListAccessibilityProvider<LoadedScriptsItem> {
getWidgetAriaLabel(): string {
return nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'loadedScriptsAriaLabel' }, "Debug Loaded Scripts");
}
getAriaLabel(element: LoadedScriptsItem): string {
if (element instanceof RootFolderTreeItem) {
......
......@@ -531,7 +531,6 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
// https://github.com/microsoft/TypeScript/issues/32526
new ReplDataSource() as IAsyncDataSource<IDebugSession, IReplElement>,
{
ariaLabel: localize('replAriaLabel', "Read Eval Print Loop Panel"),
accessibilityProvider: new ReplAccessibilityProvider(),
identityProvider: { getId: (element: IReplElement) => element.getId() },
mouseSupport: false,
......
......@@ -367,6 +367,11 @@ export class ReplDataSource implements IAsyncDataSource<IDebugSession, IReplElem
}
export class ReplAccessibilityProvider implements IListAccessibilityProvider<IReplElement> {
getWidgetAriaLabel(): string {
return localize('debugConsole', "Debug Console");
}
getAriaLabel(element: IReplElement): string {
if (element instanceof Variable) {
return localize('replVariableAriaLabel', "Variable {0} has value {1}, read eval print loop, debug", element.name, element.value);
......
......@@ -102,7 +102,6 @@ export class VariablesView extends ViewPane {
this.tree = <WorkbenchAsyncDataTree<IViewModel | IExpression | IScope, IExpression | IScope, FuzzyScore>>this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'VariablesView', treeContainer, new VariablesDelegate(),
[this.instantiationService.createInstance(VariablesRenderer), new ScopesRenderer(), new ScopeErrorRenderer()],
new VariablesDataSource(), {
ariaLabel: nls.localize('variablesAriaTreeLabel', "Debug Variables"),
accessibilityProvider: new VariablesAccessibilityProvider(),
identityProvider: { getId: (element: IExpression | IScope) => element.getId() },
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IExpression | IScope) => e },
......@@ -350,6 +349,11 @@ export class VariablesRenderer extends AbstractExpressionsRenderer {
}
class VariablesAccessibilityProvider implements IListAccessibilityProvider<IExpression | IScope> {
getWidgetAriaLabel(): string {
return nls.localize('variablesAriaTreeLabel', "Debug Variables");
}
getAriaLabel(element: IExpression | IScope): string | null {
if (element instanceof Scope) {
return nls.localize('variableScopeAriaLabel', "Scope {0}, variables, debug", element.name);
......
......@@ -76,7 +76,6 @@ export class WatchExpressionsView extends ViewPane {
const expressionsRenderer = this.instantiationService.createInstance(WatchExpressionsRenderer);
this.tree = <WorkbenchAsyncDataTree<IDebugService | IExpression, IExpression, FuzzyScore>>this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'WatchExpressions', treeContainer, new WatchExpressionsDelegate(), [expressionsRenderer, this.instantiationService.createInstance(VariablesRenderer)],
new WatchExpressionsDataSource(), {
ariaLabel: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel' }, "Debug Watch Expressions"),
accessibilityProvider: new WatchExpressionsAccessibilityProvider(),
identityProvider: { getId: (element: IExpression) => element.getId() },
keyboardNavigationLabelProvider: {
......@@ -94,7 +93,6 @@ export class WatchExpressionsView extends ViewPane {
listBackground: this.getBackgroundColor()
}
});
this.tree.setInput(this.debugService);
CONTEXT_WATCH_EXPRESSIONS_FOCUSED.bindTo(this.tree.contextKeyService);
......@@ -298,6 +296,11 @@ export class WatchExpressionsRenderer extends AbstractExpressionsRenderer {
}
class WatchExpressionsAccessibilityProvider implements IListAccessibilityProvider<IExpression> {
getWidgetAriaLabel(): string {
return nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel' }, "Debug Watch Expressions");
}
getAriaLabel(element: IExpression): string {
if (element instanceof Expression) {
return nls.localize('watchExpressionAriaLabel', "{0} value {1}, watch, debug", (<Expression>element).name, (<Expression>element).value);
......
......@@ -272,6 +272,9 @@ export class ExtensionsTree extends WorkbenchAsyncDataTree<IExtensionData, IExte
accessibilityProvider: <IListAccessibilityProvider<IExtensionData>>{
getAriaLabel(extensionData: IExtensionData): string {
return localize('extension-arialabel', "{0}. Press enter for extension details.", extensionData.extension.displayName);
},
getWidgetAriaLabel(): string {
return localize('extensions', "Extensions");
}
}
},
......
......@@ -137,13 +137,15 @@ export class ExtensionsListView extends ViewPane {
const extensionsViewState = new ExtensionsViewState();
const renderer = this.instantiationService.createInstance(Renderer, extensionsViewState);
this.list = this.instantiationService.createInstance<typeof WorkbenchPagedList, WorkbenchPagedList<IExtension>>(WorkbenchPagedList, 'Extensions', extensionsList, delegate, [renderer], {
ariaLabel: localize('extensions', "Extensions"),
multipleSelectionSupport: false,
setRowLineHeight: false,
horizontalScrolling: false,
accessibilityProvider: <IListAccessibilityProvider<IExtension | null>>{
getAriaLabel(extension: IExtension | null): string {
return extension ? localize('extension-arialabel', "{0}. Press enter for extension details.", extension.displayName) : '';
},
getWidgetAriaLabel(): string {
return localize('extensions', "Extensions");
}
},
overrideStyles: {
......
......@@ -698,6 +698,10 @@ export class SaveExtensionHostProfileAction extends Action {
}
class RuntimeExtensionsEditorAccessibilityProvider implements IListAccessibilityProvider<IRuntimeExtension> {
getWidgetAriaLabel(): string {
return nls.localize('runtimeExtensions', "Runtime Extensions");
}
getAriaLabel(element: IRuntimeExtension): string | null {
return element.description.name;
}
......
......@@ -374,7 +374,6 @@ export class ExplorerView extends ViewPane {
this.instantiationService.createInstance(ExplorerDataSource), {
compressionEnabled: isCompressionEnabled(),
accessibilityProvider: this.renderer,
ariaLabel: nls.localize('treeAriaLabel', "Files Explorer"),
identityProvider: {
getId: (stat: ExplorerItem) => {
if (stat instanceof NewExplorerItem) {
......
......@@ -254,6 +254,10 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
});
}
getWidgetAriaLabel(): string {
return localize('treeAriaLabel', "Files Explorer");
}
get templateId(): string {
return FilesRenderer.ID;
}
......
......@@ -693,6 +693,11 @@ class OpenEditorsDragAndDrop implements IListDragAndDrop<OpenEditor | IEditorGro
}
class OpenEditorsAccessibilityProvider implements IListAccessibilityProvider<OpenEditor | IEditorGroup> {
getWidgetAriaLabel(): string {
return nls.localize('openEditors', "Open Editors");
}
getAriaLabel(element: OpenEditor | IEditorGroup): string | null {
if (element instanceof OpenEditor) {
return `${element.editor.getName()} ${element.editor.getDescription()}`;
......
......@@ -75,6 +75,10 @@ export class MarkersTreeAccessibilityProvider implements IListAccessibilityProvi
constructor(@ILabelService private readonly labelService: ILabelService) { }
getWidgetAriaLabel(): string {
return localize('problemsView', "Problems View");
}
public getAriaLabel(element: TreeElement): string | null {
if (element instanceof ResourceMarkers) {
const path = this.labelService.getUriLabel(element.resource, { relative: true }) || element.resource.fsPath;
......
......@@ -600,9 +600,9 @@ export class MarkersView extends ViewPane implements IMarkerFilterController {
} else {
this.messageBoxContainer.style.display = 'none';
if (filtered === total) {
this.ariaLabelElement.setAttribute('aria-label', localize('No problems filtered', "Showing {0} problems", total));
this.setAriaLabel(localize('No problems filtered', "Showing {0} problems", total));
} else {
this.ariaLabelElement.setAttribute('aria-label', localize('problems filtered', "Showing {0} of {1} problems", filtered, total));
this.setAriaLabel(localize('problems filtered', "Showing {0} of {1} problems", filtered, total));
}
this.messageBoxContainer.removeAttribute('tabIndex');
}
......@@ -631,19 +631,26 @@ export class MarkersView extends ViewPane implements IMarkerFilterController {
e.stopPropagation();
}
});
this.ariaLabelElement!.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS);
this.setAriaLabel(Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS);
}
private renderNoProblemsMessageForActiveFile(container: HTMLElement) {
const span = dom.append(container, dom.$('span'));
span.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT;
this.ariaLabelElement!.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT);
this.setAriaLabel(Messages.MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT);
}
private renderNoProblemsMessage(container: HTMLElement) {
const span = dom.append(container, dom.$('span'));
span.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT;
this.ariaLabelElement!.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT);
this.setAriaLabel(Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT);
}
private setAriaLabel(label: string): void {
if (this.tree) {
this.tree.ariaLabel = label;
}
this.ariaLabelElement!.setAttribute('aria-label', label);
}
private clearFilters(): void {
......
......@@ -340,7 +340,7 @@ export class OutlinePane extends ViewPane {
filter: this._treeFilter,
identityProvider: new OutlineIdentityProvider(),
keyboardNavigationLabelProvider: new OutlineNavigationLabelProvider(),
accessibilityProvider: new OutlineAccessibilityProvider(),
accessibilityProvider: new OutlineAccessibilityProvider(localize('outline', "Outline")),
hideTwistiesOfChildlessElements: true,
overrideStyles: {
listBackground: this.getBackgroundColor()
......
......@@ -456,7 +456,6 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditorP
this.keybindingsListContainer = DOM.append(parent, $('.keybindings-list-container'));
this.keybindingsList = this._register(this.instantiationService.createInstance(WorkbenchList, 'KeybindingsEditor', this.keybindingsListContainer, new Delegate(), [new KeybindingItemRenderer(this, this.instantiationService)], {
identityProvider: { getId: (e: IListEntry) => e.id },
ariaLabel: localize('keybindingsLabel', "Keybindings"),
setRowLineHeight: false,
horizontalScrolling: false,
accessibilityProvider: new AccessibilityProvider(),
......@@ -464,6 +463,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditorP
listBackground: editorBackground
}
})) as WorkbenchList<IListEntry>;
this._register(this.keybindingsList.onContextMenu(e => this.onContextMenu(e)));
this._register(this.keybindingsList.onDidChangeFocus(e => this.onFocusChange(e)));
this._register(this.keybindingsList.onDidFocus(() => {
......@@ -1106,6 +1106,10 @@ class WhenColumn extends Column {
class AccessibilityProvider implements IListAccessibilityProvider<IKeybindingItemEntry> {
getWidgetAriaLabel(): string {
return localize('keybindingsLabel', "Keybindings");
}
getAriaLabel(keybindingItemEntry: IKeybindingItemEntry): string {
let ariaLabel = localize('commandAriaLabel', "Command is {0}.", keybindingItemEntry.keybindingItem.commandLabel ? keybindingItemEntry.keybindingItem.commandLabel : keybindingItemEntry.keybindingItem.command);
ariaLabel += keybindingItemEntry.keybindingItem.keybinding ? localize('keybindingAriaLabel', "Keybinding is {0}.", keybindingItemEntry.keybindingItem.keybinding.getAriaLabel()) : localize('noKeybinding', "No Keybinding assigned.");
......
......@@ -1558,13 +1558,23 @@ export class SettingsTree extends ObjectTree<SettingsTreeElement> {
renderers,
{
supportDynamicHeights: true,
ariaRole: 'form',
ariaLabel: localize('treeAriaLabel', "Settings"),
identityProvider: {
getId(e) {
return e.id;
}
},
accessibilityProvider: {
getWidgetRole() {
return 'form';
},
getAriaLabel() {
// TODO@roblourens https://github.com/microsoft/vscode/issues/95862
return '';
},
getWidgetAriaLabel() {
return localize('settings', "Settings");
}
},
styleController: id => new DefaultStyleController(DOM.createStyleSheet(container), id),
filter: instantiationService.createInstance(SettingsTreeFilter, viewState)
});
......
......@@ -156,6 +156,10 @@ export function createTOCIterator(model: TOCTreeModel | SettingsTreeGroupElement
}
class SettingsAccessibilityProvider implements IListAccessibilityProvider<SettingsTreeGroupElement> {
getWidgetAriaLabel(): string {
return localize('settingsTOC', "Settings Table of Contents");
}
getAriaLabel(element: SettingsTreeElement): string {
if (!element) {
return '';
......
......@@ -395,6 +395,10 @@ export class SCMAccessibilityProvider implements IListAccessibilityProvider<Tree
constructor(@ILabelService private readonly labelService: ILabelService) { }
getWidgetAriaLabel(): string {
return localize('scm', "Source Control Management");
}
getAriaLabel(element: TreeElement): string {
if (ResourceTree.isResourceNode(element)) {
return this.labelService.getUriLabel(element.uri, { relative: true, noPrefix: true }) || element.name;
......
......@@ -308,6 +308,10 @@ export class SearchAccessibilityProvider implements IListAccessibilityProvider<R
) {
}
getWidgetAriaLabel(): string {
return nls.localize('search', "Search");
}
getAriaLabel(element: RenderableMatch): string | null {
if (element instanceof FolderMatch) {
return element.resource ?
......
......@@ -881,9 +881,11 @@ export class TimelinePane extends ViewPane {
return element.ariaLabel;
}
return element.ariaLabel ?? localize('timeline.aria.item', "{0}: {1}", element.relativeTime ?? '', element.label);
},
getWidgetAriaLabel(): string {
return localize('timeline', "Timeline");
}
},
ariaLabel: this.title,
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider(),
overrideStyles: {
listBackground: this.getBackgroundColor(),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册