Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7204c9d
refactor(eui): migrate EuiToolTip to functional component
weronikaolejniczak Apr 7, 2026
7e4fec1
refactor(eui): memoize EuiToolTip styles
weronikaolejniczak Apr 7, 2026
45cc756
refactor(eui): update EuiToolTip usages
weronikaolejniczak Apr 7, 2026
451f7a5
chore(eui): update VRT reference images
weronikaolejniczak Apr 7, 2026
221f34e
chore(eui): update EuiToolTip test suite
weronikaolejniczak Apr 7, 2026
fcc3c7e
chore(eui): update EuiIconTip test suite
weronikaolejniczak Apr 7, 2026
d7c08d6
chore(eui): add filter select item tooltip test
weronikaolejniczak Apr 8, 2026
722bc07
REMOVE BEFORE MERGE - temp stories
weronikaolejniczak Apr 8, 2026
b806650
refactor(eui): update nits after review
weronikaolejniczak Apr 8, 2026
d226eb5
fix(eui): fix tooltip reposition on resize window
weronikaolejniczak Apr 8, 2026
a38e23d
fix(eui): position tooltip on mount fixing StrictMode
weronikaolejniczak Apr 8, 2026
402d1a1
chore(eui): just some formatting weirdness
weronikaolejniczak Apr 8, 2026
88161ad
refactor(eui): narrow types in EuiToolTip
weronikaolejniczak Apr 9, 2026
a89ee57
chore(eui): change test to it in filter select item test
weronikaolejniczak Apr 9, 2026
d9cec6d
fix(eui): use ref on htmlIdGenerator return value
weronikaolejniczak Apr 9, 2026
cede9a3
chore(eui): update assertions in EuiIconTip tests
weronikaolejniczak Apr 9, 2026
03ca9cd
chore(eui): rephrase stale comment
weronikaolejniczak Apr 9, 2026
8a2d8e1
chore(eui): update comment
weronikaolejniczak Apr 9, 2026
bb760b1
feat(eui): remove delay from EuiToolTip
weronikaolejniczak Apr 9, 2026
4b4fab8
feat(eui): show tooltip on keyboard focus, not mouse focus
weronikaolejniczak Apr 9, 2026
cbb2012
chore(eui): update tests affected by focus-visible
weronikaolejniczak Apr 9, 2026
be4734d
TEMP STORY
weronikaolejniczak Apr 9, 2026
8ebbbec
chore(eui): add a comment about programmatic focus return
weronikaolejniczak Apr 9, 2026
beb09cb
refactor(eui): bye bye enqueueStateChange in tooltip
weronikaolejniczak Apr 9, 2026
49c59c4
chore(eui): use simulateFocusVisible helper
weronikaolejniczak Apr 9, 2026
fbb1b81
fix(eui): fix onMouseOut firing on moving over child elements
weronikaolejniczak Apr 10, 2026
f7c5e73
chore(eui): update Cypress test for EuiToolTip
weronikaolejniczak Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { css } from '@emotion/react';
import { fireEvent } from '@testing-library/react';
import {
render,
simulateFocusVisible,
waitForEuiToolTipHidden,
waitForEuiToolTipVisible,
} from '../../../test/rtl';
Expand Down Expand Up @@ -245,6 +246,7 @@ describe('EuiButtonGroup', () => {
});

