Skip to content

Commit aa1a478

Browse files
committed
Finalized tooltips
1 parent 515dbf9 commit aa1a478

File tree

6 files changed

+177
-35
lines changed

6 files changed

+177
-35
lines changed

__tests__/Tooltip.test.tsx

Whitespace-only changes.

jest.config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$",
32
"setupFilesAfterEnv": ["./setupTests.ts"],
43
"moduleNameMapper": {
54
"@/(.*)": "<rootDir>/src/$1"

src/components/Overlay/OverlayTrigger.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,28 @@ const OverlayTrigger = ({
6363
}
6464
}
6565

66+
const createChildren = () => shown && (
67+
<Overlay
68+
motion={motion}
69+
arrow={arrow}
70+
triggerRef={triggerRef}
71+
placement={placement}
72+
positionStrategy={positionStrategy}
73+
className={className}
74+
>
75+
{overlay}
76+
</Overlay>
77+
)
78+
6679
return (
6780
<>
6881
{React.cloneElement(triggerElement, {
6982
ref: triggerRef,
7083
...attachEvents(triggerElement, trigger)
7184
})}
72-
<AnimatePresence>
73-
{shown && (
74-
<Overlay
75-
motion={motion}
76-
arrow={arrow}
77-
triggerRef={triggerRef}
78-
placement={placement}
79-
positionStrategy={positionStrategy}
80-
className={className}
81-
>
82-
{overlay}
83-
</Overlay>
84-
)}
85-
</AnimatePresence>
85+
{motion
86+
? React.createElement(AnimatePresence, {}, createChildren())
87+
: createChildren()}
8688
</>
8789
)
8890
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { mount } from 'enzyme';
2+
import React from 'react';
3+
import OverlayTrigger from '@/components/Overlay/OverlayTrigger';
4+
import { motion } from 'framer-motion';
5+
6+
describe('Overlay test', () => {
7+
it('should render overlay when hovered', async () => {
8+
const tooltip = mount(
9+
<div>
10+
<OverlayTrigger
11+
overlay="test"
12+
>
13+
<button>test</button>
14+
</OverlayTrigger>
15+
</div>
16+
);
17+
18+
tooltip.find('button').simulate('mouseenter');
19+
20+
expect(tooltip.find('.content').text()).toBe('test');
21+
22+
tooltip.find('button').simulate('mouseleave');
23+
24+
expect(tooltip.find('.content').length).toBe(0);
25+
});
26+
27+
it('should call props along hover triggers', async () => {
28+
const mockFnEnter = jest.fn();
29+
const mockFnLeave = jest.fn();
30+
31+
const tooltip = mount(
32+
<div>
33+
<OverlayTrigger
34+
overlay="test"
35+
>
36+
<button onMouseEnter={mockFnEnter} onMouseLeave={mockFnLeave}>test</button>
37+
</OverlayTrigger>
38+
</div>
39+
);
40+
41+
tooltip.find('button').simulate('mouseenter');
42+
tooltip.find('button').simulate('mouseleave');
43+
44+
expect(mockFnEnter).toHaveBeenCalled();
45+
expect(mockFnLeave).toHaveBeenCalled();
46+
});
47+
48+
it('should render overlay when clicked', async () => {
49+
const mockFn = jest.fn();
50+
51+
const tooltip = mount(
52+
<div>
53+
<OverlayTrigger
54+
trigger="click"
55+
overlay="test"
56+
>
57+
<button onClick={mockFn}>test</button>
58+
</OverlayTrigger>
59+
</div>
60+
);
61+
62+
tooltip.find('button').simulate('click');
63+
64+
expect(tooltip.find('.content').text()).toBe('test');
65+
expect(mockFn).toHaveBeenCalled();
66+
});
67+
68+
it('should render overlay with arrow', async () => {
69+
const tooltip = mount(
70+
<div>
71+
<OverlayTrigger
72+
trigger="click"
73+
overlay="test"
74+
arrow
75+
>
76+
<button>test</button>
77+
</OverlayTrigger>
78+
</div>
79+
);
80+
81+
tooltip.find('button').simulate('click');
82+
83+
expect(tooltip.find('.arrow')).toBeDefined();
84+
});
85+
86+
it('should render overlay without arrow', async () => {
87+
const tooltip = mount(
88+
<div>
89+
<OverlayTrigger
90+
trigger="click"
91+
overlay="test"
92+
arrow={false}
93+
>
94+
<button>test</button>
95+
</OverlayTrigger>
96+
</div>
97+
);
98+
99+
tooltip.find('button').simulate('click');
100+
101+
expect(tooltip.find('.arrow').length).toBe(0);
102+
});
103+
104+
it('should should use motion when defined', async () => {
105+
const tooltip = mount(
106+
<div>
107+
<OverlayTrigger
108+
trigger="click"
109+
overlay="test"
110+
motion="fade"
111+
>
112+
<button>test</button>
113+
</OverlayTrigger>
114+
</div>
115+
);
116+
117+
tooltip.find('button').simulate('click');
118+
119+
expect(tooltip.find(motion.div)).toBeDefined();
120+
});
121+
122+
it('should should ignore undefined motion', async () => {
123+
const tooltip = mount(
124+
<div>
125+
<OverlayTrigger
126+
trigger="click"
127+
overlay="test"
128+
motion="bounce"
129+
>
130+
<button>test</button>
131+
</OverlayTrigger>
132+
</div>
133+
);
134+
135+
tooltip.find('button').simulate('click');
136+
137+
expect(tooltip.find(motion.div).length).toBe(0);
138+
});
139+
});

src/components/Overlay/index.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const Overlay = ({
6161
return {};
6262
}
6363

64-
useEffect((): void => {
64+
useEffect(() => {
6565
if (ref.current && triggerRef.current) {
6666
popper.current = createPopper(
6767
triggerRef.current,
@@ -72,6 +72,17 @@ const Overlay = ({
7272
}
7373
}, [])
7474

75+
const createChildren = () => (
76+
<>
77+
{arrow && (<div className="overlay-arrow arrow" />)}
78+
<div
79+
className="content"
80+
>
81+
{children}
82+
</div>
83+
</>
84+
);
85+
7586
return createPortal(
7687
<MotionConfig features={[ExitFeature, AnimationFeature]}>
7788
<div
@@ -82,26 +93,21 @@ const Overlay = ({
8293
className
8394
)}
8495
>
85-
<motion.div
86-
className="overlay-animator"
87-
exit={{}}
88-
{...createMotion()}
89-
>
90-
{arrow && (<div className="overlay-arrow arrow" />)}
91-
<div
92-
className="content"
93-
>
94-
{children}
95-
</div>
96-
</motion.div>
96+
{Object.keys(createMotion()).length
97+
? React.createElement<HTMLMotionProps<'div'>>(motion.div, {
98+
className: 'overlay-animator',
99+
...createMotion(),
100+
}, createChildren())
101+
: createChildren()
102+
}
97103
</div>
98104
</MotionConfig>,
99105
document.body
100106
)
101107
}
102108

103109
Overlay.propTypes = {
104-
triggerRef: PropTypes.shape({ current: PropTypes.instanceOf(HTMLElement) })
110+
triggerRef: PropTypes.shape({current: PropTypes.instanceOf(HTMLElement)})
105111
}
106112

107113
export default Overlay;

src/style/components/_overlay.scss

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
.overlay-container {
2-
> .overlay-animator {
3-
position: relative;
4-
}
5-
62
> .overlay-animator, & {
73
> .arrow {
84
position: absolute;
@@ -23,7 +19,7 @@
2319
}
2420

2521
> .arrow {
26-
bottom: -8px;
22+
bottom: 0;
2723
height: 8px;
2824
width: 16px;
2925

@@ -45,7 +41,7 @@
4541
}
4642

4743
> .arrow {
48-
top: -8px;
44+
top: 0;
4945
height: 8px;
5046
width: 16px;
5147

0 commit comments

Comments
 (0)