Skip to content

Commit 9cbad00

Browse files
committed
add support for multi-trigger tooltips
1 parent f0282cb commit 9cbad00

File tree

9 files changed

+835
-265
lines changed

9 files changed

+835
-265
lines changed

.size-snapshot.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
{
22
"dist/cjs/react-popper-tooltip.js": {
3-
"bundled": 14603,
4-
"minified": 7833,
5-
"gzipped": 2309
3+
"bundled": 14528,
4+
"minified": 7979,
5+
"gzipped": 2340
66
},
77
"dist/esm/react-popper-tooltip.js": {
8-
"bundled": 14564,
9-
"minified": 7809,
10-
"gzipped": 2303,
8+
"bundled": 14489,
9+
"minified": 7955,
10+
"gzipped": 2335,
1111
"treeshaked": {
1212
"rollup": {
1313
"code": 172,
1414
"import_statements": 152
1515
},
1616
"webpack": {
17-
"code": 8517
17+
"code": 8654
1818
}
1919
}
2020
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ Each placement can have a variation from this list:
234234

235235
### trigger
236236

237-
> `string` | defaults to `hover`
237+
> `string` or `string[]` | defaults to `"hover"`
238238
239-
The event that triggers the tooltip. One of `click`, `right-click`, `hover`, `focus`, and `none`.
239+
The event(s) that trigger the tooltip. One of `click`, `right-click`, `hover`, `focus`, and `none`, or an array of them.
240240

241241
### getTriggerRef
242242

docs/readme.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ _`followCursor` prop_
9797
</div>
9898
</Playground>
9999

100+
## Multi-trigger
101+
102+
<Playground>
103+
<BasicTooltipTrigger trigger={['click', 'hover']} tooltip="Hello, World!">
104+
Click or hover me!
105+
</BasicTooltipTrigger>
106+
</Playground>
107+
100108
## Controlled
101109

102110
_`tooltipShown` prop_

package.json

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-popper-tooltip",
3-
"version": "2.9.1",
3+
"version": "2.10.0",
44
"description": "React tooltip library built around react-popper",
55
"homepage": "https://react-popper-tooltip.netlify.com",
66
"repository": {
@@ -19,18 +19,27 @@
1919
],
2020
"scripts": {
2121
"build": "rm -rf dist && rollup -c && cp src/styles.css dist && yarn tsc && rm -rf compiled",
22-
"prepublishOnly": "yarn typecheck && yarn lint && yarn test && yarn build",
22+
"prepublishOnly": "yarn typecheck && yarn lint && yarn build && yarn test",
2323
"docs": "docz dev",
2424
"docs:build": "docz build",
2525
"typecheck": "tsc --noEmit",
2626
"lint": "eslint src/**/*.{ts,tsx}",
2727
"test": "jest"
2828
},
29-
"pre-commit": [
30-
"typecheck",
31-
"lint",
32-
"test"
33-
],
29+
"husky": {
30+
"hooks": {
31+
"pre-commit": "yarn typecheck && yarn build && yarn test && lint-staged"
32+
}
33+
},
34+
"lint-staged": {
35+
"src/**/*.(ts|tsx)": [
36+
"prettier --write",
37+
"yarn lint --fix"
38+
],
39+
"*": [
40+
"git add"
41+
]
42+
},
3443
"keywords": [
3544
"react",
3645
"tooltip",
@@ -58,26 +67,27 @@
5867
"@babel/preset-react": "^7.6.3",
5968
"@babel/preset-typescript": "^7.6.0",
6069
"@testing-library/react": "^9.3.0",
61-
"@types/jest": "^24.0.19",
62-
"@types/react": "^16.9.9",
63-
"@types/react-dom": "^16.9.2",
64-
"@typescript-eslint/eslint-plugin": "^2.4.0",
65-
"@typescript-eslint/parser": "^2.4.0",
70+
"@types/jest": "^24.0.20",
71+
"@types/react": "^16.9.11",
72+
"@types/react-dom": "^16.9.3",
73+
"@typescript-eslint/eslint-plugin": "^2.5.0",
74+
"@typescript-eslint/parser": "^2.5.0",
6675
"docz": "^1.3.2",
6776
"docz-plugin-css": "^0.11.0",
6877
"docz-theme-default": "^1.2.0",
69-
"eslint": "^6.5.1",
78+
"eslint": "^6.6.0",
7079
"eslint-config-prettier": "^6.4.0",
7180
"eslint-plugin-jsx-a11y": "^6.2.3",
7281
"eslint-plugin-prettier": "^3.1.1",
7382
"eslint-plugin-react": "^7.16.0",
83+
"husky": "^3.0.9",
7484
"jest": "^24.9.0",
75-
"pre-commit": "^1.2.2",
85+
"lint-staged": "^9.4.2",
7686
"prettier": "^1.18.2",
77-
"react": "^16.10.2",
78-
"react-dom": "^16.10.2",
87+
"react": "^16.11.0",
88+
"react-dom": "^16.11.0",
7989
"react-hot-loader": "^4.12.15",
80-
"rollup": "^1.25.0",
90+
"rollup": "^1.25.2",
8191
"rollup-plugin-babel": "^4.3.3",
8292
"rollup-plugin-node-resolve": "^5.2.0",
8393
"rollup-plugin-size-snapshot": "^0.10.0",

src/Tooltip.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Tooltip extends Component<TooltipProps> {
2020
}));
2121
observer.observe(this.tooltipRef!, MUTATION_OBSERVER_CONFIG);
2222

23-
if (trigger !== 'none') {
23+
if (trigger !== 'none' && trigger !== 'focus') {
2424
const {
2525
removeParentOutsideClickHandler,
2626
removeParentOutsideRightClickHandler
@@ -48,7 +48,7 @@ class Tooltip extends Component<TooltipProps> {
4848
this.observer.disconnect();
4949
}
5050

51-
if (trigger !== 'none') {
51+
if (trigger !== 'none' && trigger !== 'focus') {
5252
const {
5353
isParentNoneTriggered,
5454
addParentOutsideClickHandler,

src/TooltipTrigger.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import Tooltip from './Tooltip';
99
import {
1010
GetTriggerPropsArg,
1111
TooltipTriggerProps,
12-
TooltipTriggerState
12+
TooltipTriggerState,
13+
TriggerTypes
1314
} from './types';
1415
import {callAll, canUseDOM, noop} from './utils';
1516

@@ -204,31 +205,31 @@ class TooltipTrigger extends Component<
204205
this[action]({pageX, pageY});
205206
};
206207

207-
private getTriggerProps = (props: GetTriggerPropsArg = {}) => {
208-
const {trigger, followCursor} = this.props;
209-
const isClickTriggered = trigger === 'click';
210-
const isHoverTriggered = trigger === 'hover';
211-
const isRightClickTriggered = trigger === 'right-click';
212-
const isFocusTriggered = trigger === 'focus';
208+
private isTriggeredBy(event: TriggerTypes) {
209+
const {trigger} = this.props;
210+
return (
211+
trigger === event || (Array.isArray(trigger) && trigger.includes(event))
212+
);
213+
}
213214

215+
private getTriggerProps = (props: GetTriggerPropsArg = {}) => {
214216
return {
215217
...props,
216-
...(isClickTriggered && {
218+
...(this.isTriggeredBy('click') && {
217219
onClick: callAll(this.clickToggle, props.onClick),
218220
onTouchEnd: callAll(this.clickToggle, props.onTouchEnd)
219221
}),
220-
...(isRightClickTriggered && {
222+
...(this.isTriggeredBy('right-click') && {
221223
onContextMenu: callAll(this.contextMenuToggle, props.onContextMenu)
222224
}),
223-
...(isHoverTriggered && {
225+
...(this.isTriggeredBy('hover') && {
224226
onMouseEnter: callAll(this.showTooltip, props.onMouseEnter),
225-
onMouseLeave: callAll(this.hideTooltip, props.onMouseLeave)
226-
}),
227-
...(isHoverTriggered &&
228-
followCursor && {
227+
onMouseLeave: callAll(this.hideTooltip, props.onMouseLeave),
228+
...(this.props.followCursor && {
229229
onMouseMove: callAll(this.showTooltip, props.onMouseMove)
230-
}),
231-
...(isFocusTriggered && {
230+
})
231+
}),
232+
...(this.isTriggeredBy('focus') && {
232233
onFocus: callAll(this.showTooltip, props.onFocus),
233234
onBlur: callAll(this.hideTooltip, props.onBlur)
234235
})

src/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from 'react';
33
import ReactPopper from 'react-popper';
44

55
export type TriggerTypes = 'none' | 'click' | 'right-click' | 'hover' | 'focus';
6+
export type Trigger = TriggerTypes | TriggerTypes[];
67

78
export interface GetTriggerPropsArg {
89
onTouchEnd?(event: React.SyntheticEvent): void;
@@ -102,7 +103,7 @@ export interface TooltipTriggerProps {
102103
* Event that triggers the tooltip
103104
* @default hover
104105
*/
105-
trigger: TriggerTypes;
106+
trigger: Trigger;
106107
/**
107108
* Whether to use React.createPortal for creating tooltip
108109
* @default true // for browser environments
@@ -136,7 +137,7 @@ export interface TooltipProps {
136137
outOfBoundaries: boolean | null;
137138
placement: PopperJS.Placement;
138139
style: React.CSSProperties;
139-
trigger: TriggerTypes;
140+
trigger: Trigger;
140141
clearScheduled(): void;
141142
hideTooltip(): void;
142143
tooltip(arg: TooltipArg): React.ReactNode;

tests/TooltipTrigger.spec.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,43 @@ describe('focus trigger', () => {
203203
});
204204
});
205205

206+
describe('multi trigger', () => {
207+
let container: HTMLElement;
208+
let queryByText: any;
209+
210+
beforeEach(() => {
211+
({container, queryByText} = render(
212+
<BasicTooltipTrigger trigger={['hover', 'focus']} tooltip={Tooltip}>
213+
{Trigger}
214+
</BasicTooltipTrigger>
215+
));
216+
fireEvent.focus(container.firstChild as HTMLElement);
217+
jest.runAllTimers();
218+
});
219+
220+
it('opens tooltip on focus', () => {
221+
expect(queryByText(Tooltip)).toBeTruthy();
222+
});
223+
224+
it('closes tooltip on blur', () => {
225+
fireEvent.blur(container.firstChild as HTMLElement);
226+
jest.runAllTimers();
227+
expect(queryByText(Tooltip)).toBeFalsy();
228+
});
229+
230+
it('opens tooltip on mouseEnter', () => {
231+
fireEvent.mouseEnter(container.firstChild as HTMLElement);
232+
jest.runAllTimers();
233+
expect(queryByText(Tooltip)).toBeTruthy();
234+
});
235+
236+
it('closes tooltip on mouseLeave', () => {
237+
fireEvent.mouseLeave(container.firstChild as HTMLElement);
238+
jest.runAllTimers();
239+
expect(queryByText(Tooltip)).toBeFalsy();
240+
});
241+
});
242+
206243
it('closes on outside click', () => {
207244
const {container, queryByText} = render(
208245
<>

0 commit comments

Comments
 (0)