describe('tooltips', () => {
afterEach(() => jest.restoreAllMocks());
it('shows a tooltip on hover and focus', async () => {
const { getByTestSubject, getByRole } = render(
<EuiButtonGroup
Expand All @@ -268,6 +270,7 @@ describe('EuiButtonGroup', () => {
fireEvent.mouseOut(getByTestSubject('buttonWithTooltip'));
await waitForEuiToolTipHidden();

simulateFocusVisible(getByTestSubject('buttonWithTooltip'));
fireEvent.focus(getByTestSubject('buttonWithTooltip'));
await waitForEuiToolTipVisible();
fireEvent.blur(getByTestSubject('buttonWithTooltip'));
Expand Down Expand Up @@ -302,6 +305,7 @@ describe('EuiButtonGroup', () => {
fireEvent.mouseOut(getByTestSubject('buttonWithTooltip').parentElement!);
await waitForEuiToolTipHidden();

simulateFocusVisible(getByTestSubject('buttonWithTooltip'));
fireEvent.focus(getByTestSubject('buttonWithTooltip'));
await waitForEuiToolTipVisible();
fireEvent.blur(getByTestSubject('buttonWithTooltip'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ exports[`EuiCollapsedNavButton renders a tooltip around the icon button 1`] = `
class="euiToolTipPopover euiToolTip emotion-euiToolTip-left-euiCollapsedNavItemTooltip-left"
data-position="left"
id="generated-id"
position="left"
role="tooltip"
style="top: -10px; left: -16px;"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import { requiredProps } from '../../test';
import { shouldRenderCustomStyles } from '../../test/internal';
import {
render,
simulateFocusVisible,
waitForEuiToolTipHidden,
waitForEuiToolTipVisible,
} from '../../test/rtl';

import { EuiColorPickerSwatch } from './color_picker_swatch';

describe('EuiColorPickerSwatch', () => {
afterEach(() => jest.restoreAllMocks());
shouldRenderCustomStyles(<EuiColorPickerSwatch />);

test('is rendered', () => {
Expand Down Expand Up @@ -61,6 +63,7 @@ describe('EuiColorPickerSwatch', () => {

const swatchElement = getByTestSubject('color-picker-swatch');

simulateFocusVisible(swatchElement);
fireEvent.focus(swatchElement);

await waitForEuiToolTipVisible();
Expand Down
3 changes: 3 additions & 0 deletions packages/eui/src/components/color_picker/hue.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { requiredProps } from '../../test/required_props';
import { shouldRenderCustomStyles } from '../../test/internal';
import {
render,
simulateFocusVisible,
waitForEuiToolTipHidden,
waitForEuiToolTipVisible,
} from '../../test/rtl';
Expand All @@ -23,6 +24,7 @@ const onChange = () => {
};

describe('EuiHue', () => {
afterEach(() => jest.restoreAllMocks());
shouldRenderCustomStyles(<EuiHue onChange={onChange} />, {
skip: { style: true },
});
Expand Down Expand Up @@ -81,6 +83,7 @@ describe('EuiHue', () => {

const thumbElement = document.querySelector('.euiHue__range')!;

simulateFocusVisible(thumbElement);
fireEvent.focus(thumbElement);

await waitForEuiToolTipVisible();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { requiredProps } from '../../test/required_props';
import { shouldRenderCustomStyles } from '../../test/internal';
import {
render,
simulateFocusVisible,
waitForEuiToolTipHidden,
waitForEuiToolTipVisible,
} from '../../test/rtl';
Expand All @@ -23,6 +24,7 @@ const onChange = () => {
};

describe('EuiSaturation', () => {
afterEach(() => jest.restoreAllMocks());
shouldRenderCustomStyles(<EuiSaturation onChange={onChange} />);

test('is rendered', () => {
Expand Down Expand Up @@ -70,6 +72,7 @@ describe('EuiSaturation', () => {

const thumbElement = document.querySelector('.euiSaturation__indicator')!;

simulateFocusVisible(thumbElement);
fireEvent.focus(thumbElement);

await waitForEuiToolTipVisible();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ exports[`EuiContextMenuItem tooltip behavior 1`] = `
class="euiToolTipPopover euiToolTip emotion-euiToolTip-top"
data-position="top"
id="generated-id"
position="top"
role="tooltip"
style="top: -16px; left: -10px;"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
*/

import React from 'react';
import { render } from '../../test/rtl';
import {
render,
waitForEuiToolTipVisible,
waitForEuiToolTipHidden,
} from '../../test/rtl';
import { requiredProps } from '../../test';
import { shouldRenderCustomStyles } from '../../test/internal';

Expand All @@ -21,4 +25,57 @@ describe('EuiFilterSelectItem', () => {

expect(container.firstChild).toMatchSnapshot();
});

describe('tooltip behavior', () => {
const tooltipProps = {
toolTipContent: 'Filter item tooltip',
toolTipProps: { 'data-test-subj': 'filterItemToolTip' },
};

// `toggleToolTip` is called in `componentDidUpdate`; on initial mount `tooltipRef.current`
// is null because `EuiToolTip` hasn't committed its ref yet, so a re-render is required
// to trigger `showToolTip`/`hideToolTip`.
it('shows tooltip when `isFocused` becomes true', async () => {
const { rerender, getByTestSubject } = render(
<EuiFilterSelectItem {...tooltipProps} isFocused={false}>
<span>Item</span>
</EuiFilterSelectItem>
);

rerender(
<EuiFilterSelectItem {...tooltipProps} isFocused={true}>
<span>Item</span>
</EuiFilterSelectItem>
);

await waitForEuiToolTipVisible();
expect(getByTestSubject('filterItemToolTip')).toBeInTheDocument();
});

it('hides tooltip when `isFocused` becomes false', async () => {
const { rerender, queryByRole } = render(
<EuiFilterSelectItem {...tooltipProps} isFocused={false}>
<span>Item</span>
</EuiFilterSelectItem>
);

rerender(
<EuiFilterSelectItem {...tooltipProps} isFocused={true}>
<span>Item</span>
</EuiFilterSelectItem>
);

await waitForEuiToolTipVisible();
expect(queryByRole('tooltip')).toBeInTheDocument();

rerender(
<EuiFilterSelectItem {...tooltipProps} isFocused={false}>
<span>Item</span>
</EuiFilterSelectItem>
);

await waitForEuiToolTipHidden();
expect(queryByRole('tooltip')).not.toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CommonProps } from '../common';

import { EuiFlexGroup, EuiFlexItem } from '../flex';
import { EuiToolTip } from '../tool_tip';
import type { EuiToolTipRef } from '../tool_tip';
import { EuiIcon } from '../icon';
import { EuiComboBoxOptionOption } from '../combo_box';

Expand Down Expand Up @@ -62,7 +63,7 @@ export class EuiFilterSelectItemClass extends Component<
};

buttonRef: HTMLButtonElement | null = null;
tooltipRef = createRef<EuiToolTip>();
tooltipRef = createRef<EuiToolTipRef>();

state = {
hasFocus: false,
Expand Down Expand Up @@ -97,6 +98,12 @@ export class EuiFilterSelectItemClass extends Component<
if (this.props.isFocused && !prevProps.isFocused) {
this.buttonRef?.scrollIntoView?.({ block: 'nearest' });
}
if (
this.props.isFocused !== prevProps.isFocused &&
this.props.toolTipContent
) {
this.toggleToolTip(this.props.isFocused ?? false);
}
}

render() {
Expand Down Expand Up @@ -142,8 +149,6 @@ export class EuiFilterSelectItemClass extends Component<
style: anchorStyles,
}
: { style };

this.toggleToolTip(isFocused ?? false);
}

let iconNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ exports[`EuiSelectableListItem props tooltip behavior on mouseover 1`] = `
data-position="top"
data-test-subj="listItemToolTip"
id="generated-id"
position="top"
role="tooltip"
style="top: -16px; left: -10px;"
>
Expand Down Expand Up @@ -628,7 +627,6 @@ exports[`EuiSelectableListItem props tooltip behavior when isFocused 1`] = `
data-position="top"
data-test-subj="listItemToolTip"
id="generated-id"
position="top"
role="tooltip"
style="top: -16px; left: -10px;"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { EuiIcon, IconColor, IconType } from '../../icon';
import { EuiScreenReaderOnly } from '../../accessibility';
import { EuiBadge, EuiBadgeProps } from '../../badge';
import { EuiToolTip } from '../../tool_tip';
import type { EuiToolTipRef } from '../../tool_tip';

import type {
EuiSelectableOption,
Expand Down Expand Up @@ -358,7 +359,7 @@ export const EuiSelectableListItem: FunctionComponent<
}, [role, checked]);

const hasToolTip = !!toolTipContent && !disabled;
const [tooltipRef, setTooltipRef] = useState<EuiToolTip | null>(null); // Needs to be state and not a ref to trigger useEffect
const [tooltipRef, setTooltipRef] = useState<EuiToolTipRef | null>(null); // Needs to be state and not a ref to trigger useEffect
const [ariaDescribedBy, setAriaDescribedBy] = useState(_ariaDescribedBy);

// Manually trigger the tooltip on keyboard focus
Expand All @@ -375,7 +376,7 @@ export const EuiSelectableListItem: FunctionComponent<
// Manually set the `aria-describedby` id on the <li> wrapper
useEffect(() => {
if (tooltipRef) {
const tooltipId = tooltipRef.state.id;
const tooltipId = tooltipRef.id;
setAriaDescribedBy(classNames(tooltipId, _ariaDescribedBy));
}
}, [tooltipRef, _ariaDescribedBy]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

import React, { PropsWithChildren, ReactElement } from 'react';
import { requiredProps } from '../../test/required_props';
import { render, waitForEuiToolTipVisible } from '../../test/rtl';
import {
render,
simulateFocusVisible,
waitForEuiToolTipVisible,
} from '../../test/rtl';
import { fireEvent } from '@testing-library/react';

import { RIGHT_ALIGNMENT, CENTER_ALIGNMENT } from '../../services';
Expand Down Expand Up @@ -241,6 +245,7 @@ describe('EuiTableHeaderCell', () => {
});

describe('tooltip', () => {
afterEach(() => jest.restoreAllMocks());
it('renders an icon with tooltip', async () => {
const { getByTestSubject } = renderInTableHeader(
<EuiTableHeaderCell
Expand All @@ -264,6 +269,7 @@ describe('EuiTableHeaderCell', () => {
'info'
);

simulateFocusVisible(getByTestSubject('icon'));
fireEvent.focus(getByTestSubject('icon'));
await waitForEuiToolTipVisible();

Expand Down Expand Up @@ -296,6 +302,7 @@ describe('EuiTableHeaderCell', () => {
'info'
);

simulateFocusVisible(getByTestSubject('tableHeaderSortButton'));
fireEvent.focus(getByTestSubject('tableHeaderSortButton'));
await waitForEuiToolTipVisible();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,3 @@ exports[`EuiIconTip is rendered 1`] = `
</span>
</span>
`;

exports[`EuiIconTip props color is rendered as the icon color 1`] = `
<span
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
id="id-wrapper"
>
<span
color="warning"
data-euiicon-type="question"
tabindex="0"
>
Info
</span>
</span>
`;

exports[`EuiIconTip props size is rendered as the icon size 1`] = `
<span
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
id="id-wrapper"
>
<span
data-euiicon-type="question"
tabindex="0"
>
Info
</span>
</span>
`;

exports[`EuiIconTip props type is rendered as the icon 1`] = `
<span
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
id="id-wrapper"
>
<span
data-euiicon-type="warning"
tabindex="0"
>
Info
</span>
</span>
`;
Loading