diff --git a/src/vs/base/browser/formattedTextRenderer.ts b/src/vs/base/browser/formattedTextRenderer.ts index 14f7493fd463a..4af9e9ed4e9f6 100644 --- a/src/vs/base/browser/formattedTextRenderer.ts +++ b/src/vs/base/browser/formattedTextRenderer.ts @@ -91,6 +91,7 @@ function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionH child = document.createElement('code'); } else if (treeNode.type === FormatType.Action && actionHandler) { const a = document.createElement('a'); + a.setAttribute('data-content-index', String(treeNode.index)); actionHandler.disposables.add(DOM.addStandardDisposableListener(a, 'click', (event) => { actionHandler.callback(String(treeNode.index), event); })); diff --git a/src/vs/base/test/browser/formattedTextRenderer.test.ts b/src/vs/base/test/browser/formattedTextRenderer.test.ts index 40147706cd51e..ae9108a37cebd 100644 --- a/src/vs/base/test/browser/formattedTextRenderer.test.ts +++ b/src/vs/base/test/browser/formattedTextRenderer.test.ts @@ -78,6 +78,7 @@ suite('FormattedTextRenderer', () => { } }); assert.strictEqual(result.innerHTML, 'action'); + assert.strictEqual(result.firstChild!.getAttribute('data-content-index'), '0'); const event: MouseEvent = document.createEvent('MouseEvent'); event.initEvent('click', true, true); @@ -97,6 +98,7 @@ suite('FormattedTextRenderer', () => { } }); assert.strictEqual(result.innerHTML, 'action'); + assert.strictEqual(result.firstChild!.firstChild!.firstChild!.getAttribute('data-content-index'), '0'); const event: MouseEvent = document.createEvent('MouseEvent'); event.initEvent('click', true, true); @@ -117,6 +119,7 @@ suite('FormattedTextRenderer', () => { } }); assert.strictEqual(result.innerHTML, 'action'); + assert.strictEqual(result.firstChild!.firstChild!.firstChild!.firstChild!.getAttribute('data-content-index'), '0'); const event: MouseEvent = document.createEvent('MouseEvent'); event.initEvent('click', true, true); diff --git a/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts index 3d1899f8ec785..f1341320d59c7 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts @@ -6,6 +6,7 @@ import { $, addDisposableListener, getActiveWindow } from '../../../../../base/browser/dom.js'; import { IContentActionHandler, renderFormattedText } from '../../../../../base/browser/formattedTextRenderer.js'; import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js'; +import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js'; import { status } from '../../../../../base/browser/ui/aria/aria.js'; import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from '../../../../../base/common/actions.js'; import { Event } from '../../../../../base/common/event.js'; @@ -271,6 +272,18 @@ class EmptyTextEditorHintContentWidget extends Disposable implements IContentWid // eslint-disable-next-line no-restricted-syntax for (const anchor of hintElement.querySelectorAll('a')) { anchor.style.cursor = 'pointer'; + anchor.tabIndex = 0; + anchor.setAttribute('role', 'button'); + anchor.addEventListener('keydown', (e: KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + e.stopPropagation(); + const index = anchor.getAttribute('data-content-index'); + if (index !== null) { + hintHandler.callback(index, new StandardKeyboardEvent(e)); + } + } + }); } return { hintElement, ariaLabel };