Skip to content

Commit 707b8bd

Browse files
Add new delay and transition props to EuiTooltip
- Added 'short' (100ms) and 'none' (0ms) delay options - Added 'fade' and 'none' transition options - Updated styles to support fade and no-animation transitions - Added tests for new props - Updated Storybook stories to demonstrate new options Co-authored-by: clintandrewhall <297604+clintandrewhall@users.noreply.github.com>
1 parent c676068 commit 707b8bd

File tree

8 files changed

+382
-2
lines changed

8 files changed

+382
-2
lines changed

packages/eui/src/components/tool_tip/__snapshots__/tool_tip.test.tsx.snap

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,84 @@ exports[`EuiToolTip anchor props are rendered 1`] = `
1717
</body>
1818
`;
1919

20+
exports[`EuiToolTip delay prop none delay 1`] = `
21+
<body
22+
class="euiBody-hasPortalContent"
23+
>
24+
<div>
25+
<span
26+
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
27+
>
28+
<button
29+
aria-describedby="generated-id"
30+
data-test-subj="trigger"
31+
>
32+
Trigger
33+
</button>
34+
</span>
35+
</div>
36+
<div
37+
data-euiportal="true"
38+
>
39+
<div
40+
class="euiToolTipPopover euiToolTip emotion-euiToolTip-top"
41+
data-position="top"
42+
id="generated-id"
43+
position="top"
44+
role="tooltip"
45+
style="top: -16px; left: -10px;"
46+
>
47+
<div
48+
class="euiToolTip__arrow emotion-euiToolTip__arrow-top"
49+
style="left: 3px; top: 100%;"
50+
/>
51+
<div>
52+
content
53+
</div>
54+
</div>
55+
</div>
56+
</body>
57+
`;
58+
59+
exports[`EuiToolTip delay prop short delay 1`] = `
60+
<body
61+
class="euiBody-hasPortalContent"
62+
>
63+
<div>
64+
<span
65+
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
66+
>
67+
<button
68+
aria-describedby="generated-id"
69+
data-test-subj="trigger"
70+
>
71+
Trigger
72+
</button>
73+
</span>
74+
</div>
75+
<div
76+
data-euiportal="true"
77+
>
78+
<div
79+
class="euiToolTipPopover euiToolTip emotion-euiToolTip-top"
80+
data-position="top"
81+
id="generated-id"
82+
position="top"
83+
role="tooltip"
84+
style="top: -16px; left: -10px;"
85+
>
86+
<div
87+
class="euiToolTip__arrow emotion-euiToolTip__arrow-top"
88+
style="left: 3px; top: 100%;"
89+
/>
90+
<div>
91+
content
92+
</div>
93+
</div>
94+
</div>
95+
</body>
96+
`;
97+
2098
exports[`EuiToolTip display prop renders block 1`] = `
2199
<div>
22100
<span
@@ -91,6 +169,84 @@ exports[`EuiToolTip shows tooltip on mouseover and focus 1`] = `
91169
</body>
92170
`;
93171

172+
exports[`EuiToolTip transition prop fade transition 1`] = `
173+
<body
174+
class="euiBody-hasPortalContent"
175+
>
176+
<div>
177+
<span
178+
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
179+
>
180+
<button
181+
aria-describedby="generated-id"
182+
data-test-subj="trigger"
183+
>
184+
Trigger
185+
</button>
186+
</span>
187+
</div>
188+
<div
189+
data-euiportal="true"
190+
>
191+
<div
192+
class="euiToolTipPopover euiToolTip emotion-euiToolTip-top-topFade"
193+
data-position="top"
194+
id="generated-id"
195+
position="top"
196+
role="tooltip"
197+
style="top: -16px; left: -10px;"
198+
>
199+
<div
200+
class="euiToolTip__arrow emotion-euiToolTip__arrow-top"
201+
style="left: 3px; top: 100%;"
202+
/>
203+
<div>
204+
content
205+
</div>
206+
</div>
207+
</div>
208+
</body>
209+
`;
210+
211+
exports[`EuiToolTip transition prop none transition 1`] = `
212+
<body
213+
class="euiBody-hasPortalContent"
214+
>
215+
<div>
216+
<span
217+
class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock"
218+
>
219+
<button
220+
aria-describedby="generated-id"
221+
data-test-subj="trigger"
222+
>
223+
Trigger
224+
</button>
225+
</span>
226+
</div>
227+
<div
228+
data-euiportal="true"
229+
>
230+
<div
231+
class="euiToolTipPopover euiToolTip emotion-euiToolTip-top-noAnimation"
232+
data-position="top"
233+
id="generated-id"
234+
position="top"
235+
role="tooltip"
236+
style="top: -16px; left: -10px;"
237+
>
238+
<div
239+
class="euiToolTip__arrow emotion-euiToolTip__arrow-top"
240+
style="left: 3px; top: 100%;"
241+
/>
242+
<div>
243+
content
244+
</div>
245+
</div>
246+
</div>
247+
</body>
248+
`;
249+
94250
exports[`EuiToolTip uses custom offset prop value 1`] = `
95251
<body
96252
class="euiBody-hasPortalContent"

packages/eui/src/components/tool_tip/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
*/
88

99
export type { ToolTipPositions } from './tool_tip_popover';
10-
export type { EuiToolTipProps } from './tool_tip';
10+
export type {
11+
EuiToolTipProps,
12+
ToolTipDelay,
13+
ToolTipTransition,
14+
} from './tool_tip';
1115
export { EuiToolTip } from './tool_tip';
1216

1317
export type { EuiIconTipProps } from './icon_tip';

packages/eui/src/components/tool_tip/tool_tip.stories.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const meta: Meta<EuiToolTipProps> = {
4545
args: {
4646
position: 'top',
4747
delay: 'regular',
48+
transition: 'default',
4849
display: 'inlineBlock',
4950
// set up for easier testing/QA
5051
anchorClassName: '',
@@ -72,6 +73,34 @@ export const Playground: Story = {
7273
}),
7374
};
7475

76+
export const ShortDelay: Story = {
77+
args: {
78+
...Playground.args,
79+
delay: 'short',
80+
},
81+
};
82+
83+
export const NoDelay: Story = {
84+
args: {
85+
...Playground.args,
86+
delay: 'none',
87+
},
88+
};
89+
90+
export const FadeTransition: Story = {
91+
args: {
92+
...Playground.args,
93+
transition: 'fade',
94+
},
95+
};
96+
97+
export const NoTransition: Story = {
98+
args: {
99+
...Playground.args,
100+
transition: 'none',
101+
},
102+
};
103+
75104
/**
76105
* VRT only stories
77106
*/

packages/eui/src/components/tool_tip/tool_tip.styles.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ const euiToolTipAnimationHorizontal = (size: string) => keyframes`
4444
}
4545
`;
4646

47+
const euiToolTipAnimationFade = keyframes`
48+
0% {
49+
opacity: 0;
50+
}
51+
52+
100% {
53+
opacity: 1;
54+
}
55+
`;
56+
4757
export const euiToolTipStyles = (euiThemeContext: UseEuiTheme) => {
4858
const { euiTheme, highContrastMode } = euiThemeContext;
4959

@@ -103,6 +113,31 @@ export const euiToolTipStyles = (euiThemeContext: UseEuiTheme) => {
103113
${animationTiming};
104114
}
105115
`,
116+
// Fade transition positions (no movement, just opacity)
117+
topFade: css`
118+
${euiCanAnimate} {
119+
animation: ${euiToolTipAnimationFade} ${animationTiming};
120+
}
121+
`,
122+
bottomFade: css`
123+
${euiCanAnimate} {
124+
animation: ${euiToolTipAnimationFade} ${animationTiming};
125+
}
126+
`,
127+
leftFade: css`
128+
${euiCanAnimate} {
129+
animation: ${euiToolTipAnimationFade} ${animationTiming};
130+
}
131+
`,
132+
rightFade: css`
133+
${euiCanAnimate} {
134+
animation: ${euiToolTipAnimationFade} ${animationTiming};
135+
}
136+
`,
137+
// No animation
138+
noAnimation: css`
139+
/* No animation - tooltip appears immediately */
140+
`,
106141
// Arrow
107142
euiToolTip__arrow: css`
108143
${arrowStyles._arrowStyles}

packages/eui/src/components/tool_tip/tool_tip.test.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,58 @@ describe('EuiToolTip', () => {
111111
expect(container).toMatchSnapshot();
112112
});
113113

114+
describe('delay prop', () => {
115+
test('short delay', async () => {
116+
const { baseElement, getByTestSubject } = render(
117+
<EuiToolTip content="content" delay="short">
118+
<button data-test-subj="trigger">Trigger</button>
119+
</EuiToolTip>
120+
);
121+
122+
fireEvent.mouseOver(getByTestSubject('trigger'));
123+
await waitForEuiToolTipVisible();
124+
expect(baseElement).toMatchSnapshot();
125+
});
126+
127+
test('none delay', async () => {
128+
const { baseElement, getByTestSubject } = render(
129+
<EuiToolTip content="content" delay="none">
130+
<button data-test-subj="trigger">Trigger</button>
131+
</EuiToolTip>
132+
);
133+
134+
fireEvent.mouseOver(getByTestSubject('trigger'));
135+
await waitForEuiToolTipVisible();
136+
expect(baseElement).toMatchSnapshot();
137+
});
138+
});
139+
140+
describe('transition prop', () => {
141+
test('fade transition', async () => {
142+
const { baseElement, getByTestSubject } = render(
143+
<EuiToolTip content="content" transition="fade">
144+
<button data-test-subj="trigger">Trigger</button>
145+
</EuiToolTip>
146+
);
147+
148+
fireEvent.mouseOver(getByTestSubject('trigger'));
149+
await waitForEuiToolTipVisible();
150+
expect(baseElement).toMatchSnapshot();
151+
});
152+
153+
test('none transition', async () => {
154+
const { baseElement, getByTestSubject } = render(
155+
<EuiToolTip content="content" transition="none">
156+
<button data-test-subj="trigger">Trigger</button>
157+
</EuiToolTip>
158+
);
159+
160+
fireEvent.mouseOver(getByTestSubject('trigger'));
161+
await waitForEuiToolTipVisible();
162+
expect(baseElement).toMatchSnapshot();
163+
});
164+
});
165+
114166
describe('aria-describedby', () => {
115167
it('by default, sets an `aria-describedby` on the anchor when the tooltip is visible', async () => {
116168
const { getByTestSubject } = render(

packages/eui/src/components/tool_tip/tool_tip.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,15 @@ import { toolTipManager } from './tool_tip_manager';
3636
export const POSITIONS = ['top', 'right', 'bottom', 'left'] as const;
3737
const DISPLAYS = ['inlineBlock', 'block'] as const;
3838

39-
export type ToolTipDelay = 'regular' | 'long';
39+
export type ToolTipDelay = 'regular' | 'long' | 'short' | 'none';
40+
export type ToolTipTransition = 'default' | 'fade' | 'none';
4041
export const DEFAULT_TOOLTIP_OFFSET = 16;
4142

4243
const delayToMsMap: { [key in ToolTipDelay]: number } = {
4344
regular: 250,
4445
long: 250 * 5,
46+
short: 100,
47+
none: 0,
4548
};
4649

4750
interface ToolTipStyles {
@@ -94,6 +97,13 @@ export interface EuiToolTipProps extends CommonProps {
9497
* Delay before showing tooltip. Good for repeatable items.
9598
*/
9699
delay: ToolTipDelay;
100+
/**
101+
* Type of transition for the tooltip appearance.
102+
* - 'default': Uses the current behavior with movement
103+
* - 'fade': Fades in without movement
104+
* - 'none': Appears immediately without animation
105+
*/
106+
transition?: ToolTipTransition;
97107
/**
98108
* An optional title for your tooltip.
99109
*/
@@ -175,6 +185,7 @@ export class EuiToolTip extends Component<EuiToolTipProps, State> {
175185
static defaultProps: Partial<EuiToolTipProps> = {
176186
position: 'top',
177187
delay: 'regular',
188+
transition: 'default',
178189
display: 'inlineBlock',
179190
disableScreenReaderOutput: false,
180191
};
@@ -346,6 +357,7 @@ export class EuiToolTip extends Component<EuiToolTipProps, State> {
346357
content,
347358
title,
348359
delay,
360+
transition,
349361
display,
350362
repositionOnScroll,
351363
disableScreenReaderOutput = false,
@@ -387,6 +399,7 @@ export class EuiToolTip extends Component<EuiToolTipProps, State> {
387399
id={id}
388400
role="tooltip"
389401
calculatedPosition={calculatedPosition}
402+
transition={transition}
390403
{...rest}
391404
>
392405
<EuiToolTipArrow

0 commit comments

Comments
 (0)