Change:
Testing My first reaction for how to stop dictation in the editor was to click the flashing microphone. It would be cool if something happened when the flashing microphone is clicked.
I will turn this into a real with action and hover.

Discussion:
max-width: var(--vscode-editor-dictation-widget-width); } <del> .monaco-editor .editor-dictation-widget .codicon.codicon-mic-filled { display: flex; align-items: center; width: 16px; height: 16px; } </del> .monaco-editor .editor-dictation-widget.recording .codicon.codicon-mic-filled { color: var(--vscode-activityBarBadge-background); animation: editor-dictation-animation 1s infinite;

*--------------------------------------------------------------------------------------------*/ import 'vs/css!./editorDictation'; <del> import { localize2 } from 'vs/nls'; import { IDimension, h, reset } from 'vs/base/browser/dom'; </del> <ins> import { localize, localize2 } from 'vs/nls'; import { IDimension } from 'vs/base/browser/dom'; </ins> import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { HasSpeechProvider, ISpeechService, SpeechToTextStatus } from 'vs/workbench/contrib/speech/common/speechService'; <del> import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; </del> import { Codicon } from 'vs/base/common/codicons'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { EditorAction2, EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions';

import { Range } from 'vs/editor/common/core/range'; import { registerAction2 } from 'vs/platform/actions/common/actions'; import { assertIsDefined } from 'vs/base/common/types'; <ins> import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { toAction } from 'vs/base/common/actions'; import { ThemeIcon } from 'vs/base/common/themables'; </ins> const EDITOR_DICTATION_IN_PROGRESS = new RawContextKey<boolean>('editorDictation.inProgress', false); const VOICE_CATEGORY = localize2('voiceCategory', "Voice");

export class EditorDictationStopAction extends EditorAction2 { <ins> static readonly ID = 'workbench.action.editorDictation.stop'; </ins> constructor() { super({ <del> id: 'workbench.action.editorDictation.stop', </del> <ins> id: EditorDictationStopAction.ID, </ins> title: localize2('stopDictation', "Stop Dictation in Editor"), category: VOICE_CATEGORY, precondition: EDITOR_DICTATION_IN_PROGRESS,

readonly allowEditorOverflow = true; private readonly domNode = document.createElement('div'); <del> private readonly elements = h('.editor-dictation-widget@main', [h('span@mic')]); constructor(private readonly editor: ICodeEditor) { </del> <ins> constructor(private readonly editor: ICodeEditor, keybindingService: IKeybindingService) { </ins> super(); <del> this.domNode.appendChild(this.elements.root); this.domNode.style.zIndex = '1000'; reset(this.elements.mic, renderIcon(Codicon.micFilled)); </del> <ins> const actionBar = this._register(new ActionBar(this.domNode)); const stopActionKeybinding = keybindingService.lookupKeybinding(EditorDictationStopAction.ID)?.getLabel(); actionBar.push(toAction({ id: EditorDictationStopAction.ID, label: stopActionKeybinding ? localize('stopDictationShort1', "Stop Dictation ({0})", stopActionKeybinding) : localize('stopDictationShort2', "Stop Dictation"), class: ThemeIcon.asClassName(Codicon.micFilled), run: () => EditorDictation.get(editor)?.stop() }), { icon: true, label: false, keybinding: stopActionKeybinding }); this.domNode.classList.add('editor-dictation-widget'); this.domNode.appendChild(actionBar.domNode); </ins> } getId(): string {

const lineHeight = this.editor.getOption(EditorOption.lineHeight); const width = this.editor.getLayoutInfo().contentWidth * 0.7; <del> this.elements.main.style.setProperty('--vscode-editor-dictation-widget-height', `${lineHeight}px`); this.elements.main.style.setProperty('--vscode-editor-dictation-widget-width', `${width}px`); </del> <ins> this.domNode.style.setProperty('--vscode-editor-dictation-widget-height', `${lineHeight}px`); this.domNode.style.setProperty('--vscode-editor-dictation-widget-width', `${width}px`); </ins> return null; }

} active(): void { <del> this.elements.main.classList.add('recording'); </del> <ins> this.domNode.classList.add('recording'); </ins> } hide() { <del> this.elements.main.classList.remove('recording'); </del> <ins> this.domNode.classList.remove('recording'); </ins> this.editor.removeContentWidget(this); } }

return editor.getContribution<EditorDictation>(EditorDictation.ID); } <del> private readonly widget = this._register(new DictationWidget(this.editor)); </del> <ins> private readonly widget = this._register(new DictationWidget(this.editor, this.keybindingService)); </ins> private readonly editorDictationInProgress = EDITOR_DICTATION_IN_PROGRESS.bindTo(this.contextKeyService); private sessionDisposables = this._register(new MutableDisposable());

constructor( private readonly editor: ICodeEditor, @ISpeechService private readonly speechService: ISpeechService, <del> @IContextKeyService private readonly contextKeyService: IContextKeyService </del> <ins> @IContextKeyService private readonly contextKeyService: IContextKeyService, @IKeybindingService private readonly keybindingService: IKeybindingService </ins> ) { super(); }