diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts b/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts index 3de50cb8937..149ee4cbff5 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts @@ -8,7 +8,7 @@ import { Disposable, MutableDisposable } from '../../../../base/common/lifecycle import { SimpleIconLabel } from '../../../../base/browser/ui/iconLabel/simpleIconLabel.js'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js'; -import { IStatusbarEntry, ShowTooltipCommand, StatusbarEntryKinds } from '../../../services/statusbar/browser/statusbar.js'; +import { IStatusbarEntry, isTooltipWithCommands, ShowTooltipCommand, StatusbarEntryKinds, TooltipContent } from '../../../services/statusbar/browser/statusbar.js'; import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from '../../../../base/common/actions.js'; import { IThemeService } from '../../../../platform/theme/common/themeService.js'; import { ThemeColor } from '../../../../base/common/themables.js'; @@ -24,7 +24,7 @@ import { spinningLoading, syncing } from '../../../../platform/theme/common/icon import { isMarkdownString, markdownStringEqual } from '../../../../base/common/htmlContent.js'; import { IHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate.js'; import { Gesture, EventType as TouchEventType } from '../../../../base/browser/touch.js'; -import type { IManagedHover } from '../../../../base/browser/ui/hover/hover.js'; +import { IManagedHover, IManagedHoverOptions } from '../../../../base/browser/ui/hover/hover.js'; import { IHoverService } from '../../../../platform/hover/browser/hover.js'; export class StatusbarEntryItem extends Disposable { @@ -116,11 +116,26 @@ export class StatusbarEntryItem extends Disposable { // Update: Hover if (!this.entry || !this.isEqualTooltip(this.entry, entry)) { - const hoverContents = isMarkdownString(entry.tooltip) ? { markdown: entry.tooltip, markdownNotSupportedFallback: undefined } : entry.tooltip; - if (this.hover) { - this.hover.update(hoverContents); + let hoverOptions: IManagedHoverOptions | undefined; + let hoverTooltip: TooltipContent | undefined; + if (isTooltipWithCommands(entry.tooltip)) { + hoverTooltip = entry.tooltip.content; + hoverOptions = { + actions: entry.tooltip.commands.map(command => ({ + commandId: command.id, + label: command.title, + run: () => this.executeCommand(command) + })) + }; } else { - this.hover = this._register(this.hoverService.setupManagedHover(this.hoverDelegate, this.container, hoverContents)); + hoverTooltip = entry.tooltip; + } + + const hoverContents = isMarkdownString(hoverTooltip) ? { markdown: hoverTooltip, markdownNotSupportedFallback: undefined } : hoverTooltip; + if (this.hover) { + this.hover.update(hoverContents, hoverOptions); + } else { + this.hover = this._register(this.hoverService.setupManagedHover(this.hoverDelegate, this.container, hoverContents, hoverOptions)); } } diff --git a/src/vs/workbench/services/statusbar/browser/statusbar.ts b/src/vs/workbench/services/statusbar/browser/statusbar.ts index 3b3f1f1fe17..7c81333e416 100644 --- a/src/vs/workbench/services/statusbar/browser/statusbar.ts +++ b/src/vs/workbench/services/statusbar/browser/statusbar.ts @@ -8,6 +8,7 @@ import { DisposableStore, IDisposable } from '../../../../base/common/lifecycle. import { ThemeColor } from '../../../../base/common/themables.js'; import { Command } from '../../../../editor/common/languages.js'; import { IMarkdownString } from '../../../../base/common/htmlContent.js'; +import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js'; import { ColorIdentifier } from '../../../../platform/theme/common/colorRegistry.js'; import { IAuxiliaryStatusbarPart, IStatusbarEntryContainer } from '../../../browser/parts/statusbar/statusbarPart.js'; @@ -111,6 +112,19 @@ export interface IStatusbarStyleOverride { export type StatusbarEntryKind = 'standard' | 'warning' | 'error' | 'prominent' | 'remote' | 'offline'; export const StatusbarEntryKinds: StatusbarEntryKind[] = ['standard', 'warning', 'error', 'prominent', 'remote', 'offline']; +export type TooltipContent = string | IMarkdownString | IManagedHoverTooltipMarkdownString | HTMLElement; + +export interface ITooltipWithCommands { + readonly content: TooltipContent; + readonly commands: Command[]; +} + +export function isTooltipWithCommands(thing: unknown): thing is ITooltipWithCommands { + const candidate = thing as ITooltipWithCommands | undefined; + + return !!candidate?.content && Array.isArray(candidate?.commands); +} + /** * A declarative way of describing a status bar entry */ @@ -141,9 +155,11 @@ export interface IStatusbarEntry { readonly role?: string; /** - * An optional tooltip text to show when you hover over the entry + * An optional tooltip text to show when you hover over the entry. + * + * Use `ITooltipWithCommands` to show a tooltip with commands in hover footer area. */ - readonly tooltip?: string | IMarkdownString | HTMLElement; + readonly tooltip?: TooltipContent | ITooltipWithCommands; /** * An optional color to use for the entry.