-
Notifications
You must be signed in to change notification settings - Fork 48
/
index.js
134 lines (121 loc) · 2.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// @flow
import React, { Component, type Node } from 'react';
import cx from 'classnames';
import styles from './Tooltip.css';
type Props = {
children: Node,
content: Node,
className?: string,
onClick?: () => void,
style?: Object,
list?: boolean,
renderDirection?: string,
pointerPosition?: string,
};
type State = {
hovered: boolean,
childrenContainerWidth: number,
};
/**
* A tooltip that appears when you hover over the component placed within.
* The tooltip will by default be centered, however it supports a 'renderDirection'
* prop that will make it render either to the left or the right from the postion of the pointer. The pointer
* (the small arrow that points towards the component within the tooltip) will
* also default to center, and it can be adjusted with the 'pointerPosition' prop.
* Both props can be set as either 'left' or 'right'.
*/
export default class Tooltip extends Component<Props, State> {
static defaultProps = {
list: false,
};
tooltip: ?HTMLDivElement;
measure() {
if (!this.tooltip) {
return;
}
const width = this.tooltip.offsetWidth;
this.setState({
childrenContainerWidth: width,
});
}
state = {
hovered: false,
childrenContainerWidth: 0,
};
onMouseEnter = () => {
this.setState({
hovered: true,
});
};
onMouseLeave = () => {
this.setState({
hovered: false,
});
};
componentDidMount() {
this.measure();
}
render() {
const {
content,
children,
className,
list,
style,
onClick,
renderDirection,
pointerPosition,
} = this.props;
let renderDirectionClass = styles.renderFromCenter;
let startPointChildren = 2;
if (!list) {
switch (renderDirection) {
case 'left':
renderDirectionClass = styles.renderDirectionLeft;
break;
case 'right':
renderDirectionClass = styles.renderDirectionRight;
break;
default:
break;
}
switch (pointerPosition) {
case 'left':
startPointChildren = 9;
break;
case 'right':
startPointChildren = 10 / 9;
break;
default:
break;
}
}
const tooltipClass = this.state.hovered
? styles.baseTooltipHover
: styles.tooltip;
const tooltip = list ? styles.listTooltip : styles.showTooltip;
return (
<div className={className} onClick={onClick}>
<div
ref={(ref) => {
this.tooltip = ref;
}}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
>
<div
className={cx(tooltipClass, tooltip, renderDirectionClass)}
style={{
...style,
marginLeft:
this.state.childrenContainerWidth / startPointChildren - 5,
}}
>
{content}
</div>
{children}
</div>
</div>
);
}
}