Skip to content

Replace tooltip with Reka UI#27029

Open
HZooly wants to merge 20 commits intomainfrom
hugo/cms-1123-replace-custom-v-tooltip-with-reka-ui
Open

Replace tooltip with Reka UI#27029
HZooly wants to merge 20 commits intomainfrom
hugo/cms-1123-replace-custom-v-tooltip-with-reka-ui

Conversation

@HZooly
Copy link
Copy Markdown
Member

@HZooly HZooly commented Apr 2, 2026

Scope

What's changed:

  • Replace the custom v-tooltip directive with one with Reka-UI's tooltip primitives
  • Add a useGlobalTooltip composable that manages a single shared reactive tooltip state (open/closed, content, position, delay)
  • Add an AppTooltip singleton component mounted at the app root, which renders the single Reka-UI TooltipContent driven by the composable
  • Rewrite the v-tooltip directive as a thin bridge that calls openTooltip/closeTooltip on mouse and keyboard focus events
  • Add keyboard accessibility: focus/blur event listeners trigger the tooltip for keyboard users
  • Use force-mount on TooltipContent so #app-tooltip-content is always present in the DOM for screen readers
  • Simplify tooltip SCSS to use Reka-UI data-state attributes; remove manual animation classes and all custom arrow CSS

Potential Risks / Drawbacks

  • force-mount keeps TooltipContent in the DOM at all times; the content reflects the last-hovered element when closed, which is read by screen readers via aria-describedby on focus
  • RTL support for tooltip positioning was previously handled manually in the directive; it is now delegated entirely to Reka-UI's floating-ui internals — needs visual verification in RTL layouts

Tested Scenarios

  • Hover over an element with v-tooltip and confirm the tooltip appears after the 500ms delay
  • Move quickly between two tooltipped elements and confirm no positional flash or content bleed from the first tooltip
  • Use v-tooltip.instant and confirm the tooltip appears immediately without a fade-in transition
  • Use v-tooltip.bottom, .left, .right, .start, .end modifiers and confirm correct placement
  • Tab to a focusable element with v-tooltip and confirm the tooltip opens and the correct description is announced
  • Unmount an element with v-tooltip while its tooltip is visible and confirm the tooltip closes cleanly
  • Use v-tooltip.inverted and v-tooltip.monospace and confirm the correct CSS classes are applied
  • Disabled elements tooltip should appear quicker (125ms)

Review Notes / Questions

  • I would like reviewers to verify the RTL layout behavior — the old directive manually adjusted left offsets for RTL; Reka-UI should handle this via floating-ui
  • Special attention should be paid to the force-mount + aria-describedby accessibility approach — the tradeoff is that screen readers always find the element in the DOM, but its content reflects the last-opened tooltip rather than being empty when closed

Checklist

  • Added or updated tests
  • Documentation PR created here or not required
  • OpenAPI package PR created here or not required

Fixes #25519

@HZooly HZooly requested a review from AlexGaillard as a code owner April 2, 2026 14:33
@linear
Copy link
Copy Markdown

linear Bot commented Apr 2, 2026

@HZooly HZooly changed the title Hugo/cms 1123 replace custom v tooltip with reka UI Replace tooltip with Reka UI Apr 2, 2026
@AlexGaillard AlexGaillard requested a review from robluton April 3, 2026 14:08
Comment thread app/src/composables/use-global-tooltip.ts Outdated
Co-authored-by: Rob Luton <rob.luton@gmail.com>
Comment thread app/src/directives/tooltip.ts Outdated
element.addEventListener('mouseleave', onLeaveTooltip);
}
}
const SIDES = ['top', 'bottom', 'left', 'right'] as const;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is also defined in the composable. Let's import the type from the composable so we have a single source of truth.

Comment thread app/src/directives/tooltip.ts Outdated
export function createEnterHandler(element: HTMLElement, binding: DirectiveBinding) {
return (): void => {
const tooltip = getTooltip();
const ALIGNS = ['start', 'center', 'end'] as const;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above. Let's import this type from the composable so we have a single source of truth.

Copy link
Copy Markdown
Contributor

@robluton robluton left a comment

Choose a reason for hiding this comment

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

LGTM! 🎸

@HZooly HZooly mentioned this pull request Apr 15, 2026
3 tasks
@formfcw formfcw self-requested a review April 17, 2026 18:18
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.

Replace custom v-tooltip with Reka UI

4 participants