Skip to content

Commit bedac7a

Browse files
authored
Merge pull request #9 from webdevia/homework-7
Tooltip: Fix positioning issues, add stories to storybook
2 parents b7752fa + 535f47b commit bedac7a

File tree

6 files changed

+69
-15
lines changed

6 files changed

+69
-15
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.tooltip-buttons {
2+
display: flex;
3+
gap: 20px;
4+
justify-content: space-between;
5+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React, { ReactNode } from 'react';
2+
import { Position, Tooltip } from '../tooltip/Tooltip';
3+
import { Button } from '../button/Button';
4+
import s from './TooltipButtons.module.scss';
5+
6+
type PredefinedTooltipProps = {
7+
children: ReactNode;
8+
position: Position;
9+
};
10+
11+
const PredefinedTooltip = ({ children, position }: PredefinedTooltipProps) => (
12+
<Tooltip content="Всплывающая подсказка" position={position}>
13+
{children}
14+
</Tooltip>
15+
);
16+
17+
export const TooltipButtons = () => (
18+
<div className={s['tooltip-buttons']}>
19+
<PredefinedTooltip position={'left'}>
20+
<Button>{'Слева'}</Button>
21+
</PredefinedTooltip>
22+
<PredefinedTooltip position={'right'}>
23+
<Button>{'Справа'}</Button>
24+
</PredefinedTooltip>
25+
<PredefinedTooltip position={'top'}>
26+
<Button>{'Сверху'}</Button>
27+
</PredefinedTooltip>
28+
<PredefinedTooltip position={'bottom'}>
29+
<Button>{'Снизу'}</Button>
30+
</PredefinedTooltip>
31+
</div>
32+
);

src/shared/tooltip/Tooltip.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
}
55

66
.tooltip-content {
7+
z-index: 1;
78
position: absolute;
89
padding: 5px;
910
border-radius: 5px;

src/shared/tooltip/Tooltip.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,35 @@ type CoordProps = {
1414
offset: number;
1515
};
1616

17-
type Position = 'top' | 'bottom' | 'left' | 'right';
17+
export type Position = 'top' | 'bottom' | 'left' | 'right';
1818

1919
type PositionMap = Record<Position, (props: CoordProps) => Coords>;
2020

2121
const getCenterCoord = (primary: number, secondary: number) => (primary - secondary) / 2;
2222

23-
const YLeft = (primary: DOMRect, secondary: DOMRect) => primary.left + getCenterCoord(primary.width, secondary.width);
24-
const XTop = (primary: DOMRect, secondary: DOMRect) => primary.top + getCenterCoord(primary.height, secondary.height);
23+
const YLeft = (primary: DOMRect, secondary: DOMRect) =>
24+
primary.left + window.scrollX + getCenterCoord(primary.width, secondary.width);
25+
const XTop = (primary: DOMRect, secondary: DOMRect) =>
26+
primary.top + window.scrollY + getCenterCoord(primary.height, secondary.height);
2527

2628
const positionMap: PositionMap = {
2729
top: ({ targetRect, tooltipRect, offset }) => ({
28-
top: targetRect.top - tooltipRect.height - offset,
29-
left: YLeft(targetRect, tooltipRect),
30+
top: targetRect.top + window.scrollY - tooltipRect.height - offset,
31+
left: targetRect.left + window.scrollX + getCenterCoord(targetRect.width, tooltipRect.width),
3032
}),
33+
3134
bottom: ({ targetRect, tooltipRect, offset }) => ({
32-
top: targetRect.bottom + offset,
35+
top: targetRect.bottom + window.scrollY + offset,
3336
left: YLeft(targetRect, tooltipRect),
3437
}),
3538
left: ({ targetRect, tooltipRect, offset }) => ({
3639
top: XTop(targetRect, tooltipRect),
37-
left: targetRect.left - (tooltipRect.width + offset),
40+
left: targetRect.left + window.scrollX - tooltipRect.width - offset,
3841
}),
3942

4043
right: ({ targetRect, tooltipRect, offset }) => ({
4144
top: XTop(targetRect, tooltipRect),
42-
left: targetRect.left + (targetRect.width + offset),
45+
left: targetRect.left + window.scrollX + targetRect.width + offset,
4346
}),
4447
};
4548

@@ -59,7 +62,7 @@ export const Tooltip = ({ children, content, duration = 1000, position = 'bottom
5962
const timerRef = useRef(null);
6063
const mountTimerRef = useRef(null);
6164

62-
const mountTimer = 10;
65+
const mountTimer = 50;
6366

6467
const clearTimeouts = () => {
6568
timerRef.current && clearTimeout(timerRef.current);
@@ -83,12 +86,11 @@ export const Tooltip = ({ children, content, duration = 1000, position = 'bottom
8386

8487
if (!target || !tooltip) return;
8588

86-
tooltip.style.setProperty('--tooltip-animation-ms', `${duration + mountTimer}ms`);
87-
8889
if (mounted) {
90+
tooltipRef.current?.style.setProperty('--tooltip-animation-ms', `${duration + mountTimer}ms`);
8991
const targetRect = target.getBoundingClientRect();
9092
const tooltipRect = tooltip.getBoundingClientRect();
91-
const calcPosition = positionMap[position];
93+
const calcPosition = positionMap[position] ?? positionMap['bottom'];
9294
setCoords(calcPosition({ targetRect, tooltipRect, offset: 5 }));
9395
}
9496

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { Meta } from '@storybook/react';
2+
import { TooltipButtons } from '../shared/tooltip-buttons/TooltipButtons';
3+
4+
const meta: Meta<typeof TooltipButtons> = {
5+
component: TooltipButtons,
6+
title: 'Сложные компоненты/Подсказка/Позиционирование',
7+
tags: ['autodocs'],
8+
};
9+
10+
export default meta;
11+
12+
export const Test = {};

src/stories/TooltipOnButton.stories.tsx renamed to src/stories/TooltipWithProperties.stories.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ import { Button } from '../shared/button/Button';
66

77
const meta: Meta<typeof Tooltip> = {
88
component: Tooltip,
9-
title: 'Сложные компоненты/Подсказка/На кнопке',
9+
title: 'Сложные компоненты/Подсказка/С настройками',
1010
tags: ['autodocs'],
1111
};
1212

1313
export default meta;
1414

1515
export const Test = {
1616
args: {
17-
children: <Button>{'Наведи на меня'}</Button>,
18-
content: 'Плавно всплывающая подсказка',
17+
content: 'Подсказка',
18+
duration: 1000,
19+
position: 'top',
20+
children: <Button>Наведи на меня</Button>,
1921
},
2022
};

0 commit comments

Comments
 (0)