Skip to content

Commit 2b355e9

Browse files
authored
Merge pull request #1 from svelte-plugins/bug-fixes
fix: cross-browser animation and add test snapshots
2 parents a4a6e85 + 8fb6188 commit 2b355e9

13 files changed

+194
-115
lines changed

docs/public/global.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/src/App.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,12 @@
183183
<Prism code={"<b use:tooltip={{ content: 'Just another tooltip.', animation: 'slide' }}>tooltip</b>"} />
184184
</div>
185185
<div class="example">
186-
<p>This tooltip uses the <b use:tooltip={{ content: 'Just another tooltip.', animation: 'puff', maxWidth: 140 }}>Puff</b> animation.</p>
186+
<p>This tooltip uses the <b use:tooltip={{ content: 'Just another tooltip.', animation: 'puff' }}>Puff</b> animation.</p>
187187
<Prism code={"<b use:tooltip={{ content: 'Just another tooltip.', animation: 'puff' }}>tooltip</b>"} />
188188
</div>
189189

190190
<div class="example">
191-
<p>This tooltip uses the <b use:tooltip={{ content: 'Just another tooltip.', animation: 'bounce', maxWidth: 140 }}>Bounce</b> animation.</p>
191+
<p>This tooltip uses the <b use:tooltip={{ content: 'Just another tooltip.', animation: 'bounce' }}>Bounce</b> animation.</p>
192192
<Prism code={"<b use:tooltip={{ content: 'Just another tooltip.', animation: 'bounce' }}>tooltip</b>"} />
193193
</div>
194194

jest.config.json

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,20 @@
22
"rootDir": "./",
33
"verbose": true,
44
"snapshotResolver": "<rootDir>/snapshot-resolver.js",
5-
"restoreMocks": true,
65
"transform": {
7-
"^.+\\.test.js$": "babel-jest",
6+
"^.+\\.(test.js|js)$": "babel-jest",
87
"^.+\\.svelte$": "jest-transform-svelte"
98
},
10-
"collectCoverageFrom": [
11-
"src/**/*.svelte",
12-
"!<rootDir>/src/*.test.svelte"
13-
],
9+
"testMatch": ["<rootDir>/src/**/*.test.js"],
10+
"collectCoverage": true,
11+
"coverageReporters": ["lcov", "json-summary", "text-summary"],
12+
"collectCoverageFrom": ["<rootDir>/src/**/*.svelte", "!<rootDir>/src/*.test.svelte"],
1413
"moduleNameMapper": {
1514
"^tests/(.*)$": "<rootDir>/tests/$1"
1615
},
17-
"modulePathIgnorePatterns": [
18-
"<rootDir>/tests"
19-
],
20-
"moduleFileExtensions": [
21-
"js",
22-
"svelte"
23-
],
24-
"setupFilesAfterEnv": [
25-
"@testing-library/jest-dom/extend-expect"
26-
]
16+
"moduleFileExtensions": ["js", "svelte"],
17+
"transformIgnorePatterns": ["/node_modules/"],
18+
"setupFilesAfterEnv": ["@testing-library/jest-dom/extend-expect"],
19+
"reporters": ["default"],
20+
"testTimeout": 30000
2721
}

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@svelte-plugins/tooltips",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"license": "MIT",
55
"description": "A simple tooltip action and component designed for Svelte.",
66
"author": "Kieran Boyle (https://github.com/dysfunc)",

