Properly handle action widget checked state (#250127)

This commit is contained in:
Logan Ramos 2025-05-30 12:00:08 -04:00 committed by GitHub
parent 7e00e4890d
commit d0e9ef35ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 5 deletions

View File

@ -5,7 +5,7 @@
import * as dom from '../../../base/browser/dom.js';
import { KeybindingLabel } from '../../../base/browser/ui/keybindingLabel/keybindingLabel.js';
import { IListEvent, IListMouseEvent, IListRenderer, IListVirtualDelegate } from '../../../base/browser/ui/list/list.js';
import { List } from '../../../base/browser/ui/list/listWidget.js';
import { IListAccessibilityProvider, List } from '../../../base/browser/ui/list/listWidget.js';
import { CancellationToken, CancellationTokenSource } from '../../../base/common/cancellation.js';
import { Codicon } from '../../../base/common/codicons.js';
import { ResolvedKeybinding } from '../../../base/common/keybindings.js';
@ -201,6 +201,7 @@ export class ActionList<T> extends Disposable {
preview: boolean,
items: readonly IActionListItem<T>[],
private readonly _delegate: IActionListDelegate<T>,
accessibilityProvider: Partial<IListAccessibilityProvider<IActionListItem<T>>> | undefined,
@IContextViewService private readonly _contextViewService: IContextViewService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@ILayoutService private readonly _layoutService: ILayoutService,
@ -213,6 +214,7 @@ export class ActionList<T> extends Disposable {
getTemplateId: element => element.kind
};
this._list = this._register(new List(user, this.domNode, virtualDelegate, [
new ActionItemRenderer<IActionListItem<T>>(preview, this._keybindingService),
new HeaderRenderer(),
@ -234,6 +236,7 @@ export class ActionList<T> extends Disposable {
getWidgetAriaLabel: () => localize({ key: 'customQuickFixWidget', comment: [`An action widget option`] }, "Action Widget"),
getRole: (e) => e.kind === ActionListItemKind.Action ? 'option' : 'separator',
getWidgetRole: () => 'listbox',
...accessibilityProvider
},
}));

View File

@ -19,6 +19,7 @@ import { createDecorator, IInstantiationService, ServicesAccessor } from '../../
import { KeybindingWeight } from '../../keybinding/common/keybindingsRegistry.js';
import { inputActiveOptionBackground, registerColor } from '../../theme/common/colorRegistry.js';
import { StandardMouseEvent } from '../../../base/browser/mouseEvent.js';
import { IListAccessibilityProvider } from '../../../base/browser/ui/list/listWidget.js';
registerColor(
'actionBar.toggledBackground',
@ -35,7 +36,7 @@ export const IActionWidgetService = createDecorator<IActionWidgetService>('actio
export interface IActionWidgetService {
readonly _serviceBrand: undefined;
show<T>(user: string, supportsPreview: boolean, items: readonly IActionListItem<T>[], delegate: IActionListDelegate<T>, anchor: HTMLElement | StandardMouseEvent | IAnchor, container: HTMLElement | undefined, actionBarActions?: readonly IAction[]): void;
show<T>(user: string, supportsPreview: boolean, items: readonly IActionListItem<T>[], delegate: IActionListDelegate<T>, anchor: HTMLElement | StandardMouseEvent | IAnchor, container: HTMLElement | undefined, actionBarActions?: readonly IAction[], accessibilityProvider?: Partial<IListAccessibilityProvider<IActionListItem<T>>>): void;
hide(didCancel?: boolean): void;
@ -59,10 +60,10 @@ class ActionWidgetService extends Disposable implements IActionWidgetService {
super();
}
show<T>(user: string, supportsPreview: boolean, items: readonly IActionListItem<T>[], delegate: IActionListDelegate<T>, anchor: HTMLElement | StandardMouseEvent | IAnchor, container: HTMLElement | undefined, actionBarActions?: readonly IAction[]): void {
show<T>(user: string, supportsPreview: boolean, items: readonly IActionListItem<T>[], delegate: IActionListDelegate<T>, anchor: HTMLElement | StandardMouseEvent | IAnchor, container: HTMLElement | undefined, actionBarActions?: readonly IAction[], accessibilityProvider?: Partial<IListAccessibilityProvider<IActionListItem<T>>>): void {
const visibleContext = ActionWidgetContextKeys.Visible.bindTo(this._contextKeyService);
const list = this._instantiationService.createInstance(ActionList, user, supportsPreview, items, delegate);
const list = this._instantiationService.createInstance(ActionList, user, supportsPreview, items, delegate, accessibilityProvider);
this._contextViewService.showContextView({
getAnchor: () => anchor,
render: (container: HTMLElement) => {

View File

@ -11,6 +11,7 @@ import { ThemeIcon } from '../../../base/common/themables.js';
import { Codicon } from '../../../base/common/codicons.js';
import { getActiveElement, isHTMLElement } from '../../../base/browser/dom.js';
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
import { IListAccessibilityProvider } from '../../../base/browser/ui/list/listWidget.js';
export interface IActionWidgetDropdownAction extends IAction {
category?: { label: string; order: number };
@ -126,6 +127,14 @@ export class ActionWidgetDropdown extends BaseDropdown {
}
}));
const accessibilityProvider: Partial<IListAccessibilityProvider<IActionListItem<IActionWidgetDropdownAction>>> = {
isChecked(element) {
return element.kind === ActionListItemKind.Action && !!element?.item?.checked;
},
getRole: (e) => e.kind === ActionListItemKind.Action ? 'menuitemcheckbox' : 'separator',
getWidgetRole: () => 'menu',
};
this.actionWidgetService.show<IActionWidgetDropdownAction>(
this._options.label ?? '',
false,
@ -133,7 +142,8 @@ export class ActionWidgetDropdown extends BaseDropdown {
actionWidgetDelegate,
this.element,
undefined,
actionBarActions
actionBarActions,
accessibilityProvider
);
}
}