vscode-docs icon indicating copy to clipboard operation
vscode-docs copied to clipboard

Add section to UX guidelines for hover

Open kkbrooks opened this issue 10 months ago • 1 comments

What to include

  • Different hover styles
  • When to use each one
  • Examples

To do

  • [ ] Research existing hover documentation
  • [ ] Determine what applies to our use cases
  • [ ] Determine what needs to be written from scratch
  • [ ] Create decision tree/flow diagram to help people make the right choice

fyi @Tyriar

kkbrooks avatar Mar 11 '25 17:03 kkbrooks

Here are my notes I presented and action items at the end:

Hover consistency

Background

  • Rich content
  • Better looking than standard
  • More control

Custom vs native

The custom hover is mostly spread throughout the workbench but there are some cases where title is still used:

Image

Image

Image

Default setupDelayedHover

setupDelayedHover(target, { content })

Shows above the target element, aligned to the top-left.

Image

This top-left behavior originated from monaco.

Image

Default setupDelayedHoverAtMouse

setupDelayedHoverAtMouse({ content })

Shows just below and to the right of the cursor.

Image

This aligns closest with the native title hover.

Locking

Normally you can only mouse over the hover if it contains a link or action in the status bar.

Holding alt will "lock" the hover, adding a 2px border and making the hover not go away when the mouse is moved, regardless of the specific options used. This is an accessibility feature useful to all to select text or when we explicitly hideOnHover.

Options

There are many options that allow devs a lot of control on how these hovers are shown. The biggest one being showPointer which centers the hover and adds a pointer.

Some examples:

Activity bar

Image

this._register(this.hoverService.setupDelayedHover(this.container, () => ({
	content: this.computeTitle(),
	position: {
		hoverPosition: this.options.hoverOptions.position(),
	},
	persistence: {
		hideOnKeyDown: true,
	},
	appearance: {
		showPointer: true,
		compact: true,
	}
}), { groupId: 'composite-bar-actions' }));

Terminal tab

Image

return this._hoverService.showDelayedHover({
    ...options,
    actions: context.hoverActions,
    target: element,
    appearance: {
        showPointer: true
    },
    position: {
        hoverPosition: this._terminalConfigurationService.config.tabs.location === 'left' ? HoverPosition.RIGHT : HoverPosition.LEFT
    }
}, { groupId: 'terminal-tabs-list' });

Extension view item

Image

This uses the simpler API meaning it must manage the groupId and delay logic itself:

return this.hoverService.showHover({
	...options,
	additionalClasses: ['extension-hover'],
	position: {
		hoverPosition: this.options.position(),
		forcePosition: true,
	},
	persistence: {
		hideOnKeyDown: true,
	}
}, focus);

Questions

  • When should we use the 3 main types?
    • At mouse (no pointer)
    • Aligned with element/text (no pointer)
    • With pointer and centered
      • Should this be the default for showDelayedHover? Should we have a showDelayedHoverWithPointer?
      • Naming could be "PointerHover" and "MouseHover"?
        • TextHover vs Regular (pointer)?
  • Should hideOnKeyDown: true be the default?
    • Probably flip default, understand why
  • compact is used inconsistently. When should we use this?
  • Could we get rid of forcePosition if we handled the small space case better?
    • A lot of times this is used to force a horizontal only position.
    • If we marked a hover as horizontally (sidebar) or vertically (status bar) positioned, maybe we could avoid being explicit about the exact position and avoid the need for forcePosition as it's implied?

Internal API for the VS Code devs: https://github.com/microsoft/vscode/blob/d81f6ad5b8fe26ed793a47e6911d75bafee7b3de/src/vs/base/browser/ui/hover/hover.ts#L12-L376

Action items

  • UX to dig up MS guidelines, we should read those and come up with our own guidelines
  • hideOnKeyDown: true should be the default? Maybe we don't need it at all?
  • compact: true is a special case, we need clear guidelines to follow
  • Add hoverPosition: 'horizontal' | 'vertical' which should render forcePosition maybe obsolete completely and simplify usage
  • Aligning with text should be a special case not the default
  • Change showHover to showInstantHover, and showDelayedHover* to showHover*?
    • showDelayedHover -> showHoverAtText
    • showDelayedHoverAtMouse -> showHoverAtMouse
    • showDelayedHover will default showPointer: true?

Tyriar avatar Mar 12 '25 12:03 Tyriar