src/action-tooltip.snap.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Components: Tooltip should render the component 1`] = `
4+
<body>
5+
<div>
6+
<div
7+
class="tooltip animation-null top"
8+
style="min-width: 200px; max-width: 200px; text-align: left;"
9+
>
10+
Hello World!
11+
12+
</div>
13+
</div>
14+
</body>
15+
`;

src/action-tooltip.svelte

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<script>
22
import { onMount, onDestroy } from 'svelte';
3+
import { formatVariableKey, getMinWidth, isInViewport } from './helpers';
4+
import { inverse } from './constants';
35
46
export let content = '';
57
export let align = 'left';
@@ -14,59 +16,38 @@
1416
let ref = null;
1517
let minWidth = 0;
1618
let component = null;
17-
18-
const inverse = {
19-
left: 'right',
20-
right: 'left',
21-
top: 'bottom',
22-
bottom: 'top'
23-
};
24-
25-
const isInViewport = () => {
26-
const rect = ref.getBoundingClientRect();
27-
28-
return (
29-
rect.top >= 0 &&
30-
rect.left >= 0 &&
31-
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
32-
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
33-
);
34-
};
19+
let animationEffect = null;
20+
let show = false;
3521
3622
onMount(() => {
23+
const delay = animation ? 200 : 0;
24+
3725
if (ref !== null) {
3826
if (isComponent && !component) {
3927
component = new content.component({ target: ref, props: content.props });
4028
}
4129
42-
const elementWidth = ref.getBoundingClientRect().width;
43-
const elementStyle = window.getComputedStyle(ref);
44-
const elementPaddingLeft = parseInt(elementStyle.getPropertyValue('padding-left'), 10);
45-
const elementPaddingRight = parseInt(elementStyle.getPropertyValue('padding-right'), 10);
46-
const elementPadding = elementPaddingLeft + elementPaddingRight;
47-
const contentWidth = elementWidth - elementPadding;
48-
49-
minWidth = Math.round(Math.min(maxWidth, contentWidth));
30+
minWidth = getMinWidth(ref, maxWidth);
5031
5132
if (style && typeof style === 'object') {
5233
for (let prop in style) {
34+
const key = formatVariableKey(prop);
5335
const value = style[prop];
54-
const key = prop
55-
.replace(/-_$/g, '')
56-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
57-
.replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2')
58-
.toLowerCase();
5936
6037
ref.style.setProperty(`--tooltip-${key}`, value);
6138
}
6239
}
6340
}
6441
65-
if (autoPosition && !isInViewport()) {
42+
if (autoPosition && !isInViewport(ref)) {
6643
position = inverse[position];
6744
}
6845
69-
ref.classList.add('show');
46+
if (animation) {
47+
animationEffect = animation;
48+
}
49+
50+
setTimeout(() => (show = true), delay);
7051
});
7152
7253
onDestroy(() => {
@@ -81,7 +62,8 @@
8162

8263
<div
8364
bind:this={ref}
84-
class="tooltip animation-{animation} {position} {theme}"
65+
class="tooltip animation-{animationEffect} {position} {theme}"
66+
class:show
8567
class:arrowless={!arrow}
8668
style="min-width: {minWidth}px; max-width: {maxWidth}px; text-align: {align};"
8769
>
@@ -121,6 +103,7 @@
121103
box-shadow: var(--tooltip-box-shadow);
122104
border-radius: var(--tooltip-border-radius);
123105
color: var(--tooltip-color);
106+
opacity: 0;
124107
font-family: var(--tooltip-font-family);
125108
font-size: var(--tooltip-font-size);
126109
font-style: normal;
@@ -129,11 +112,14 @@
129112
padding: var(--tooltip-padding);
130113
position: absolute;
131114
text-align: left;
115+
visibility: hidden;
132116
white-space: nowrap;
133117
z-index: var(--tooltip-z-index);
134118
}
135119
136120
.tooltip.show {
121+
opacity: 1;
122+
visibility: visible;
137123
white-space: normal;
138124
}
139125
@@ -210,7 +196,7 @@
210196
211197
.tooltip.animation-fade {
212198
opacity: 0;
213-
transition: opacity 0.3s ease-in-out;
199+
transition: opacity 0.25s ease-in-out;
214200
}
215201
216202
.tooltip.animation-fade.show {
@@ -222,7 +208,7 @@
222208
.tooltip.top.animation-slide {
223209
margin-top: 10px;
224210
opacity: 0;
225-
transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out;
211+
transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out;
226212
}
227213
228214
.tooltip.top.animation-slide.show {
@@ -233,7 +219,7 @@
233219
.tooltip.bottom.animation-slide {
234220
margin-bottom: 20px;
235221
opacity: 0;
236-
transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out;
222+
transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out;
237223
}
238224
239225
.tooltip.bottom.animation-slide.show {
@@ -244,7 +230,7 @@
244230
.tooltip.right.animation-slide {
245231
margin-right: 20px;
246232
opacity: 0;
247-
transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out;
233+
transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out;
248234
}
249235
250236
.tooltip.right.animation-slide.show {
@@ -255,7 +241,7 @@
255241
.tooltip.left.animation-slide {
256242
margin-left: 20px;
257243
opacity: 0;
258-
transition: opacity 0.3s ease-in-out, margin 0.3s ease-in-out;
244+
transition: opacity 0.25s ease-in-out, margin 0.25s ease-in-out;
259245
}
260246
261247
.tooltip.left.animation-slide.show {
@@ -270,7 +256,7 @@
270256
opacity: 0;
271257
transform: translate(calc(-100% - var(--tooltip-offset-x)), -50%) scale(2, 2);
272258
transform-origin: 50% 50%;
273-
transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out;
259+
transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out;
274260
}
275261
276262
.tooltip.left.animation-puff.show {
@@ -284,7 +270,7 @@
284270
opacity: 0;
285271
transform: translate(calc(100% + var(--tooltip-offset-x)), -50%) scale(2, 2);
286272
transform-origin: 50% 50%;
287-
transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out;
273+
transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out;
288274
}
289275
290276
.tooltip.right.animation-puff.show {
@@ -298,7 +284,7 @@
298284
opacity: 0;
299285
transform: translate(-50%, calc(-100% - var(--tooltip-offset-y))) scale(2, 2);
300286
transform-origin: 50% 50%;
301-
transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out;
287+
transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out;
302288
}
303289
304290
.tooltip.top.animation-puff.show {
@@ -312,7 +298,7 @@
312298
opacity: 0;
313299
transform: translate(-50%, calc(100% + var(--tooltip-offset-y))) scale(2, 2);
314300
transform-origin: 50% 50%;
315-
transition: opacity 0.3s ease-in-out, filter 0.3s ease-in-out, transform 0.3s ease-in-out;
301+
transition: opacity 0.25s ease-in-out, filter 0.25s ease-in-out, transform 0.25s ease-in-out;
316302
}
317303
318304
.tooltip.bottom.animation-puff.show {
@@ -327,7 +313,7 @@
327313
opacity: 0;
328314
transform: translate(calc(-100% - var(--tooltip-offset-x)), -50%) scale(1.2, 1.2);
329315
transform-origin: 50% 50%;
330-
transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3);
316+
transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3);
331317
}
332318
333319
.tooltip.left.animation-bounce.show {
@@ -339,7 +325,7 @@
339325
opacity: 0;
340326
transform: translate(calc(100% + var(--tooltip-offset-x)), -50%) scale(1.2, 1.2);
341327
transform-origin: 50% 50%;
342-
transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3);
328+
transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3);
343329
}
344330
345331
.tooltip.right.animation-bounce.show {
@@ -351,7 +337,7 @@
351337
opacity: 0;
352338
transform: translate(-50%, calc(-100% - var(--tooltip-offset-y))) scale(1.2, 1.2);
353339
transform-origin: 50% 50%;
354-
transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3);
340+
transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3);
355341
}
356342
357343
.tooltip.top.animation-bounce.show {
@@ -363,7 +349,7 @@
363349
opacity: 0;
364350
transform: translate(-50%, calc(100% + var(--tooltip-offset-y))) scale(1.2, 1.2);
365351
transform-origin: 50% 50%;
366-
transition: opacity 0.3s ease-in-out, transform 0.3s cubic-bezier(0.5, -1, 0.5, 3);
352+
transition: opacity 0.25s ease-in-out, transform 0.25s cubic-bezier(0.5, -1, 0.5, 3);
367353
}
368354
369355
.tooltip.bottom.animation-bounce.show {

src/action-tooltip.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { render } from '@testing-library/svelte';
2+
import Tooltip from './action-tooltip.svelte';
3+
4+
describe('Components: Tooltip', () => {
5+
let TestHarness;
6+
7+
beforeEach(() => {
8+
TestHarness = () =>
9+
render(Tooltip, {
10+
content: 'Hello World!'
11+
});
12+
});
13+
14+
it('should render the component', () => {
15+
const { container } = TestHarness();
16+
expect(container).toMatchSnapshot();
17+
});
18+
});

src/constants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const inverse = {
2+
left: 'right',
3+
right: 'left',
4+
top: 'bottom',
5+
bottom: 'top'
6+
};

src/helpers.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export const formatVariableKey = (str) => {
2+
return str
3+
.replace(/-_$/g, '')
4+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
5+
.replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2')
6+
.toLowerCase();
7+
};
8+
9+
export const getMinWidth = (element, maxWidth) => {
10+
const extraCharPadding = 2;
11+
const elementWidth = element.getBoundingClientRect().width + extraCharPadding;
12+
const elementStyle = window.getComputedStyle(element);
13+
const elementPaddingLeft = parseInt(elementStyle.getPropertyValue('padding-left'), 10);
14+
const elementPaddingRight = parseInt(elementStyle.getPropertyValue('padding-right'), 10);
15+
const elementPadding = elementPaddingLeft + elementPaddingRight;
16+
const contentWidth = elementWidth - elementPadding;
17+
18+
return Math.round(Math.min(maxWidth, contentWidth || maxWidth));
19+
};
20+
21+
export const isInViewport = (element) => {
22+
const rect = element.getBoundingClientRect();
23+
24+
return (
25+
rect.top >= 0 &&
26+
rect.left >= 0 &&
27+
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
28+
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
29+
);
30+
};

0 commit comments

Comments
 (0)