Skip to content

[EuiToolTip] Show tooltip only on keyboard focus#9624

Merged
weronikaolejniczak merged 15 commits intoelastic:mainfrom
weronikaolejniczak:feat/remove-delay-fix-focus-tooltip
May 4, 2026
Merged

[EuiToolTip] Show tooltip only on keyboard focus#9624
weronikaolejniczak merged 15 commits intoelastic:mainfrom
weronikaolejniczak:feat/remove-delay-fix-focus-tooltip

Conversation

@weronikaolejniczak
Copy link
Copy Markdown
Contributor

@weronikaolejniczak weronikaolejniczak commented Apr 29, 2026

Summary

Testing videos

Trigger Behavior
Mouse over, mouse out
Kapture.2026-04-29.at.13.59.03.mp4
Mouse click, mouse out
Kapture.2026-04-29.at.14.01.18.mp4
Keyboard focus, blur or Escape
Kapture.2026-04-29.at.14.01.57.mp4
Auto-focus
Kapture.2026-04-29.at.14.03.44.mp4
Flyout focus return (mouse)
Kapture.2026-04-29.at.14.04.27.mp4
Flyout focus return (keyboard)
Kapture.2026-04-29.at.14.05.08.mp4
Modal focus return (mouse)
Kapture.2026-04-29.at.14.06.27.mp4
Modal focus return (keyboard)
Kapture.2026-04-29.at.14.05.53.mp4
Mobile (emulating touch events)
Kapture.2026-04-29.at.14.50.10.mp4

Accessibility

The behavior has been approved by a11y consultants. It satisfies the Success Criterion 1.4.13 Content on Hover or Focus:

(Level AA)

Where receiving and then removing pointer hover or keyboard focus triggers additional content to become visible and then hidden, the following are true:

Dismissible
A mechanism is available to dismiss the additional content without moving pointer hover or keyboard focus, unless the additional content communicates an input error or does not obscure or replace other content;

Hoverable
If pointer hover can trigger the additional content, then the pointer can be moved over the additional content without the additional content disappearing;

Persistent
The additional content remains visible until the hover or focus trigger is removed, the user dismisses it, or its information is no longer valid.

Some more details here.

API Changes

N/A

Screenshots

N/A

Impact Assessment

Note: Most PRs should be tested in Kibana to help gauge their Impact before merging.

  • 🔴 Breaking changes
  • 💅 Visual changes
  • 🧪 Test impact - consumers relying on tooltip appearing from fireEvent.focus() in tests will need to add simulateFocusVisible. Found 1 such test in Kibana (x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/value_with_space_warning/value_with_space_warning.test.tsx:44).
  • 🔧 Hard to integrate

Impact level: 🟢 Low

Release Readiness

  • Documentation: {link to docs page(s)}
  • Figma: {link to Figma or issue}
  • Migration guide: {steps or link, for breaking/visual changes or deprecations}
  • Adoption plan (new features): {link to issue/doc or outline who will integrate this and where}

QA instructions for reviewer

I added temp stories to make testing easier:

FocusClickVsKeyboard story

  • Hover a button → tooltip appears; move mouse away → tooltip hides
  • Click a button → tooltip appears on hover but hides on mouseout even though the button now has focus
  • Tab to a button → tooltip appears and stays visible until Tab away or Escape but not on mouseout

ArrowKeyNavigation story

  • Tab into the toolbar, then use or arrow keys to move between buttons - tooltip should appear on each button

FocusReturnFlyout

  • Opening the overlay and closing using a mouse - tooltip doesn't appear
  • Opening the overlay and closing using a keyboard - tooltip appears

FocusReturnModal

  • Opening the overlay and closing using a mouse - tooltip doesn't appear
  • Opening the overlay and closing using a keyboard - tooltip appears

FocusReturnPopover

  • Opening the overlay and closing using a mouse - tooltip doesn't appear
  • Opening the overlay and closing using a keyboard - tooltip appears

Smoke-test affected components

Checklist before marking Ready for Review

Reviewer checklist

  • Approved Impact Assessment — Acceptable to merge given the consumer impact.
  • Approved Release Readiness — Docs, Figma, and migration info are sufficient to ship.

