accessibility について
VS Code のインタラクティブな UI を実装するためのアクセシビリティスキルです。キーボード操作、スクリーンリーダー対応、アクセシブルビュー、通知の実装要件を示します。
主な機能
- 01アクセシビリティヘルプダイアログの追加
- 02視覚情報のプレーンテキスト表示
- 03アクセシビリティ音声案内の設定
- 04音と音声によるシグナル
- 05ARIA アラートとステータスメッセージ
- 06キーボードナビゲーションへの対応
活用シーン
- 01新しい VS Code パネルやウィジェットの構築
- 02既存の操作機能のアクセシビリティ改善
- 03視覚情報のスクリーンリーダー対応
- 04エラーや進捗のアクセシブルな通知
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ vscode --skill accessibilityインストール後、Claude Code で/accessibilityを入力して読み込まれたか確認します。
詳細
このスキルを使用するタイミング
インタラクティブ UI を導入または変更する VS Code の機能開発では、必ずこのスキルを使用してください。アクセシビリティへの言及が依頼にない場合も含め、新機能やコントリビューションではデフォルトでこのスキルを使用してください。
適用例:
- 「新機能を追加する」
- 「新しいパネル/ビュー/ウィジェットを実装する」
- 「新しいコマンドやワークフローを追加する」
- 「workbench/editor/extensions に新しいコントリビューションを追加する」
- 「既存の UI 操作を更新する」
プロンプトでアクセシビリティが明示されていないという理由だけで、このスキルを省略しないでください。
VS Code に新しいインタラクティブ UI サーフェス(パネル、ビュー、ウィジェット、エディターオーバーレイ、ダイアログ、またはユーザーが操作するフォーカス可能なリッチコンポーネント)を追加する場合、その機能にまだ存在しなければ、次の 3 つのアクセシビリティ要素を必ず用意してください。
- アクセシビリティヘルプダイアログ — 機能にフォーカスがあるとき、アクセシビリティヘルプのキーバインドで開きます。
- アクセシブルビュー — スクリーンリーダーユーザーに機能の内容を提示する、プレーンテキストの読み取り専用エディターです(機能が視覚的に複雑な内容を表示する場合)。
- アクセシビリティ詳細度設定 — 「アクセシビリティヘルプを開く」ヒントを読み上げるかどうかを制御するブール値設定です。
3 つすべてが揃っている既存機能の例:ターミナル、チャットパネル、ノートブック、差分エディター、インライン補完、コメント、デバッグ REPL、ホバー、通知。ヘルプダイアログのみがある(アクセシブルビューはない)機能の例:検索ウィジェット、ソース管理の入力欄、キーバインドエディター、問題パネル、チュートリアル。
以下のセクション 4~7(シグナル、ARIA アナウンス、キーボードナビゲーション、ARIA ラベル)は、既存機能の変更を含む、あらゆる UI の変更に幅広く適用されます。
既存機能を更新する場合(新しいコマンド、キーボードショートカット、インタラクティブ機能の追加など)、その機能に既存のアクセシビリティヘルプダイアログ(provideContent())も更新し、新機能を説明してください。スクリーンリーダーユーザーは、利用可能な操作を見つけるための主要な手段としてヘルプダイアログを利用します。
1. アクセシビリティヘルプダイアログ
アクセシビリティヘルプダイアログでは、その機能の内容、利用可能なキーボードショートカット、スクリーンリーダーを使った操作方法をユーザーに説明します。
手順
-
type = AccessibleViewType.Helpを設定して、IAccessibleViewImplementationを実装するクラスを作成します。priorityを設定します(値が大きいほど、複数のプロバイダーが一致したときに優先して表示されます)。- 機能にフォーカスがあるときに一致する
ContextKeyExpressionをwhenに設定します。 getProvider(accessor)はAccessibleContentProviderを返します。
-
IAccessibleViewContentProviderを実装するコンテンツプロバイダークラスを作成します。id—src/vs/platform/accessibility/browser/accessibleView.tsのAccessibleViewProviderIdenum に新しいエントリーを追加します。verbositySettingKey— 新しいAccessibilityVerbositySettingIdエントリーを参照します(§3 を参照)。options—{ type: AccessibleViewType.Help }を指定します。provideContent()— ローカライズされた複数行のヘルプテキストを返します。
-
onClose()を実装し、ヘルプダイアログを開く前にフォーカスされていた要素にフォーカスを戻します。これにより、キーボードユーザーとスクリーンリーダーユーザーは、以前のコンテキストに戻れます。 -
機能の
*.contribution.tsファイルで、実装を登録します。AccessibleViewRegistry.register(new MyFeatureAccessibilityHelp());
実装例の骨組み
最も簡単な方法は、getProvider() から AccessibleContentProvider を直接返すことです。これはコードベースで最も一般的なパターンです(chat、inline chat、quick chat などで使用されています)。
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,
);
}
}
また、プロバイダーにサービスのインジェクションが必要な場合や、状態を追跡する必要がある場合(以前フォーカスされていた要素への参照を保存するなど)は、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 { /* … */ }
}
// In getProvider():
getProvider(accessor: ServicesAccessor) {
return accessor.get(IInstantiationService).createInstance(MyFeatureAccessibilityHelpProvider);
}
2. アクセシブルビュー
アクセシブルビューでは、機能の視覚的なコンテンツを読み取り専用エディター内にプレーンテキストで表示します。機能が、スクリーンリーダーで直接読み上げられないリッチコンテンツや視覚的なコンテンツを表示する場合(例:チャットの応答、ホバー時のツールチップ、通知、ターミナル出力、インライン補完)に必要です。
機能がネイティブのテキスト入力/出力を使ったキーボード操作のみで完結する場合(例:シンプルな入力フィールド)、アクセシブルビューは不要です。必要なのはアクセシビリティヘルプダイアログのみです。
手順
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) {
// 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,
);
}
}
3. アクセシビリティの詳細度設定
詳細度設定では、機能にフォーカスが移ったときに「アクセシビリティヘルプを表示するには Alt+F1 を押してください」のようなヒントを読み上げるかどうかを制御します。ショートカットをすでに知っているユーザーは、この設定を無効にできます。
手順
-
src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.tsのAccessibilityVerbositySettingIdにエントリーを追加します。export const enum AccessibilityVerbositySettingId { // … existing entries … MyFeature = 'accessibility.verbosity.myFeature' } -
同じファイルの
configuration.propertiesオブジェクトに構成プロパティを登録します。[AccessibilityVerbositySettingId.MyFeature]: { description: localize('verbosity.myFeature.description', 'Provide information about how to access the My Feature accessibility help menu when My Feature is focused.'), ...baseVerbosityProperty },baseVerbosityPropertyにより、type: 'boolean'、default: true、tags: ['accessibility']が設定されます。 -
ヒントを表示するかどうかを実行時に確認できるよう、ヘルプダイアログのプロバイダー(
verbositySettingKey)とアクセシブルビューのプロバイダーの両方で、設定キーを参照します。
4. アクセシビリティシグナル(サウンドとアナウンス)
アクセシビリティシグナルは、視覚的に発生するイベントに対して、音声や読み上げによるフィードバックを提供します。重要なイベントが発生したとき(例:エラーの表示、タスクの完了、コンテンツの変更)に、IAccessibilitySignalService を使ってシグナルを再生します。
使用するタイミング
- 既存のシグナルを使用します。イベントにすでにシグナルが定義されている場合は、そのシグナルを使用してください(
AccessibilitySignal.*の静的メンバーを参照。例:AccessibilitySignal.error、AccessibilitySignal.terminalQuickFix、AccessibilitySignal.clear)。 - 適切な既存シグナルがない場合は、新しいシグナルの追加について @meganrogge に相談してください。事前に調整せず、新しいシグナルを登録しないでください。
シグナルの仕組み
各シグナルには、ユーザー設定で制御される2種類のモダリティがあります。
- サウンド — 短い音声キューです。
auto(スクリーンリーダーの接続時にオン)、on、offに設定できます。 - アナウンス —
aria-liveによる読み上げメッセージです。autoまたは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 });
5. ARIA アラートとステータスメッセージ
src/vs/base/browser/ui/aria/aria.ts の alert() および status() 関数を使って、動的な変更をスクリーンリーダーに通知します。
alert(msg) — 積極的なライブリージョン(role="alert")
- 用途:ユーザーがすぐに知る必要のある、緊急で重要な情報。
- 例:エラー、警告、重大な状態変更、ユーザーが開始した操作の結果。
- 動作:スクリーンリーダーが現在読み上げている内容を中断します。
status(msg) — 丁寧なライブリージョン(aria-live="polite")
- 用途:緊急ではなく、スクリーンリーダーがアイドル状態のときに読み上げる情報更新。
- 例:進行状況の更新、検索結果の件数、バックグラウンドでの状態変更。
- 動作:キューに追加され、スクリーンリーダーが現在の出力を終えた後に読み上げられます。
ガイドライン
alert()よりstatus()を優先してください。ただし、時間的な制約がある情報や、ユーザーの直接操作の結果である場合は除きます。alert()を使いすぎると、煩雑で操作を妨げる体験になります。- メッセージは簡潔にしてください。 スクリーンリーダーはメッセージ全体を読み上げるため、長いメッセージはユーザーを待たせます。
- 重複させないでください。アクセシビリティ機能によってイベントがすでに通知される場合、同じ情報について
alert()やstatus()も呼び出さないでください。 - すべてのメッセージを
nls.localize()でローカライズしてください。
6. キーボードナビゲーション
すべてのインタラクティブな UI 要素は、キーボードだけで完全に操作できなければなりません。
要件
- Tab の順序:すべてのインタラクティブな要素に、論理的な順序で
Tab/Shift+Tabを使ってアクセスできなければなりません。 - 矢印キーでのナビゲーション:リスト、ツリー、グリッド、ツールバーでは、WAI-ARIA のパターンに沿った矢印キーでのナビゲーションをサポートする必要があります。
- フォーカスの可視性:フォーカス中の要素には、視認できるフォーカスインジケーターが必要です(VS Code のテーマシステムでは
focusBorderによって提供されます)。 - マウスだけの操作は禁止:クリックやホバーで実行できるすべての操作は、キーボードでも実行できなければなりません(コンテキストメニュー、ボタン、トグルなど)。
- Escape で閉じる:オーバーレイ、ダイアログ、ポップアップは
Escapeで閉じ、フォーカスを直前の要素に戻せる必要があります。 - フォーカスのトラップ:モーダルダイアログは、閉じられるまでダイアログ内にフォーカスを留める必要があります。
利用できないオプションの説明
発見可能な利用不可機能のパターンに従ってください。ドキュメントで紹介されている機能が、ユーザーに有効化できないという理由だけで、説明なく表示されなくなることがあってはなりません。コントロールがサポートする ARIA セマンティクスを使って、無効状態とその理由の両方を通知してください。灰色のラベル、ブリーフケースのアイコン、ホバーだけでは不十分です。テキストですでに意味が伝わる場合、アイコンは装飾として扱ってください。
説明リンクは、無効なオプションを有効にすることなく、マウスとキーボードの両方で個別に操作できる必要があります。tabIndexやプログラムによるfocus()だけでなく、実際の Tab/Shift+Tab と Enter の動作を確認してください。リストのナビゲーションでは、無効な行がスキップされる場合があります。ポリシーの更新時にはフォーカスと選択状態を維持し、古くなったアクションを防ぎ、利用可能な説明と次の手順を使って機能のアクセシビリティヘルプを更新してください。設計ガイダンスにリンクされている設定、モデル、ハーネス、権限ピッカーの例を再利用してください。
7. ARIA ラベルとロール
スクリーンリーダーがすべてのインタラクティブな 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":装飾的、または重複する要素(テキストラベルの横にあるアイコン、装飾用の区切り線)は、アクセシビリティツリーから隠す必要があります。
ガイドライン
- 「button」や「icon」のような汎用的なラベルは避け、操作を説明してください。「パネルを閉じる」「サイドバーを切り替える」「タスクを実行する」などのラベルを使用します。
- スクリーンリーダー(macOS の VoiceOver、Windows の NVDA)でテストし、ラベルが文脈に沿って正しく読み上げられることを確認してください。
- 仮想化されたリストやツリーでは、スクリーンリーダーが正しい件数を通知できるよう、
aria-setsizeとaria-posinsetを使用してください。
新機能ごとのチェックリスト
-
accessibleView.tsに新しいAccessibleViewProviderIdエントリを追加 -
accessibilityConfiguration.tsに新しいAccessibilityVerbositySettingIdエントリを追加 -
...baseVerbosityPropertyを使用して、設定プロパティに冗長性設定を登録 -
type = Helpを指定したIAccessibleViewImplementationを作成して登録 - コンテンツプロバイダーが正しい
verbositySettingKeyを参照している - ヘルプテキスト全体を
nls.localize()でローカライズ - ヘルプテキスト内のキーバインドには、動的解決のため
<keybinding:commandId>構文を使用 - ダイアログが機能にフォーカスがある場合にのみ表示されるよう、
whenコンテキストキーを設定 - 機能にリッチコンテンツまたは視覚的なコンテンツがある場合:
type = Viewを指定したIAccessibleViewImplementationを作成して登録 - 機能の
*.contribution.tsファイルで登録呼び出しを行う - 重要なイベントでアクセシビリティシグナルを再生(既存の
AccessibilitySignal.*を使用するか、新しいものを登録) - 動的な変更には、適切に
aria.alert()またはaria.status()を使用(緊急でない限りstatus()を優先) - すべてのインタラクティブ要素にキーボードで到達し、操作できる
- 表示テキストのないすべてのインタラクティブ要素に、ローカライズされた
aria-labelがある - カスタムウィジェットで、適切な ARIA
roleと状態属性を宣言 - 装飾要素を
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— ARIA ライブリージョンでの通知に使用するalert()、status()