accessibility by microsoft/vscode
npx skills add https://github.com/microsoft/vscode --skill accessibility当进行任何引入或更改交互式 UI 的 VS Code 功能工作时,请使用此技能。对于新功能和贡献,默认使用此技能,即使请求中没有明确提及无障碍功能。
触发示例:
不要仅仅因为提示中没有提到无障碍功能而跳过此技能。
当向 VS Code 添加新的交互式 UI 界面时——无论是面板、视图、小部件、编辑器覆盖层、对话框,还是任何用户可交互的、可聚焦的富组件——你必须提供三个无障碍组件(如果该功能尚未具备):
已具备所有三个组件的现有功能示例:终端、聊天面板、笔记本、差异编辑器、内联补全、评论、调试 REPL、悬停提示和通知。仅具备帮助对话框(无无障碍视图)的功能包括查找小部件、源代码控制输入、快捷键编辑器、问题面板和演练。
下面的第 4-7 节(信号、ARIA 播报、键盘导航、ARIA 标签)更广泛地适用于任何 UI 更改,包括对现有功能的修改。
当更新现有功能时——例如,添加新命令、键盘快捷键或交互功能——你还必须更新该功能现有的无障碍帮助对话框()以记录新功能。屏幕阅读器用户依赖帮助对话框作为发现可用操作的主要方式。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
provideContent()无障碍帮助对话框告诉用户该功能的作用、可用的键盘快捷键以及如何通过屏幕阅读器与之交互。
IAccessibleViewImplementation 的类,其中 type = AccessibleViewType.Help。
priority(值越高,当多个提供程序匹配时越先显示)。when 设置为一个 ContextKeyExpression,当功能获得焦点时匹配。getProvider(accessor) 返回一个 AccessibleContentProvider。IAccessibleViewContentProvider。
id —— 在 src/vs/platform/accessibility/browser/accessibleView.ts 的 AccessibleViewProviderId 枚举中添加一个新条目。verbositySettingKey —— 引用新的 AccessibilityVerbositySettingId 条目(见第 3 节)。options —— { type: AccessibleViewType.Help }。provideContent() —— 返回本地化的多行帮助文本。onClose() 以将焦点恢复到打开帮助对话框之前聚焦的元素。这确保了键盘用户和屏幕阅读器用户可以返回到他们之前的上下文。AccessibleViewRegistry.register(new MyFeatureAccessibilityHelp());
在功能的 *.contribution.ts 文件中。最简单的方法是从 getProvider() 直接返回一个 AccessibleContentProvider。这是代码库中最常见的模式(被聊天、内联聊天、快速聊天等使用):
import { AccessibleViewType, AccessibleContentProvider, AccessibleViewProviderId } from '../../../../platform/accessibility/browser/accessibleView.js';
import { IAccessibleViewImplementation } from '../../../../platform/accessibility/browser/accessibleViewRegistry.js';
import { AccessibilityVerbositySettingId } from '../../../../platform/accessibility/common/accessibilityConfiguration.js';
export class MyFeatureAccessibilityHelp implements IAccessibleViewImplementation {
readonly priority = 100;
readonly name = 'my-feature';
readonly type = AccessibleViewType.Help;
readonly when = MyFeatureContextKeys.isFocused;
getProvider(accessor: ServicesAccessor) {
const helpText = [
localize('myFeature.help.overview', "您正在我的功能中。…"),
localize('myFeature.help.key1', "- {0}: 执行某个操作", '<keybinding:myFeature.doSomething>'),
].join('\n');
return new AccessibleContentProvider(
AccessibleViewProviderId.MyFeature,
{ type: AccessibleViewType.Help },
() => helpText,
() => { /* onClose — 重新聚焦到之前聚焦的元素 */ },
AccessibilityVerbositySettingId.MyFeature,
);
}
}
或者,如果提供程序需要注入服务或必须跟踪状态(例如,存储对之前聚焦元素的引用),可以创建一个扩展 Disposable 并实现 IAccessibleViewContentProvider 的自定义类,然后通过 IInstantiationService 实例化它(参见 CommentsAccessibilityHelpProvider 作为示例):
class MyFeatureAccessibilityHelpProvider extends Disposable implements IAccessibleViewContentProvider {
readonly id = AccessibleViewProviderId.MyFeature;
readonly verbositySettingKey = AccessibilityVerbositySettingId.MyFeature;
readonly options: IAccessibleViewOptions = { type: AccessibleViewType.Help };
provideContent(): string { /* … */ }
onClose(): void { /* … */ }
}
// 在 getProvider() 中:
getProvider(accessor: ServicesAccessor) {
return accessor.get(IInstantiationService).createInstance(MyFeatureAccessibilityHelpProvider);
}
无障碍视图将功能的视觉内容以纯文本形式呈现在一个只读编辑器中。当功能渲染屏幕阅读器无法直接读取的富内容或视觉内容时(例如:聊天回复、悬停工具提示、通知、终端输出、内联补全),这是必需的。
如果功能纯粹是键盘驱动的,并且使用原生文本输入/输出(例如,简单的输入字段),则不需要无障碍视图——只需要无障碍帮助对话框。
IAccessibleViewImplementation 的类,其中 type = AccessibleViewType.View。options —— { type: AccessibleViewType.View },可选地指定用于语法高亮的 language。provideContent() —— 以纯文本形式返回功能的当前内容。provideNextContent() / providePreviousContent() 用于逐项导航。onClose() 以将焦点恢复到打开无障碍视图之前聚焦的元素。actions,用于用户可以从无障碍视图执行的操作。AccessibleViewRegistry.register(new MyFeatureAccessibleView());
export class MyFeatureAccessibleView implements IAccessibleViewImplementation {
readonly priority = 100;
readonly name = 'my-feature';
readonly type = AccessibleViewType.View;
readonly when = MyFeatureContextKeys.isFocused;
getProvider(accessor: ServicesAccessor) {
// 检索服务,从功能的当前状态构建内容
const content = getMyFeatureContent();
if (!content) {
return undefined;
}
return new AccessibleContentProvider(
AccessibleViewProviderId.MyFeature,
{ type: AccessibleViewType.View },
() => content,
() => { /* onClose — 重新聚焦到打开无障碍视图之前聚焦的元素 */ },
AccessibilityVerbositySettingId.MyFeature,
);
}
}
详细程度设置控制当功能获得焦点时是否播报诸如"按 Alt+F1 获取无障碍帮助"之类的提示。已经知道快捷键的用户可以禁用它。
src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts 的 AccessibilityVerbositySettingId 中添加一个条目:
export const enum AccessibilityVerbositySettingId {
// … 现有条目 …
MyFeature = 'accessibility.verbosity.myFeature'
}
configuration.properties 对象中注册配置属性:
[AccessibilityVerbositySettingId.MyFeature]: {
description: localize('verbosity.myFeature.description',
'当我的功能获得焦点时,提供有关如何访问我的功能无障碍帮助菜单的信息。'),
...baseVerbosityProperty
},
baseVerbosityProperty 为其提供 type: 'boolean'、default: true 和 tags: ['accessibility']。verbositySettingKey)和无障碍视图提供程序中引用此设置键,以便运行时可以检查是否显示提示。无障碍信号为视觉上发生的事件提供听觉和语音反馈。当发生重要事件时(例如,出现错误、任务完成、内容更改),使用 IAccessibilitySignalService 来播放信号。
AccessibilitySignal.* 静态成员——例如 AccessibilitySignal.error、AccessibilitySignal.terminalQuickFix、AccessibilitySignal.clear)。每个信号都有两种模式,由用户设置控制:
auto(屏幕阅读器连接时开启)、on 或 off。aria-live 播报的语音消息,可配置为 auto 或 off。// 通过构造函数参数注入服务
constructor(
@IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService
) { }
// 播放信号
this._accessibilitySignalService.playSignal(AccessibilitySignal.terminalQuickFix);
// 带选项播放
this._accessibilitySignalService.playSignal(AccessibilitySignal.error, { userGesture: true });
使用 src/vs/base/browser/ui/aria/aria.ts 中的 alert() 和 status() 函数向屏幕阅读器播报动态变化。
alert(msg) —— 强断言实时区域 (role="alert")status(msg) —— 礼貌实时区域 (aria-live="polite")status() 而非 alert(),除非信息具有时效性或是用户直接操作的结果。过度使用 alert() 会造成嘈杂、干扰性的体验。alert() / status()。nls.localize()。每个交互式 UI 元素都必须能完全通过键盘操作。
Tab / Shift+Tab 以逻辑顺序访问。focusBorder 提供此功能)。Escape 键关闭,并将焦点返回到之前的元素。所有交互式 UI 元素必须具有适当的 ARIA 属性,以便屏幕阅读器能够识别和描述它们。
aria-label:每个没有可见文本的交互式元素(图标按钮、纯图标操作、自定义小部件)必须有一个描述性的 aria-label。标签应本地化。aria-labelledby / aria-describedby:使用这些属性将元素与现有的可见文本关联起来,而不是重复字符串。role:不使用原生 HTML 元素的自定义小部件必须声明正确的 ARIA 角色(例如 role="button"、role="tree"、role="tablist")。aria-expanded、aria-selected、aria-checked:切换和选择状态必须通过适当的 ARIA 状态属性传达。aria-hidden="true":装饰性或冗余元素(文本标签旁边的图标、装饰性分隔符)必须从无障碍树中隐藏。aria-setsize 和 aria-posinset,以便屏幕阅读器报告正确的计数。accessibleView.ts 中添加了新的 AccessibleViewProviderId 条目accessibilityConfiguration.ts 中添加了新的 AccessibilityVerbositySettingId 条目...baseVerbosityProperty 注册了详细程度设置type = Help 的 IAccessibleViewImplementationverbositySettingKeynls.localize() 本地化<keybinding:commandId> 语法进行动态解析when 上下文键已设置,以便对话框仅在功能获得焦点时出现type = View 的 IAccessibleViewImplementation*.contribution.ts 文件中进行了注册调用AccessibilitySignal.* 或注册新的)aria.alert() 或 aria.status()(除非紧急,否则优先使用 status())aria-labelrole 和状态属性aria-hidden="true" 隐藏src/vs/platform/accessibility/browser/accessibleView.ts —— AccessibleViewProviderId、AccessibleContentProvider、IAccessibleViewContentProvidersrc/vs/platform/accessibility/browser/accessibleViewRegistry.ts —— AccessibleViewRegistry、IAccessibleViewImplementationsrc/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts —— AccessibilityVerbositySettingId、详细程度设置注册src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts —— IAccessibilitySignalService、AccessibilitySignalsrc/vs/base/browser/ui/aria/aria.ts —— alert()、status(),用于 ARIA 实时区域播报每周安装量
228
代码仓库
GitHub 星标数
183.0K
首次出现
2026年2月8日
安全审计
安装于
opencode227
gemini-cli226
codex225
github-copilot223
kimi-cli223
amp223
Use this skill for any VS Code feature work that introduces or changes interactive UI. Use this skill by default for new features and contributions, including when the request does not explicitly mention accessibility.
Trigger examples:
Do not skip this skill just because accessibility is not named in the prompt.
When adding a new interactive UI surface to VS Code — a panel, view, widget, editor overlay, dialog, or any rich focusable component the user interacts with — you must provide three accessibility components (if they do not already exist for the feature):
Examples of existing features that have all three: the terminal , chat panel , notebook , diff editor , inline completions , comments , debug REPL , hover , and notifications. Features with only a help dialog (no accessible view) include find widgets , source control input , keybindings editor , problems panel , and walkthroughs.
Sections 4–7 below (signals, ARIA announcements, keyboard navigation, ARIA labels) apply more broadly to any UI change , including modifications to existing features.
When updating an existing feature — for example, adding new commands, keyboard shortcuts, or interactive capabilities — you must also update the feature's existing accessibility help dialog (provideContent()) to document the new functionality. Screen reader users rely on the help dialog as the primary way to discover available actions.
An accessibility help dialog tells the user what the feature does, which keyboard shortcuts are available, and how to interact with it via a screen reader.
Create a class implementingIAccessibleViewImplementation with type = AccessibleViewType.Help.
priority (higher = shown first when multiple providers match).when to a ContextKeyExpression that matches when the feature is focused.getProvider(accessor) returns an AccessibleContentProvider.Create a content-provider class implementing IAccessibleViewContentProvider.
in the feature's *.contribution.ts file.
The simplest approach is to return an AccessibleContentProvider directly from getProvider(). This is the most common pattern in the codebase (used by chat, inline chat, quick chat, etc.):
import { AccessibleViewType, AccessibleContentProvider, AccessibleViewProviderId } from '../../../../platform/accessibility/browser/accessibleView.js';
import { IAccessibleViewImplementation } from '../../../../platform/accessibility/browser/accessibleViewRegistry.js';
import { AccessibilityVerbositySettingId } from '../../../../platform/accessibility/common/accessibilityConfiguration.js';
export class MyFeatureAccessibilityHelp implements IAccessibleViewImplementation {
readonly priority = 100;
readonly name = 'my-feature';
readonly type = AccessibleViewType.Help;
readonly when = MyFeatureContextKeys.isFocused;
getProvider(accessor: ServicesAccessor) {
const helpText = [
localize('myFeature.help.overview', "You are in My Feature. …"),
localize('myFeature.help.key1', "- {0}: Do something", '<keybinding:myFeature.doSomething>'),
].join('\n');
return new AccessibleContentProvider(
AccessibleViewProviderId.MyFeature,
{ type: AccessibleViewType.Help },
() => helpText,
() => { /* onClose — refocus whatever was focused before */ },
AccessibilityVerbositySettingId.MyFeature,
);
}
}
Alternatively, if the provider needs injected services or must track state (e.g., storing a reference to the previously focused element), create a custom class that extends Disposable and implements IAccessibleViewContentProvider, then instantiate it via IInstantiationService (see CommentsAccessibilityHelpProvider for an example):
class MyFeatureAccessibilityHelpProvider extends Disposable implements IAccessibleViewContentProvider {
readonly id = AccessibleViewProviderId.MyFeature;
readonly verbositySettingKey = AccessibilityVerbositySettingId.MyFeature;
readonly options: IAccessibleViewOptions = { type: AccessibleViewType.Help };
provideContent(): string { /* … */ }
onClose(): void { /* … */ }
}
// In getProvider():
getProvider(accessor: ServicesAccessor) {
return accessor.get(IInstantiationService).createInstance(MyFeatureAccessibilityHelpProvider);
}
An accessible view presents the feature's visual content as plain text in a read-only editor. It is required when the feature renders rich or visual content that a screen reader cannot directly read (for example: chat responses, hover tooltips, notifications, terminal output, inline completions).
If the feature is purely keyboard-driven with native text input/output (e.g., a simple input field), an accessible view is not needed — only an accessibility help dialog is required.
Create a class implementingIAccessibleViewImplementation with type = AccessibleViewType.View.
Create a content-provider similar to the help dialog, but:
options — { type: AccessibleViewType.View }, optionally with a language for syntax highlighting.provideContent() — return the feature's current content as plain text.provideNextContent() / providePreviousContent() for item-by-item navigation.export class MyFeatureAccessibleView implements IAccessibleViewImplementation {
readonly priority = 100;
readonly name = 'my-feature';
readonly type = AccessibleViewType.View;
readonly when = MyFeatureContextKeys.isFocused;
getProvider(accessor: ServicesAccessor) {
// Retrieve services, build content from the feature's current state
const content = getMyFeatureContent();
if (!content) {
return undefined;
}
return new AccessibleContentProvider(
AccessibleViewProviderId.MyFeature,
{ type: AccessibleViewType.View },
() => content,
() => { /* onClose — refocus whatever was focused before the accessible view opened */ },
AccessibilityVerbositySettingId.MyFeature,
);
}
}
A verbosity setting controls whether a hint such as "press Alt+F1 for accessibility help" is announced when the feature gains focus. Users who already know the shortcut can disable it.
Add an entry to AccessibilityVerbositySettingId in src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts:
export const enum AccessibilityVerbositySettingId { // … existing entries … MyFeature = 'accessibility.verbosity.myFeature' }
Register the configuration property in the same file's configuration.properties object:
description: localize('verbosity.myFeature.description', 'Provide information about how to access the My Feature accessibility help menu when My Feature is focused.'), ...baseVerbosityProperty },
The baseVerbosityProperty gives it type: 'boolean', default: true, and tags: ['accessibility'].
verbositySettingKey) and the accessible-view provider so the runtime can check whether to show the hint.Accessibility signals provide audible and spoken feedback for events that happen visually. Use IAccessibilitySignalService to play signals when something important occurs (e.g., an error appears, a task completes, content changes).
AccessibilitySignal.* static members — e.g., AccessibilitySignal.error, AccessibilitySignal.terminalQuickFix, AccessibilitySignal.clear).Each signal has two modalities controlled by user settings:
auto (on when screen reader attached), on, or off.aria-live, configurable to auto or off.// Inject the service via constructor parameter
constructor(
@IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService
) { }
// Play a signal
this._accessibilitySignalService.playSignal(AccessibilitySignal.terminalQuickFix);
// Play with options
this._accessibilitySignalService.playSignal(AccessibilitySignal.error, { userGesture: true });
Use the alert() and status() functions from src/vs/base/browser/ui/aria/aria.ts to announce dynamic changes to screen readers.
alert(msg) — Assertive live region (role="alert")status(msg) — Polite live region (aria-live="polite")status() over alert() unless the information is time-sensitive or the result of a direct user action. Overusing alert() creates a noisy, disruptive experience.alert() / status() for the same information.nls.localize().Every interactive UI element must be fully operable via the keyboard.
Tab / Shift+Tab in a logical order.focusBorder).Escape, returning focus to the previous element.All interactive UI elements must have appropriate ARIA attributes so screen readers can identify and describe them.
aria-label : Every interactive element without visible text (icon buttons, icon-only actions, custom widgets) must have a descriptive aria-label. Labels should be localized.aria-labelledby / aria-describedby : Use these to associate elements with existing visible text rather than duplicating strings.role : Custom widgets that do not use native HTML elements must declare the correct ARIA role (e.g., role="button", role="tree", role="tablist").aria-expanded , , : Toggle and selection states must be communicated via the appropriate ARIA state attributes.aria-setsize and aria-posinset when virtualized so screen readers report the correct count.AccessibleViewProviderId entry added in accessibleView.tsAccessibilityVerbositySettingId entry added in accessibilityConfiguration.ts...baseVerbosityPropertyIAccessibleViewImplementation with type = Help created and registeredverbositySettingKeynls.localize()src/vs/platform/accessibility/browser/accessibleView.ts — AccessibleViewProviderId, AccessibleContentProvider, IAccessibleViewContentProvidersrc/vs/platform/accessibility/browser/accessibleViewRegistry.ts — AccessibleViewRegistry, IAccessibleViewImplementationsrc/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts — AccessibilityVerbositySettingId, verbosity setting registrationWeekly Installs
228
Repository
GitHub Stars
183.0K
First Seen
Feb 8, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode227
gemini-cli226
codex225
github-copilot223
kimi-cli223
amp223
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
107,800 周安装
id — add a new entry in the AccessibleViewProviderId enum in src/vs/platform/accessibility/browser/accessibleView.ts.verbositySettingKey — reference the new AccessibilityVerbositySettingId entry (see §3).options — { type: AccessibleViewType.Help }.provideContent() — return localized, multi-line help text.ImplementonClose() to restore focus to whatever element was focused before the help dialog opened. This ensures keyboard users and screen reader users return to their previous context.
Register the implementation:
AccessibleViewRegistry.register(new MyFeatureAccessibilityHelp());
onClose()actions for actions the user can take from the accessible view.Register alongside the help dialog:
AccessibleViewRegistry.register(new MyFeatureAccessibleView());
aria-selectedaria-checkedaria-hidden="true" : Decorative or redundant elements (icons next to text labels, decorative separators) must be hidden from the accessibility tree.<keybinding:commandId>when context key is set so the dialog only appears when the feature is focusedIAccessibleViewImplementation with type = View created and registered*.contribution.ts fileAccessibilitySignal.* or register a new one)aria.alert() or aria.status() used appropriately for dynamic changes (prefer status() unless urgent)aria-labelrole and state attributesaria-hidden="true"src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts — IAccessibilitySignalService, AccessibilitySignalsrc/vs/base/browser/ui/aria/aria.ts — alert(), status() for ARIA live region announcements