From c93e674e1c3beac8fca98fc85e2171fa29193b80 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 17 Jan 2026 02:42:05 -0800 Subject: [PATCH 1/2] Optimize initial hint at low widths Fixes #288118 --- .../browser/media/terminalInitialHint.css | 22 ++++++++- .../terminal.initialHint.contribution.ts | 45 ++++++++++++++----- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/media/terminalInitialHint.css b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/media/terminalInitialHint.css index 047e72f58da..c169a9d60bb 100644 --- a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/media/terminalInitialHint.css +++ b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/media/terminalInitialHint.css @@ -8,7 +8,27 @@ container-type: inline-size; } -@container (max-width: 300px) { +.monaco-workbench .terminal-initial-hint .terminal-initial-hint-separator { + display: none; +} + +.monaco-workbench .terminal-initial-hint .terminal-initial-hint-compact { + display: none !important; +} + +@container (max-width: 500px) { + .monaco-workbench .terminal-initial-hint .terminal-initial-hint-prose { + display: none !important; + } + .monaco-workbench .terminal-initial-hint .terminal-initial-hint-separator { + display: block; + } + .monaco-workbench .terminal-initial-hint .terminal-initial-hint-compact { + display: inline !important; + } +} + +@container (max-width: 240px) { .monaco-workbench .terminal-initial-hint > * { display: none !important; } diff --git a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts index 1953144be29..0b3db8501b9 100644 --- a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts @@ -282,11 +282,13 @@ class TerminalInitialHintWidget extends Disposable { if (terminalAgents?.length) { const actionPart = localize('emptyHintText', 'Open chat {0}. ', keybindingHintLabel); - const [before, after] = actionPart.split(keybindingHintLabel).map((fragment) => { - const hintPart = $('a', undefined, fragment); - this._toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CLICK, handleClick)); - return hintPart; - }); + const [beforeText, afterText] = actionPart.split(keybindingHintLabel); + const before = $('a', undefined, beforeText); + this._toDispose.add(dom.addDisposableListener(before, dom.EventType.CLICK, handleClick)); + const after = $('span.terminal-initial-hint-prose', undefined); + const afterLink = $('a', undefined, afterText); + this._toDispose.add(dom.addDisposableListener(afterLink, dom.EventType.CLICK, handleClick)); + after.appendChild(afterLink); hintElement.appendChild(before); @@ -299,6 +301,7 @@ class TerminalInitialHintWidget extends Disposable { this._toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CLICK, handleClick)); hintElement.appendChild(after); + hintElement.appendChild($('span.terminal-initial-hint-separator')); ariaLabelParts.push(actionPart); } @@ -327,11 +330,13 @@ class TerminalInitialHintWidget extends Disposable { this._commandService.executeCommand(TerminalSuggestCommandId.TriggerSuggest); }; - const [suggestBefore, suggestAfter] = suggestActionPart.split(suggestKeybindingLabel).map((fragment) => { - const hintPart = $('a', undefined, fragment); - this._toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CLICK, handleSuggestClick)); - return hintPart; - }); + const [suggestBeforeText, suggestAfterText] = suggestActionPart.split(suggestKeybindingLabel); + const suggestBefore = $('a', undefined, suggestBeforeText); + this._toDispose.add(dom.addDisposableListener(suggestBefore, dom.EventType.CLICK, handleSuggestClick)); + const suggestAfter = $('span.terminal-initial-hint-prose', undefined); + const suggestAfterLink = $('a', undefined, suggestAfterText); + this._toDispose.add(dom.addDisposableListener(suggestAfterLink, dom.EventType.CLICK, handleSuggestClick)); + suggestAfter.appendChild(suggestAfterLink); hintElement.appendChild(suggestBefore); @@ -343,6 +348,7 @@ class TerminalInitialHintWidget extends Disposable { this._toDispose.add(dom.addDisposableListener(suggestLabel.element, dom.EventType.CLICK, handleSuggestClick)); hintElement.appendChild(suggestAfter); + hintElement.appendChild($('span.terminal-initial-hint-separator')); ariaLabelParts.push(suggestActionPart); } @@ -352,15 +358,30 @@ class TerminalInitialHintWidget extends Disposable { return undefined; } + // Dismiss hint - normal mode version const typeToDismiss = localize({ key: 'hintTextDismiss', comment: [ 'Preserve double-square brackets and their order', ] - }, ' Start typing to dismiss or [[don\'t show]] this again.'); + }, '[[don\'t show]] this again.'); const typeToDismissRendered = renderFormattedText(typeToDismiss, { actionHandler: dontShowHintHandler }); - typeToDismissRendered.classList.add('detail'); + typeToDismissRendered.classList.add('detail', 'terminal-initial-hint-prose'); + + const proseBefore = $('span.terminal-initial-hint-prose', undefined, ' Start typing to dismiss or '); + hintElement.appendChild(proseBefore); hintElement.appendChild(typeToDismissRendered); + + // Dismiss hint - compact mode version + const typeToDismissCompact = localize({ + key: 'hintTextDismissCompact', + comment: [ + 'Preserve double-square brackets and their order', + ] + }, '[[Don\'t show this again]]'); + const typeToDismissCompactRendered = renderFormattedText(typeToDismissCompact, { actionHandler: dontShowHintHandler }); + typeToDismissCompactRendered.classList.add('detail', 'terminal-initial-hint-compact'); + hintElement.appendChild(typeToDismissCompactRendered); ariaLabelParts.push(localize('hintTextDismissAriaLabel', 'Start typing to dismiss or don\'t show this again.')); return { ariaLabel: ariaLabelParts.join(' '), hintHandler, hintElement }; From 7eec263c7cc28e7c1a0f46881a24b3c8e92f3d06 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 17 Jan 2026 03:25:48 -0800 Subject: [PATCH 2/2] Address feedback --- .../terminal.initialHint.contribution.ts | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts index 0b3db8501b9..e3a1c39329d 100644 --- a/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/inlineHint/browser/terminal.initialHint.contribution.ts @@ -234,6 +234,21 @@ class TerminalInitialHintWidget extends Disposable { })); } + /** + * Creates wrapped hint elements with click listeners for responsive hint layouts. + * Returns a before link and an after prose span containing a link. + */ + private _createWrappedHintElements(text: string, keybindingLabel: string, clickHandler: () => void): { before: HTMLAnchorElement; after: HTMLSpanElement } { + const [beforeText, afterText] = text.split(keybindingLabel); + const before = $('a', undefined, beforeText) as HTMLAnchorElement; + this._toDispose.add(dom.addDisposableListener(before, dom.EventType.CLICK, clickHandler)); + const after = $('span.terminal-initial-hint-prose', undefined) as HTMLSpanElement; + const afterLink = $('a', undefined, afterText); + this._toDispose.add(dom.addDisposableListener(afterLink, dom.EventType.CLICK, clickHandler)); + after.appendChild(afterLink); + return { before, after }; + } + private _getHintInlineChat() { const ariaLabelParts: string[] = []; @@ -282,13 +297,7 @@ class TerminalInitialHintWidget extends Disposable { if (terminalAgents?.length) { const actionPart = localize('emptyHintText', 'Open chat {0}. ', keybindingHintLabel); - const [beforeText, afterText] = actionPart.split(keybindingHintLabel); - const before = $('a', undefined, beforeText); - this._toDispose.add(dom.addDisposableListener(before, dom.EventType.CLICK, handleClick)); - const after = $('span.terminal-initial-hint-prose', undefined); - const afterLink = $('a', undefined, afterText); - this._toDispose.add(dom.addDisposableListener(afterLink, dom.EventType.CLICK, handleClick)); - after.appendChild(afterLink); + const { before, after } = this._createWrappedHintElements(actionPart, keybindingHintLabel, handleClick); hintElement.appendChild(before); @@ -330,13 +339,7 @@ class TerminalInitialHintWidget extends Disposable { this._commandService.executeCommand(TerminalSuggestCommandId.TriggerSuggest); }; - const [suggestBeforeText, suggestAfterText] = suggestActionPart.split(suggestKeybindingLabel); - const suggestBefore = $('a', undefined, suggestBeforeText); - this._toDispose.add(dom.addDisposableListener(suggestBefore, dom.EventType.CLICK, handleSuggestClick)); - const suggestAfter = $('span.terminal-initial-hint-prose', undefined); - const suggestAfterLink = $('a', undefined, suggestAfterText); - this._toDispose.add(dom.addDisposableListener(suggestAfterLink, dom.EventType.CLICK, handleSuggestClick)); - suggestAfter.appendChild(suggestAfterLink); + const { before: suggestBefore, after: suggestAfter } = this._createWrappedHintElements(suggestActionPart, suggestKeybindingLabel, handleSuggestClick); hintElement.appendChild(suggestBefore); @@ -348,6 +351,7 @@ class TerminalInitialHintWidget extends Disposable { this._toDispose.add(dom.addDisposableListener(suggestLabel.element, dom.EventType.CLICK, handleSuggestClick)); hintElement.appendChild(suggestAfter); + // Layout-only separator; visibility and spacing are controlled via CSS (including responsive breakpoints). hintElement.appendChild($('span.terminal-initial-hint-separator')); ariaLabelParts.push(suggestActionPart); @@ -368,7 +372,7 @@ class TerminalInitialHintWidget extends Disposable { const typeToDismissRendered = renderFormattedText(typeToDismiss, { actionHandler: dontShowHintHandler }); typeToDismissRendered.classList.add('detail', 'terminal-initial-hint-prose'); - const proseBefore = $('span.terminal-initial-hint-prose', undefined, ' Start typing to dismiss or '); + const proseBefore = $('span.terminal-initial-hint-prose', undefined, localize('hintTextDismissProse', " Start typing to dismiss or ")); hintElement.appendChild(proseBefore); hintElement.appendChild(typeToDismissRendered);