@weronikaolejniczak weronikaolejniczak force-pushed the feat/remove-delay-fix-focus-tooltip branch from 94b6fd9 to 23b6524 Compare April 29, 2026 13:23
@weronikaolejniczak weronikaolejniczak marked this pull request as ready for review April 29, 2026 13:24
@weronikaolejniczak weronikaolejniczak requested a review from a team as a code owner April 29, 2026 13:24
Copilot AI review requested due to automatic review settings April 29, 2026 13:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates EuiToolTip focus behavior so tooltips only persist/show on keyboard focus (:focus-visible), preventing unwanted tooltip re-open/persistence for mouse click focus and programmatic focus return (e.g., overlay close).

Changes:

  • Gate tooltip “focus show” logic behind :focus-visible checks (including initial mount/autoFocus handling).
  • Add RTL helper simulateFocusVisible() and update Jest tests to reflect the new focus-visible behavior.
  • Adjust Cypress spec to use real keyboard tabbing for focus-visible coverage and add a changelog entry.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/eui/src/components/tool_tip/tool_tip.tsx Only show/persist tooltip on :focus-visible focus; keep hover behavior
packages/eui/src/components/tool_tip/tool_tip_anchor.tsx Thread focus event through anchor → tooltip handler
packages/eui/src/test/rtl/component_helpers.ts Add simulateFocusVisible() RTL helper for jsdom modality gap
packages/eui/src/components/tool_tip/tool_tip.test.tsx Update unit tests for keyboard-focus-visible vs click-focus behavior
packages/eui/src/components/tool_tip/tool_tip.spec.tsx Update Cypress tests to use realPress('Tab') for keyboard focus-visible
packages/eui/src/components/tool_tip/tool_tip.stories.tsx Add manual QA stories for focus-visible/focus-return scenarios
packages/eui/src/components/table/table_header_cell.test.tsx Switch tooltip assertions from focus to hover interactions
packages/eui/src/components/color_picker/saturation.test.tsx Use simulateFocusVisible() before focus assertions
packages/eui/src/components/color_picker/hue.test.tsx Use simulateFocusVisible() before focus assertions
packages/eui/src/components/color_picker/color_picker_swatch.test.tsx Use simulateFocusVisible() before focus assertions
packages/eui/src/components/button/button_group/button_group.test.tsx Use simulateFocusVisible() before focus assertions
packages/eui/changelogs/upcoming/9624.md Document tooltip behavior fixes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/eui/src/components/tool_tip/tool_tip.stories.tsx Outdated
Comment thread packages/eui/src/components/tool_tip/tool_tip.tsx
Comment thread packages/eui/src/components/tool_tip/tool_tip.tsx
Comment thread packages/eui/src/test/rtl/component_helpers.ts Outdated
Copy link
Copy Markdown
Contributor

@mgadewoll mgadewoll left a comment

Choose a reason for hiding this comment

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

I checked the listed components, everything works as expected. 👍
I left some general thoughts, and I think the Copilot notes are generally worth to address.

