Skip to content

feat: add tooltip support for menu items#11549

Open
vursen wants to merge 6 commits intomainfrom
feat/menu-item-tooltips
Open

feat: add tooltip support for menu items#11549
vursen wants to merge 6 commits intomainfrom
feat/menu-item-tooltips

Conversation

@vursen
Copy link
Copy Markdown
Contributor

@vursen vursen commented Apr 23, 2026

Description

Fixes #10415

Adds optional tooltip support to <vaadin-context-menu> and <vaadin-menu-bar> items rendered via the items API. Setting an item's tooltip property causes a slotted <vaadin-tooltip slot="tooltip"> to open on hover and keyboard focus. The slotted tooltip is shared between root items and any nested sub-menus, so hover/hide delays, the generator, and the position can be configured in one place.

<vaadin-context-menu>
  <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
</vaadin-context-menu>
contextMenu.items = [
  { text: 'Open', tooltip: 'Open the selected file' },
  { text: 'Delete', disabled: true, tooltip: 'Not available right now' },
];

Per-item position

  • Menu-bar root buttons default to bottom.
  • Items with a sub-menu default to start so the tooltip doesn't overlap the opening sub-menu.
  • All other items, including disabled ones (whose sub-menus cannot be opened), default to end.
  • Items can override the default with a tooltipPosition property.
  • A position set on the slotted <vaadin-tooltip> element always wins over per-item values.

Disabled items

Combined with the accessibleDisabledMenuItems feature flag from #11541, this is the primary motivation: disabled items can be hovered / focused and explain why they're unavailable via a tooltip.

Type of change

  • Feature

@vursen vursen force-pushed the feat/menu-item-tooltips branch from 1f73ea3 to 468ec8b Compare April 23, 2026 13:10
@vursen vursen marked this pull request as draft April 23, 2026 13:41
@vursen vursen force-pushed the feat/accessible-disabled-menu-items branch from f0f70d6 to 18f7a62 Compare April 23, 2026 13:43
Base automatically changed from feat/accessible-disabled-menu-items to main April 23, 2026 13:54
@vursen vursen force-pushed the feat/menu-item-tooltips branch 2 times, most recently from 582faae to 0e83e53 Compare April 24, 2026 08:31
@vursen vursen changed the title feat: add tooltip support for context-menu and menu-bar sub-menu items feat: add tooltip support for menu items Apr 24, 2026
@vursen vursen force-pushed the feat/menu-item-tooltips branch from 11cb227 to 197a4ff Compare April 27, 2026 05:36
@vursen vursen changed the base branch from main to refactor/tooltip-controller-open-close April 27, 2026 06:12
Base automatically changed from refactor/tooltip-controller-open-close to main April 27, 2026 07:21
@vursen vursen force-pushed the feat/menu-item-tooltips branch 4 times, most recently from fa51e28 to d771cbd Compare April 27, 2026 09:25
Menu items rendered via the `items` API can now show a tooltip on hover
and keyboard focus by setting their `tooltip` property. A slotted
`<vaadin-tooltip slot="tooltip">` element on the `<vaadin-context-menu>`
or `<vaadin-menu-bar>` is required to render the tooltip; menu-bar
sub-menu items reuse the same tooltip element as the root-level buttons
so the hover and hide delays can be configured in a single place.

Per-item `tooltipPosition` lets callers override where the tooltip opens
relative to the item. Context-menu items and menu-bar sub-menu items
default to `end`, items with a non-empty `children` array default to
`start` so the tooltip doesn't overlap the opening sub-menu, and
menu-bar root buttons fall back to the position configured on the
slotted `<vaadin-tooltip>`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vursen vursen force-pushed the feat/menu-item-tooltips branch from ab92199 to 312901b Compare April 28, 2026 11:38
vursen added 2 commits April 29, 2026 11:12
- Move ContextMenuTooltipController setup into ContextMenuMixin so subclasses get tooltip support automatically.
- Use `target._item` in ContextMenuTooltipController to read the item from rendered list-box children.
- Close (not just untarget) the context-menu tooltip on overlay mouseleave.
- In menu-bar, open hover tooltip for items with children when the sub-menu is closed, and force-close the tooltip when collapsing without focus restore.
@vursen vursen force-pushed the feat/menu-item-tooltips branch from a8a6821 to 07ffc75 Compare April 29, 2026 12:54
vursen added 3 commits April 29, 2026 16:55
Disabled items cannot open their sub-menu, so anchoring the tooltip at
`start` leaves empty space where the sub-menu would have appeared.
Treat disabled parents as leaf items and place the tooltip at `end`.
Document that sub-menu items default to `start`, all others (including
disabled) default to `end`, and an explicit `position` on the slotted
`<vaadin-tooltip>` overrides the per-item default.
@sonarqubecloud
Copy link
Copy Markdown

@vursen vursen marked this pull request as ready for review April 29, 2026 14:24
@vursen vursen requested a review from web-padawan April 30, 2026 08:04

/**
* Controller for the tooltip slotted into a menu-like component (such as
* `<vaadin-context-menu>` or `<vaadin-menu-bar>`). Configures the tooltip
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this could be placed in context-menu package for now.

* @protected
*/
_getItem(_target) {
throw new Error('Must be implemented by subclass');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a need for these errors, this is a private helper anyway. It's enough to add a comment // To be implemented. like we do elsewhere in the codebase.

this._tooltipController.open({ trigger: 'hover' });
});

overlay.addEventListener('mouseleave', (event) => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO these events could be added in a Lit template.

ready() {
super.ready();

this._tooltipController = this.parentElement._tooltipController;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit confusing (we don't reuse controllers this way elsewhere), maybe could add a comment.

<slot name="submenu" slot="submenu"></slot>
</vaadin-context-menu-overlay>

<slot name="tooltip"></slot>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized that we don't have shadow DOM snapshot tests that would fail with this addition.
Please consider adding them in a separate PR so that this one would then be rebased.

});
/** @override */
_getDefaultPosition(target) {
if (target.matches('vaadin-menu-bar-button')) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could use tagName check instead like we usually do in such cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[context-menu] Implement accessible disabled menu items with tooltip support

2 participants