Skip to content

Commit 7fe6a75

Browse files
committed
💄 fix: improve default tooltip arrow size
1 parent e490f2a commit 7fe6a75

12 files changed

+201
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import '@testing-library/jest-dom';
2+
import { render, screen } from '@testing-library/react';
3+
import React from 'react';
4+
import { Triangle, TooltipContent, TooltipContentProps } from 'lib';
5+
6+
jest.mock('lib/components/Triangle/Triangle', () => {
7+
return {
8+
Triangle: jest.fn(() => <div data-testid="triangle" />),
9+
};
10+
});
11+
12+
describe('TooltipContent', () => {
13+
const defaultProps: TooltipContentProps = {
14+
children: 'Tooltip text',
15+
triangleColor: 'red',
16+
};
17+
18+
it('renders the tooltip content', () => {
19+
render(<TooltipContent {...defaultProps} />);
20+
expect(screen.getByText('Tooltip text')).toBeInTheDocument();
21+
});
22+
23+
it('renders the triangle when triangleSize is provided', () => {
24+
render(<TooltipContent {...defaultProps} triangleSize={10} />);
25+
expect(screen.getAllByTestId('triangle')).toHaveLength(1);
26+
});
27+
28+
it('renders the triangle border when triangleBorderColor is provided', () => {
29+
render(<TooltipContent {...defaultProps} triangleBorderColor="black" triangleSize={10} />);
30+
expect(screen.getAllByTestId('triangle')).toHaveLength(2); // one for the border, one for the triangle
31+
});
32+
33+
it('does not render if position is null', () => {
34+
render(<TooltipContent {...defaultProps} position={null as never} />);
35+
expect(screen.queryByText('Tooltip text')).not.toBeInTheDocument();
36+
});
37+
38+
it('passes correct props to the Triangle component', () => {
39+
render(<TooltipContent {...defaultProps} position="top-left" triangleBorderColor="blue" triangleSize={12} />);
40+
expect(Triangle).toHaveBeenCalledWith(
41+
expect.objectContaining({
42+
color: 'blue',
43+
position: 'bottom',
44+
size: 12,
45+
}),
46+
expect.anything(),
47+
);
48+
});
49+
50+
const positions = [
51+
{ position: 'top-left', expected: 'bottom' },
52+
{ position: 'top-center', expected: 'bottom' },
53+
{ position: 'top-right', expected: 'bottom' },
54+
{ position: 'bottom-left', expected: 'top' },
55+
{ position: 'bottom-center', expected: 'top' },
56+
{ position: 'bottom-right', expected: 'top' },
57+
{ position: 'left-center', expected: 'right' },
58+
{ position: 'right-center', expected: 'left' },
59+
{ position: 'left-top', expected: 'right' },
60+
{ position: 'left-bottom', expected: 'right' },
61+
{ position: 'right-top', expected: 'left' },
62+
{ position: 'right-bottom', expected: 'left' },
63+
];
64+
65+
positions.forEach(({ position, expected }) => {
66+
it(`passes correct props to the Triangle component for position ${position}`, () => {
67+
render(
68+
<TooltipContent {...defaultProps} position={position as never} triangleBorderColor="blue" triangleSize={12} />,
69+
);
70+
expect(Triangle).toHaveBeenCalledWith(
71+
expect.objectContaining({
72+
color: 'blue',
73+
position: expected,
74+
size: 12,
75+
}),
76+
expect.anything(),
77+
);
78+
});
79+
});
80+
});

jest.config.ci.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = {
1212
},
1313
modulePathIgnorePatterns: [...config.modulePathIgnorePatterns, '<rootDir>/package.json'],
1414
moduleNameMapper: {
15-
'^lib(.*)$': '<rootDir>/lib$1',
15+
'^lib(.*)$': '<rootDir>/lib/cjs$1',
1616
'^__mocks__/(.*)$': '<rootDir>/__mocks__/$1',
1717
'\\.css$': '<rootDir>/__mocks__/style.mock.js',
1818
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':

src/compositions/Dropover/DropoverLabel.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@ export const DropoverLabel = React.forwardRef<HTMLDivElement, DropoverLabelProps
6161

6262
{!noTriangle && (
6363
<Rhythm ml={2}>
64-
<Triangle color={focused ? triangleFocusedColor : triangleColor} position="bottom" size={triangleSize} />
64+
<Triangle
65+
aria-hidden="true"
66+
color={focused ? triangleFocusedColor : triangleColor}
67+
position="bottom"
68+
size={triangleSize}
69+
/>
6570
</Rhythm>
6671
)}
6772
</div>

src/compositions/Tooltip/InlineTextTooltip.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function InlineTextTooltip<F extends HTMLElement | undefined = undefined>
4949
themeId: initThemeId,
5050
tooltipClassName,
5151
triangleBorderWidth = 2,
52-
triangleSize,
52+
triangleSize = 8,
5353
uncentered = false,
5454
width,
5555
...props

src/compositions/Tooltip/InlineTooltip.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function InlineTooltip<F extends HTMLElement | undefined = undefined>({
4242
triangleBorderColor,
4343
triangleBorderWidth,
4444
triangleColor,
45-
triangleSize,
45+
triangleSize = 8,
4646
uncentered = false,
4747
...props
4848
}: InlineTooltipProps<F>): React.ReactElement {

src/compositions/Tooltip/PortalTextTooltip.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function PortalTextTooltip<F extends HTMLElement | undefined = undefined>
4949
themeId: initThemeId,
5050
tooltipClassName,
5151
triangleBorderWidth = 2,
52-
triangleSize,
52+
triangleSize = 8,
5353
uncentered,
5454
width,
5555
...props

src/compositions/Tooltip/PortalTooltip.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function PortalTooltip<F extends HTMLElement | undefined = undefined>({
4242
triangleBorderColor,
4343
triangleBorderWidth,
4444
triangleColor,
45-
triangleSize,
45+
triangleSize = 8,
4646
uncentered,
4747
...props
4848
}: PortalTooltipProps<F>): React.ReactElement {

src/compositions/Tooltip/TooltipContent.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export function TooltipContent({
152152
>
153153
{triangleBorderColor && !!triangleSize && (
154154
<Triangle
155+
aria-hidden="true"
155156
className={cx(styles.tooltipContent__triangle)}
156157
color={triangleBorderColor}
157158
position={getTrianglePosition(position, cornerTriangle)}
@@ -173,6 +174,7 @@ export function TooltipContent({
173174

174175
{!!triangleSize && (
175176
<Triangle
177+
aria-hidden="true"
176178
className={cx(styles.tooltipContent__triangle)}
177179
color={triangleColor}
178180
position={getTrianglePosition(position, cornerTriangle)}

src/compositions/Tooltip/stories/InlineTextTooltip.stories.tsx

+45-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ const defaultArgs = {
237237
</Typography>
238238
),
239239
triangleBorderWidth: 2,
240-
triangleSize: 10,
241240
uncentered: false,
242241
withoutTogglerFocusStyle: false,
243242
withPopoverTogglerProps: false,
@@ -374,3 +373,48 @@ OnIcon.decorators = [
374373
</Typography>
375374
),
376375
];
376+
377+
export const NoTriangle = Template.bind({});
378+
NoTriangle.storyName = 'No triangle';
379+
NoTriangle.args = {
380+
...defaultArgs,
381+
children: 'Tiny little portal tooltip. Hardly bigger than an acorn.',
382+
hoverable: false,
383+
toggler: (
384+
<Rhythm mx={1}>
385+
<IconButton color="primary">
386+
<ArrowUpDownIcon scale="medium" />
387+
</IconButton>
388+
</Rhythm>
389+
),
390+
triangleSize: 0,
391+
withoutTogglerFocusStyle: true,
392+
};
393+
394+
NoTriangle.decorators = [
395+
(Story, { args: { position, layout } }) => (
396+
<Typography<'div'>
397+
as="div"
398+
color="primary"
399+
style={{
400+
margin: 20,
401+
height: 60,
402+
position: 'relative',
403+
}}
404+
>
405+
<div
406+
style={{
407+
alignItems: 'center',
408+
display: 'flex',
409+
position: 'absolute',
410+
...getHorizontalPosition(position, layout),
411+
...getVerticalPosition(position, layout),
412+
}}
413+
>
414+
<span>Sometimes a tooltip should be clickable, or on an icon.</span>
415+
{Story()}
416+
<span>That is neat.</span>
417+
</div>
418+
</Typography>
419+
),
420+
];

src/compositions/Tooltip/stories/InlineTooltip.stories.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ const defaultArgs = {
266266
</Typography>
267267
),
268268
triangleColor: themes.light['color-P10'],
269-
triangleSize: 10,
270269
uncentered: false,
271270
width: 300,
272271
withoutTogglerFocusStyle: false,
@@ -409,6 +408,15 @@ TriangleSize.args = {
409408
triangleSize: 12,
410409
};
411410

411+
export const NoTriangle = Template.bind({});
412+
NoTriangle.storyName = 'No triangle';
413+
NoTriangle.args = {
414+
...defaultArgs,
415+
offset: { horizontal: 42, vertical: 20 },
416+
position: 'bottom-right',
417+
triangleSize: 0,
418+
};
419+
412420
export const ManualFocus = Template.bind({});
413421
ManualFocus.storyName = 'With manual focus';
414422
ManualFocus.args = {

src/compositions/Tooltip/stories/PortalTextTooltip.stories.tsx

+45-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ const defaultArgs = {
248248
</Typography>
249249
),
250250
triangleBorderWidth: 2,
251-
triangleSize: 10,
252251
uncentered: false,
253252
withoutTogglerFocusStyle: false,
254253
withPopoverTogglerProps: false,
@@ -385,3 +384,48 @@ OnIcon.decorators = [
385384
</Typography>
386385
),
387386
];
387+
388+
export const NoTriangle = Template.bind({});
389+
NoTriangle.storyName = 'No triangle';
390+
NoTriangle.args = {
391+
...defaultArgs,
392+
children: 'Tiny little portal tooltip. Hardly bigger than an acorn.',
393+
hoverable: false,
394+
toggler: (
395+
<Rhythm mx={1}>
396+
<IconButton color="primary">
397+
<ArrowUpDownIcon scale="medium" />
398+
</IconButton>
399+
</Rhythm>
400+
),
401+
triangleSize: 0,
402+
withoutTogglerFocusStyle: true,
403+
};
404+
405+
NoTriangle.decorators = [
406+
(Story, { args: { position, layout } }) => (
407+
<Typography<'div'>
408+
as="div"
409+
color="primary"
410+
style={{
411+
margin: 20,
412+
height: 60,
413+
position: 'relative',
414+
}}
415+
>
416+
<div
417+
style={{
418+
alignItems: 'center',
419+
display: 'flex',
420+
position: 'absolute',
421+
...getHorizontalPosition(position, layout),
422+
...getVerticalPosition(position, layout),
423+
}}
424+
>
425+
<span>Sometimes a tooltip should be clickable, or on an icon.</span>
426+
{Story()}
427+
<span>That is neat.</span>
428+
</div>
429+
</Typography>
430+
),
431+
];

src/compositions/Tooltip/stories/PortalTooltip.stories.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ const defaultArgs = {
277277
</Typography>
278278
),
279279
triangleColor: themes.light['color-P10'],
280-
triangleSize: 10,
281280
uncentered: false,
282281
width: 300,
283282
withoutTogglerFocusStyle: false,
@@ -420,6 +419,15 @@ TriangleSize.args = {
420419
triangleSize: 12,
421420
};
422421

422+
export const NoTriangle = Template.bind({});
423+
NoTriangle.storyName = 'No triangle';
424+
NoTriangle.args = {
425+
...defaultArgs,
426+
offset: { horizontal: 42, vertical: 20 },
427+
position: 'bottom-right',
428+
triangleSize: 0,
429+
};
430+
423431
export const AbsolutePortal = Template.bind({});
424432
AbsolutePortal.storyName = 'Portal: Absolute';
425433
AbsolutePortal.args = {

0 commit comments

Comments
 (0)