ℹ️ I did notice that EuiMarkdownEditor doesn't actually show a tooltip on keyboard focus, but that's also currently the behavior on production. (We might want to improve that at some point, but it's not related to this PR)

Comment thread packages/eui/changelogs/upcoming/9624.md Outdated
Comment thread packages/eui/src/test/rtl/component_helpers.ts Outdated
Comment thread packages/eui/src/test/rtl/component_helpers.ts Outdated
Comment thread packages/eui/src/test/rtl/component_helpers.ts Outdated
Comment thread packages/eui/changelogs/upcoming/9624.md Outdated
Comment thread packages/eui/changelogs/upcoming/9624.md Outdated
@weronikaolejniczak
Copy link
Copy Markdown
Contributor Author

weronikaolejniczak commented Apr 30, 2026

@mgadewoll I addressed all your comments. Thank you for the review, Lene 🙏🏻 Let's see what Copilot has to say and how EUI CI and Kibana CI responds. Thanks for pushing me to do it early, I already found some issues 😄

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/eui/src/components/tool_tip/tool_tip.stories.tsx Outdated
Comment thread packages/eui/src/components/tool_tip/tool_tip.test.tsx
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/eui/src/components/tool_tip/tool_tip.spec.tsx
Comment thread packages/eui/src/components/tool_tip/tool_tip.test.tsx
Comment thread packages/eslint-plugin/README.md
@tkajtoch
Copy link
Copy Markdown
Member

buildkite test this

const { getByRole } = render(<MyComponent />);
const cleanup = focusEuiToolTipTrigger(getByRole('button'));
expect(getByRole('tooltip')).toBeInTheDocument();
cleanup();
Copy link
Copy Markdown
Contributor

@mgadewoll mgadewoll Apr 30, 2026

Choose a reason for hiding this comment

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

Based on #9624 (comment) - We should probably highlight using try...finally here to ensure the cleanup is always called (independent of potential assertion failures).

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.

We agreed to update this after merging.

Comment thread packages/eslint-plugin/README.md Outdated
Comment thread packages/eslint-plugin/README.md Outdated
Copy link
Copy Markdown
Contributor

@mgadewoll mgadewoll left a comment

Choose a reason for hiding this comment

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

🟢 Code changes are LGTM. The behavior was tested manually and works as expected and affected components don't have any regression.

Thanks for adding the additional ESLint rule 🙏

@weronikaolejniczak weronikaolejniczak enabled auto-merge (squash) May 4, 2026 08:58
@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

cc @weronikaolejniczak

@weronikaolejniczak weronikaolejniczak merged commit e7412fb into elastic:main May 4, 2026
5 checks passed
@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

cc @weronikaolejniczak

weronikaolejniczak added a commit to elastic/kibana that referenced this pull request May 11, 2026
## Dependency updates

- `@elastic/eui` - v114.3.0 ⏩ v115.0.0
- `@elastic/eslint-plugin-eui` - v2.11.1 ⏩ v2.12.0

## Package updates

### Summary

> [!NOTE]
> Please be mindful that as the Design System team we are not aware of
your specific area pre-requisites and testing setups, and are
realistically not capable of testing the entirety of Kibana. That being
said, we want to do our best at migrating breaking changes. All tooltip
usages were updated accordingly but there might be mistakes and bugs.
That's why, **I would advise every reviewer to smoke-test their domain
tooltips**. We'd also greatly appreciate your help with adjusting
anything that may be wrong 🙏🏻


https://github.com/user-attachments/assets/2da29c89-aba1-40f9-ae3e-13790a34aedf

- tooltips **no longer appear on programmatic focus return** (e.g. when
closing flyouts, modals) - unless you're using the keyboard to navigate,
- tooltips **do not persist on mouse click** which was annoying for the
sighted users and tricky to handle in automated testing environments,
- there's **no timeout-based delay** that's inconsistent across Kibana
and makes the UI seem laggy,
- we made the **animation simpler** and tooltip content **font-size
smaller**, resulting in a better visual hierarchy,
- :accessibility: VoiceOver no longer has problems with **announcing
tooltip content** on trigger focus.

These changes have been developed with [SC 1.4.13 Content on Hover or
Focus](https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus) in mind
while providing the best possible UX.

### `@elastic/eui`
[v115.0.0](https://github.com/elastic/eui/blob/main/packages/eui/changelogs/CHANGELOG_2026.md)

- Updated `EuiToolTip` default font size from 14px to 12px
([#9627](elastic/eui#9627))
- Updated `EuiToolTip` show animation to opacity-only with a 150ms grace
period delay, preventing visual flickering when quickly hovering over
multiple tooltip triggers
([#9626](elastic/eui#9626))
- Updated `EuiToolTip` to respect input modality. Tooltip no longer
persists on mouse-click focus or shows on programmatic focus return.
([#9624](elastic/eui#9624))

**Bug fixes**

- Fixed `uiPlugins[].button` type to allow UI plugins to not have a
toolbar button in `EuiMarkdownEditor`
([#9634](elastic/eui#9634))
- Fixed `EuiToolTip` self-hiding when the mouse moves over child
elements within the trigger
([#9626](elastic/eui#9626))

**Breaking changes**

- Removed `delay` prop and `ToolTipDelay` type from `EuiToolTip` and
`EuiIconTip` ([#9626](elastic/eui#9626))
- Removed `waitForEuiToolTipVisible` and `waitForEuiToolTipHidden` RTL
test helpers; tooltip show/hide is now synchronous so direct assertions
can be used instead ([#9626](elastic/eui#9626))

**Accessibility**

- Fixed invalid nested interactive elements in `EuiMarkdownEditor` by
removing `role` from the drop zone wrapper.
([#9625](elastic/eui#9625))

### `@elastic/eslint-plugin-eui`
[v2.12.0](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2026.md)

- Added a new `prefer-tooltip-trigger-focus-test-utility` rule that
flags `fireEvent.focus()` inside `it`/`test` blocks that also query for
a tooltip. The rule auto-fixes to `focusEuiToolTipTrigger` from EUI's
RTL test utilities. ([#9624](elastic/eui#9624))

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants