Skip to content

Commit 1a77a10

Browse files
committed
refactor(tooltips): add show prop to interface for manual control over showing and hiding
1 parent bf17305 commit 1a77a10

File tree

7 files changed

+194
-113
lines changed

7 files changed

+194
-113
lines changed

src/action-tooltip.snap.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ exports[`Components: Tooltip should render the component 1`] = `
1010
Hello World!
1111
1212
</div>
13+
1314
</div>
1415
</body>
1516
`;

src/action-tooltip.svelte

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,76 @@
55
import { formatVariableKey, getMinWidth, isInViewport } from './helpers';
66
import { inverse } from './constants';
77
8+
/** @type {'hover' | 'click' | 'prop' | string} */
89
export let action = 'hover';
10+
11+
/** @type {string | {component: any, props?: Record<string, any>}} */
912
export let content = '';
13+
14+
/** @type {'left' | string} */
1015
export let align = 'left';
16+
17+
/** @type {'top' | string} */
1118
export let position = 'top';
19+
20+
/** @type {number} */
1221
export let maxWidth = 200;
13-
/**
14-
* @type {{ [x: string]: any; } | null}
15-
*/
16-
export let style = null;
22+
23+
/** @type {Record<string, string> | null} */
24+
export let style = null;
25+
26+
/** @type {string} */
1727
export let theme = '';
28+
29+
/** @type {string} */
1830
export let animation = '';
31+
32+
/** @type {boolean} */
1933
export let arrow = true;
34+
35+
/** @type {boolean} */
2036
export let autoPosition = false;
2137
22-
/**
23-
* @type {HTMLDivElement | null}
24-
*/
25-
let ref = null;
38+
/** @type {boolean} */
39+
export let show = false;
40+
41+
/** @type {HTMLDivElement | null} */
42+
let tooltipRef = null;
43+
44+
/** @type {number} */
2645
let minWidth = 0;
27-
/**
28-
* @type {{ $destroy: () => void; } | null}
29-
*/
46+
47+
/** @type {any} */
3048
let component = null;
31-
/**
32-
* @type {string | null}
33-
*/
49+
50+
/** @type {string | null} */
3451
let animationEffect = null;
35-
let show = false;
3652
37-
onMount(() => {
38-
const delay = animation ? 200 : 0;
53+
/** @type {boolean} */
54+
let visible = false;
3955
40-
if (ref !== null) {
56+
const delay = animation ? 200 : 0;
57+
58+
onMount(() => {
59+
if (tooltipRef !== null) {
4160
if (isComponent && !component) {
4261
// @ts-ignore
43-
component = new content.component({ target: ref, props: { action, ...content.props } });
62+
component = new content.component({ target: tooltipRef, props: { action, ...content.props } });
4463
}
4564
46-
minWidth = getMinWidth(ref, maxWidth);
65+
minWidth = getMinWidth(tooltipRef, maxWidth);
4766
4867
if (style && typeof style === 'object') {
4968
for (let prop in style) {
5069
const key = formatVariableKey(prop);
5170
const value = style[prop];
5271
53-
ref.style.setProperty(`--tooltip-${key}`, value);
72+
tooltipRef.style.setProperty(`--tooltip-${key}`, value);
5473
}
5574
}
5675
}
5776
58-
if (autoPosition && !isInViewport(ref)) {
77+
if (autoPosition && !isInViewport(tooltipRef)) {
5978
// @ts-ignore
6079
position = inverse[position];
6180
}
@@ -64,7 +83,7 @@
6483
animationEffect = animation;
6584
}
6685
67-
setTimeout(() => (show = true), delay);
86+
setTimeout(() => (visible = true), delay);
6887
});
6988
7089
onDestroy(() => {
@@ -75,13 +94,14 @@
7594
});
7695
7796
$: isComponent = typeof content === 'object';
97+
$: tooltipRef && show ? setTimeout(() => (visible = true), delay) : (visible = false);
7898
</script>
7999

80100
{#if content}
81101
<div
82-
bind:this={ref}
102+
bind:this={tooltipRef}
83103
class="tooltip animation-{animationEffect} {position} {theme}"
84-
class:show
104+
class:show={visible}
85105
class:arrowless={!arrow}
86106
style="min-width: {minWidth}px; max-width: {maxWidth}px; text-align: {align};"
87107
>

src/action-tooltip.svelte.d.ts

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,70 @@ import type { SvelteComponentTyped } from 'svelte';
22

33
export interface ComponentProps {
44
/**
5-
* The content of the tooltip.
6-
* @default ''
5+
* The action to trigger the tooltip
6+
* @default 'hover'
77
*/
8-
content?: string;
8+
action: 'hover' | 'click' | 'prop' | string;
99

1010
/**
11-
* The position of the tooltip.
12-
* Allowed values are 'top', 'bottom', 'left' or 'right'.
13-
* @default 'top'
11+
* The alignment of the tooltip.
12+
* @default 'left'
1413
*/
15-
position?: string;
14+
align?: 'left' | 'right' | 'center' | string;
1615

1716
/**
18-
* The maximum width of the tooltip.
19-
* @default 200
17+
* The animation style of the tooltip.
18+
* @default ''
2019
*/
21-
maxWidth?: number;
20+
animation?: string;
2221

2322
/**
24-
* The style of the tooltip.
25-
* @default null
23+
* Whether to show the arrow of the tooltip.
24+
* @default true
2625
*/
27-
style?: undefined;
26+
arrow?: boolean;
2827

2928
/**
30-
* The theme of the tooltip.
31-
* @default ''
29+
* Whether to automatically position the tooltip when clipping occurs.
30+
* @default false
3231
*/
33-
theme?: string;
32+
autoPosition?: boolean;
3433

3534
/**
36-
* The animation style of the tooltip.
35+
* The content of the tooltip.
3736
* @default ''
3837
*/
39-
animation?: string;
38+
content?: string;
4039

4140
/**
42-
* Whether to show the arrow of the tooltip.
43-
* @default true
41+
* The maximum width of the tooltip.
42+
* @default 200
4443
*/
45-
arrow?: boolean;
44+
maxWidth?: number;
4645

4746
/**
48-
* Whether to automatically position the tooltip.
47+
* The position of the tooltip.
48+
* @default 'top'
49+
*/
50+
position?: 'bottom' | 'left' | 'right' | 'top' | string;
51+
52+
/**
53+
* Control the visibility of the tooltip.
4954
* @default false
5055
*/
51-
autoPosition?: boolean;
56+
show?: boolean;
57+
58+
/**
59+
* The style of the tooltip.
60+
* @default null
61+
*/
62+
style?: undefined;
63+
64+
/**
65+
* The theme of the tooltip.
66+
* @default ''
67+
*/
68+
theme?: string;
5269
}
5370

5471
export default class Component extends SvelteComponentTyped<

src/action.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import Tooltip from './action-tooltip.svelte';
22

33
export const tooltip = (element, props) => {
4-
54
let component = null;
65
let title = element.getAttribute('title');
76
let action = props?.action || element.getAttribute('action') || 'hover';
@@ -17,13 +16,13 @@ export const tooltip = (element, props) => {
1716

1817
const onClick = () => {
1918
if (component) {
20-
onMouseLeave();
19+
onHide();
2120
} else {
22-
onMouseEnter();
21+
onShow();
2322
}
2423
};
2524

26-
const onMouseEnter = () => {
25+
const onShow = () => {
2726
if (!component) {
2827
component = new Tooltip({
2928
target: element,
@@ -32,7 +31,7 @@ export const tooltip = (element, props) => {
3231
}
3332
};
3433

35-
const onMouseLeave = () => {
34+
const onHide = () => {
3635
if (component) {
3736
component.$destroy();
3837
component = null;
@@ -45,25 +44,31 @@ export const tooltip = (element, props) => {
4544

4645
if (action === 'click') {
4746
element.addEventListener('click', onClick);
48-
} else {
49-
element.addEventListener('mouseenter', onMouseEnter);
50-
element.addEventListener('mouseleave', onMouseLeave);
47+
}
48+
49+
if (action === 'hover') {
50+
element.addEventListener('mouseenter', onShow);
51+
element.addEventListener('mouseleave', onHide);
5152
}
5253
}
5354
}
5455

5556
const removeListeners = () => {
5657
if (element !== null) {
5758
element.removeEventListener('click', onClick);
58-
element.removeEventListener('mouseenter', onMouseEnter);
59-
element.removeEventListener('mouseleave', onMouseLeave);
59+
element.removeEventListener('mouseenter', onShow);
60+
element.removeEventListener('mouseleave', onHide);
6061
}
6162
};
6263

6364
addListeners();
6465

6566
element.style.position = 'relative';
6667

68+
if (props.show) {
69+
onShow();
70+
}
71+
6772
return {
6873
destroy() {
6974
removeListeners();

src/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export { default } from "./tooltip.svelte";
1+
export { default as Tooltip } from './tooltip.svelte';
2+
export { tooltip } from './action';

0 commit comments

Comments
 (0)