Change:
Testing This would benefit from an underline instead of the bold treatment to match the rendering we use in the workspace banner links (e.g. restricted mode) <img width="490" alt="CleanShot 2023-06-26 at 21 53 54 src=""
I also think its hard to discover, but I think we are not using underline for links in hovers so far?
We also do not show underlines in other places we show markdown in hovers: <img width="485" alt="image" src=""I used bold because the blue background of the hover made the contrast poor with our usual blue link color. We could use another color instead though.
I think the intent of the blue color in the message widget is to draw more attention, i.e. giving the signal of an information message vs. just being a normal tooltip. But maybe we can make the background color of the widget the same as hovers and then user blue color for links. I think that way we can still keep the blue border but it will not collide with the links.
Sample with a mix of hover colors and info colors for border: <img width="764" alt="image" src=""
And in dark theme: ! Changes I did: use hover colors use the same border radius of as in editor hovers allow to tab into the message with keyboard to invoke the link within

Discussion:
} .monaco-editor .monaco-editor-overlaymessage .message { <del> padding: 1px 4px; color: var(--vscode-inputValidation-infoForeground); background-color: var(--vscode-inputValidation-infoBackground); </del> <ins> padding: 2px 4px; color: var(--vscode-editorHoverWidget-foreground); background-color: var(--vscode-editorHoverWidget-background); </ins> border: 1px solid var(--vscode-inputValidation-infoBorder); <ins> border-radius: 3px; </ins> } .monaco-editor .monaco-editor-overlaymessage .message p {

} .monaco-editor .monaco-editor-overlaymessage .message a { <del> font-weight: bold; color: var(--vscode-inputValidation-infoForeground); </del> <ins> color: var(--vscode-textLink-foreground); } .monaco-editor .monaco-editor-overlaymessage .message a:hover { color: var(--vscode-textLink-activeForeground); </ins> } .monaco-editor.hc-black .monaco-editor-overlaymessage .message,

z-index: 1000; border-width: 8px; position: absolute; <ins> left: 2px; </ins> } .monaco-editor .monaco-editor-overlaymessage .anchor.top {

import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; import { alert } from 'vs/base/browser/ui/aria/aria'; <del> import { TimeoutTimer } from 'vs/base/common/async'; </del> <ins> import { Event } from 'vs/base/common/event'; </ins> import { IMarkdownString, isMarkdownString } from 'vs/base/common/htmlContent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';

private readonly _messageWidget = new MutableDisposable<MessageWidget>(); private readonly _messageListeners = new DisposableStore(); private _message: { element: HTMLElement; dispose: () => void } | undefined; <del> private _focus: boolean = false; </del> <ins> private _mouseOverMessage: boolean = false; </ins> constructor( editor: ICodeEditor,

}) : undefined; this._messageWidget.value = new MessageWidget(this._editor, position, typeof message === 'string' ? message : this._message!.element); <del> // close on blur, cursor, model change, dispose this._messageListeners.add(this._editor.onDidBlurEditorText(() => { if (!this._focus) { this.closeMessage(); </del> <ins> // close on blur (debounced to allow to tab into the message), cursor, model change, dispose this._messageListeners.add(Event.debounce(this._editor.onDidBlurEditorText, (last, event) => event, 0)(() => { if (this._mouseOverMessage) { return; // override when mouse over message } if (this._messageWidget.value && dom.isAncestor(document.activeElement, this._messageWidget.value.getDomNode())) { return; // override when focus is inside the message </ins> } <ins> this.closeMessage(); </ins> } )); this._messageListeners.add(this._editor.onDidChangeCursorPosition(() => this.closeMessage())); this._messageListeners.add(this._editor.onDidDispose(() => this.closeMessage())); this._messageListeners.add(this._editor.onDidChangeModel(() => this.closeMessage())); <del> this._messageListeners.add(dom.addDisposableListener(this._messageWidget.value.getDomNode(), dom.EventType.MOUSE_ENTER, () => this._focus = true, true)); this._messageListeners.add(dom.addDisposableListener(this._messageWidget.value.getDomNode(), dom.EventType.MOUSE_LEAVE, () => this._focus = false, true)); // 3sec this._messageListeners.add(new TimeoutTimer(() => this.closeMessage(), 3000)); </del> <ins> this._messageListeners.add(dom.addDisposableListener(this._messageWidget.value.getDomNode(), dom.EventType.MOUSE_ENTER, () => this._mouseOverMessage = true, true)); this._messageListeners.add(dom.addDisposableListener(this._messageWidget.value.getDomNode(), dom.EventType.MOUSE_LEAVE, () => this._mouseOverMessage = false, true)); </ins> // close on mouse move let bounds: Range;