Add screenreader warning on terminal tool notifications (#274228)

Enables markdown message parts to receive accessibility information on when to announce statusUpdates (and apply ariaLabel)
This commit is contained in:
Ben Villalobos
2025-11-02 17:26:25 -08:00
committed by GitHub
parent 9996e714c5
commit 4c2ed1a2e7
2 changed files with 27 additions and 2 deletions

View File

@@ -6,6 +6,7 @@
import '../media/chatCodeBlockPill.css';
import './media/chatMarkdownPart.css';
import * as dom from '../../../../../base/browser/dom.js';
import { status } from '../../../../../base/browser/ui/aria/aria.js';
import { allowedMarkdownHtmlAttributes, MarkdownRendererMarkedOptions, type MarkdownRenderOptions } from '../../../../../base/browser/markdownRenderer.js';
import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js';
import { HoverPosition } from '../../../../../base/browser/ui/hover/hoverWidget.js';
@@ -61,11 +62,19 @@ import { ChatExtensionsContentPart } from './chatExtensionsContentPart.js';
import { IOpenEditorOptions, registerOpenEditorListeners } from '../../../../../platform/editor/browser/editor.js';
import { HoverStyle } from '../../../../../base/browser/ui/hover/hover.js';
import { ChatEditingActionContext } from '../chatEditing/chatEditingActions.js';
import { AccessibilityWorkbenchSettingId } from '../../../accessibility/browser/accessibilityConfiguration.js';
const $ = dom.$;
export interface IChatMarkdownContentPartOptions {
readonly codeBlockRenderOptions?: ICodeBlockRenderOptions;
readonly accessibilityOptions?: {
/**
* Message to announce to screen readers as a status update if VerboseChatProgressUpdates is enabled.
* Will also be used as the aria-label for the container.
* */
statusMessage?: string;
};
}
export class ChatMarkdownContentPart extends Disposable implements IChatContentPart {
@@ -118,6 +127,13 @@ export class ChatMarkdownContentPart extends Disposable implements IChatContentP
this.domNode = $('div.chat-markdown-part');
if (this.rendererOptions.accessibilityOptions?.statusMessage) {
this.domNode.ariaLabel = this.rendererOptions.accessibilityOptions.statusMessage;
if (configurationService.getValue<boolean>(AccessibilityWorkbenchSettingId.VerboseChatProgressUpdates)) {
status(this.rendererOptions.accessibilityOptions.statusMessage);
}
}
const enableMath = configurationService.getValue<boolean>(ChatConfiguration.EnableMath);
const doRenderMarkdown = () => {

View File

@@ -15,7 +15,7 @@ import { CodeBlockModelCollection } from '../../../common/codeBlockModelCollecti
import { IChatCodeBlockInfo } from '../../chat.js';
import { ChatQueryTitlePart } from '../chatConfirmationWidget.js';
import { IChatContentPartRenderContext } from '../chatContentParts.js';
import { ChatMarkdownContentPart, EditorPool } from '../chatMarkdownContentPart.js';
import { ChatMarkdownContentPart, EditorPool, type IChatMarkdownContentPartOptions } from '../chatMarkdownContentPart.js';
import { ChatProgressSubPart } from '../chatProgressContentPart.js';
import { BaseChatToolInvocationSubPart } from './chatToolInvocationSubPart.js';
import '../media/chatTerminalToolProgressPart.css';
@@ -38,6 +38,7 @@ import { IMarkdownRenderer } from '../../../../../../platform/markdown/browser/m
import * as domSanitize from '../../../../../../base/browser/domSanitize.js';
import { DomSanitizerConfig } from '../../../../../../base/browser/domSanitize.js';
import { allowedMarkdownHtmlAttributes } from '../../../../../../base/browser/markdownRenderer.js';
import { stripIcons } from '../../../../../../base/common/iconLabels.js';
const MAX_TERMINAL_OUTPUT_PREVIEW_HEIGHT = 200;
@@ -143,7 +144,15 @@ export class ChatTerminalToolProgressPart extends BaseChatToolInvocationSubPart
wordWrap: 'on'
}
};
this.markdownPart = this._register(_instantiationService.createInstance(ChatMarkdownContentPart, chatMarkdownContent, context, editorPool, false, codeBlockStartIndex, renderer, {}, currentWidthDelegate(), codeBlockModelCollection, { codeBlockRenderOptions }));
const markdownOptions: IChatMarkdownContentPartOptions = {
codeBlockRenderOptions,
accessibilityOptions: pastTenseMessage ? {
statusMessage: localize('terminalToolCommand', '{0}', stripIcons(pastTenseMessage))
} : undefined
};
this.markdownPart = this._register(_instantiationService.createInstance(ChatMarkdownContentPart, chatMarkdownContent, context, editorPool, false, codeBlockStartIndex, renderer, {}, currentWidthDelegate(), codeBlockModelCollection, markdownOptions));
this._register(this.markdownPart.onDidChangeHeight(() => this._onDidChangeHeight.fire()));
elements.message.append(this.markdownPart.domNode);