Skip to content

Commit

Permalink
fix(@vtmn/svelte, @vtmn/css): fix timeout on overlays components (#…
Browse files Browse the repository at this point in the history
…1480)

Co-authored-by: Thibault Mahe <[email protected]>
  • Loading branch information
Tlahey and thibault-mahe committed Feb 12, 2024
1 parent 877a592 commit 15ccc52
Show file tree
Hide file tree
Showing 20 changed files with 163 additions and 35 deletions.
3 changes: 2 additions & 1 deletion packages/showcases/svelte/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import viewports from '@vtmn/showcase-core/addons/viewports.json';
import DivDecorator from './DivDecorator.svelte';
import { addReadme } from 'storybook-readme/html';

import "@vtmn/svelte/dist/index.css"
import "@vtmn/css-design-tokens/dist/index.css";
import "@vtmn/svelte/dist/index-with-vars.css";
import '@vtmn/icons/dist/vitamix/font/vitamix.css';

export const decorators = [() => DivDecorator, withDesign, addReadme];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
type: 'text',
},
},
timeout: {
type: { name: 'number', required: false },
description: 'Duration of the animation',
defaultValue: 8000,
control: {
type: 'number',
},
},
variant: {
type: { name: 'boolean', required: false },
description: 'Variant of the alert',
Expand Down Expand Up @@ -85,7 +93,7 @@
args={{
title: undefined,
description: undefined,
timeout: 0,
timeout: null,
ariaLabelCloseButton: 'Close alert',
}}
let:args
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@
<Meta
title="Components / Overlays / VtmnSnackbar"
component={VtmnSnackbar}
{argTypes}
argTypes={{
...argTypes,
timeout: {
type: { name: 'number', required: false },
description: 'Duration of the animation',
defaultValue: 4500,
control: {
type: 'number',
},
},
}}
parameters={{
...parameters,
readme: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@
<Meta
title="Components / Overlays / VtmnToast"
component={VtmnToast}
{argTypes}
argTypes={{
...argTypes,
timeout: {
type: { name: 'number', required: false },
description: 'Duration of the animation',
defaultValue: 4500,
control: {
type: 'number',
},
},
}}
parameters={{
...parameters,
readme: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
position: fixed;
inset-block-start: rem(32px);
inset-inline-end: rem(16px);
margin-left: rem(16px);
animation: var(--vtmn-animation_alert);
}

Expand All @@ -130,3 +131,7 @@
animation: var(--vtmn-animation_alert-mobile);
}
}

.vtmn-alert.animate-delay {
animation-delay: 0s, 0s, var(--vtmn-animation_alert-duration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@
transform: translate(50%, 0%);
}
}

.vtmn-snackbar.animate-delay {
animation-delay: 0s, 0s, var(--vtmn-animation_overlay-duration),
var(--vtmn-animation_overlay-duration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,8 @@
margin: 0 auto;
}
}

.vtmn-toast.animate-delay {
animation-delay: 0s, 0s, var(--vtmn-animation_overlay-duration),
var(--vtmn-animation_overlay-duration);
}
17 changes: 11 additions & 6 deletions packages/sources/css/src/design-tokens/src/animations.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
:root {
--vtmn-animation_alert: fade-in 200ms ease-in forwards,
slide-left 0.2s ease-in forwards, slide-right 0.2s 7.5s ease-in forwards;
--vtmn-animation_alert-mobile: fade_in 200ms ease-in forwards,
slide-up 0.2s ease-in forwards, slide-down 0.2s 7.5s ease-in forwards;
--vtmn-animation_alert-duration: 7.5s;
--vtmn-animation_overlay-duration: 4.5s;
--vtmn-animation_alert: fade-in 0.2s ease-in forwards,
slide-left 0.2s ease-in forwards,
slide-right 0.2s var(--vtmn-animation_alert-duration) ease-in forwards;
--vtmn-animation_alert-mobile: fade_in 0.2s ease-in forwards,
slide-up 0.2s ease-in forwards,
slide-down 0.2s var(--vtmn-animation_alert-duration) ease-in forwards;
--vtmn-animation_fade-in: fade-in 200ms ease-in-out forwards;
--vtmn-animation_show-up: show-up 400ms ease-in-out forwards;
--vtmn-animation_overlay: fade-in 0.5s ease-in-out forwards,
show-up 0.5s ease-in-out forwards, fade-out 0.5s 4.5s ease-in-out forwards,
vanish 0.5s 4.5s ease-in-out forwards;
show-up 0.5s ease-in-out forwards,
fade-out 0.5s var(--vtmn-animation_overlay-duration) ease-in-out forwards,
vanish 0.5s var(--vtmn-animation_overlay-duration) ease-in-out forwards;
--vtmn-animation_linear-indeterminate: 1.5s ease-in-out infinite
linear-indeterminate;
--vtmn-animation_circle-indeterminate: 4s linear infinite circle-indeterminate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import VtmnButton from '../../actions/VtmnButton/VtmnButton.svelte';
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import { cn } from '../../../utils/classnames';
import { VTMN_ALERT_VARIANT } from './enums';
import {
VTMN_ALERT_TIMEOUT,
VTMN_ALERT_VARIANT,
CSS_ANIMATION_TIME_MS,
INFINITE_TIMEOUT_MS,
} from './enums';
/**
* @type {'info'|'success'|'danger'|'warning'} variant of the alert
Expand All @@ -29,10 +34,9 @@
/**
* @type {number} time (ms) before the alert disappears
* Can't be above 8000ms.
* Set to 0 to keep the alert visible
* Set to Infinity to keep the alert visible
*/
export let timeout = 8000;
export let timeout = VTMN_ALERT_TIMEOUT;
/**
* @type {string} aria label on the button
Expand All @@ -49,18 +53,34 @@
const closeHandler = () => dispatch('close');
const _clearTimeout = () => timeoutId && clearTimeout(timeoutId);
const _setTimeout = () =>
(timeoutId = timeout && setTimeout(closeHandler, timeout));
(timeoutId =
typeof timeout === 'number' &&
setTimeout(
closeHandler,
(timeout < Infinity ? timeout : INFINITE_TIMEOUT_MS) +
CSS_ANIMATION_TIME_MS,
));
onDestroy(_clearTimeout);
onMount(_setTimeout);
$: componentClass = cn(
'vtmn-alert',
timeout > 0 && 'show',
typeof timeout === 'number' && 'show animate-delay',
variant && `vtmn-alert_variant--${variant}`,
className,
);
</script>

<div class={componentClass} role="alert" tabindex="-1" {...$$restProps}>
<div
class={componentClass}
style:--vtmn-animation_alert-duration={typeof timeout === 'number' &&
timeout < Infinity
? `${timeout}ms`
: `${INFINITE_TIMEOUT_MS}ms`}
role="alert"
tabindex="-1"
{...$$restProps}
>
<div class="vtmn-alert_content" role="document">
<div class="vtmn-alert_content-title">
{#if $$slots.title}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export const VTMN_ALERT_TIMEOUT = 8000;

export const CSS_ANIMATION_TIME_MS = 700;

export const INFINITE_TIMEOUT_MS = 9999000;

export const VTMN_ALERT_VARIANT = {
INFO: 'info',
WARNING: 'warning',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import '@testing-library/jest-dom';
import { fireEvent, render, waitFor } from '@testing-library/svelte';
import VtmnAlertItem from '../VtmnAlertItem.svelte';
import VtmnAlertItemWithSlot from './VtmnAlertItemWithSlots.test.svelte';
import { CSS_ANIMATION_TIME_MS } from '../enums';

const timeout = 5000;

Expand Down Expand Up @@ -165,7 +166,7 @@ describe('VtmnAlertItem', () => {
component.$on('close', handleClick);
expect(handleClick).toHaveBeenCalledTimes(0);
await waitFor(() => expect(handleClick).toHaveBeenCalledTimes(1), {
timeout: 100,
timeout: 100 + CSS_ANIMATION_TIME_MS,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

{#each $vtmnSnackbarStore as snackbar (snackbar.id)}
<VtmnSnackbarItem
timeout={VTMN_SNACKBAR_TIMEOUT}
timeout={typeof snackbar.timeout === 'number'
? snackbar.timeout
: VTMN_SNACKBAR_TIMEOUT}
content={snackbar.content}
withCloseButton={snackbar.withCloseButton}
actionLabel={snackbar.action.label}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { cn } from '../../../utils/classnames';
import VtmnButton from '../../actions/VtmnButton/VtmnButton.svelte';
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import { INFINITE_TIMEOUT_MS, CSS_ANIMATION_TIME_MS } from './enum';
/**
* @type {string} text write into the snackbar
Expand All @@ -21,6 +22,7 @@
/**
* @type {number} timeout before the component execute the close action.
* Set to Infinity to keep the snackbar visible
*/
export let timeout;
Expand All @@ -31,20 +33,33 @@
export { className as class };
let timeoutId;
const dispatch = createEventDispatcher();
const closeHandler = () => dispatch('close');
const actionHandler = () => dispatch('action');
const _clearTimeout = () => timeoutId && clearTimeout(timeoutId);
const _setTimeout = () => (timeoutId = setTimeout(closeHandler, timeout));
const _setTimeout = () =>
(timeoutId =
typeof timeout === 'number' &&
setTimeout(
closeHandler,
(timeout < Infinity ? timeout : INFINITE_TIMEOUT_MS) +
CSS_ANIMATION_TIME_MS,
));
onDestroy(_clearTimeout);
onMount(_setTimeout);
$: componentClass = cn('vtmn-snackbar', 'show', className);
$: componentClass = cn('vtmn-snackbar show animate-delay', className);
</script>

<div class={componentClass} role="status">
<div
class={componentClass}
style:--vtmn-animation_overlay-duration={typeof timeout === 'number' &&
timeout < Infinity
? `${timeout}ms`
: `${INFINITE_TIMEOUT_MS}ms`}
role="status"
>
<div class="vtmn-snackbar_content">
{content}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const VTMN_SNACKBAR_TIMEOUT = 5000;
export const VTMN_SNACKBAR_TIMEOUT = 4500;
export const INFINITE_TIMEOUT_MS = 9999000;
export const CSS_ANIMATION_TIME_MS = 500; // sum total animation css + safety threshold
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import '@testing-library/jest-dom';
import { fireEvent, render, waitFor } from '@testing-library/svelte';

import VtmnSnackbarItem from '../VtmnSnackbarItem.svelte';
import { CSS_ANIMATION_TIME_MS } from '../enum';

describe('VtmnSnackbar', () => {
const timeout = 1000;
Expand Down Expand Up @@ -43,7 +44,7 @@ describe('VtmnSnackbar', () => {
component.$on('close', handleClick);
expect(handleClick).toHaveBeenCalledTimes(0);
await waitFor(() => expect(handleClick).toHaveBeenCalledTimes(1), {
timeout: 100,
timeout: 100 + CSS_ANIMATION_TIME_MS,
});
});
test('Should trigger event on click button close', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ class VtmnSnackbarStore {
this._snackbar = writable([]);
}

send({ content, withCloseButton, action }) {
send({ content, withCloseButton, action, timeout }) {
this._snackbar.set([
{ content, withCloseButton, action, id: `vtmn-snackbar-${uuid()}` },
{
content,
withCloseButton,
action,
timeout,
id: `vtmn-snackbar-${uuid()}`,
},
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import VtmnButton from '../../actions/VtmnButton/VtmnButton.svelte';
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import { cn } from '../../../utils/classnames';
import { INFINITE_TIMEOUT_MS, CSS_ANIMATION_TIME_MS } from './enums';
/**
* @type {boolean} display the toast with an icon
Expand All @@ -22,6 +23,7 @@
/**
* @type {number} Time (ms) before the component dispatch automatically 'close'
* Set to Infinity to keep the toast visible
*/
export let timeout;
Expand All @@ -36,19 +38,34 @@
const dispatch = createEventDispatcher();
const closeHandler = () => dispatch('close');
const _clearTimeout = () => timeoutId && clearTimeout(timeoutId);
const _setTimeout = () => (timeoutId = setTimeout(closeHandler, timeout));
const _setTimeout = () =>
(timeoutId =
typeof timeout === 'number' &&
setTimeout(
closeHandler,
(timeout < Infinity ? timeout : INFINITE_TIMEOUT_MS) +
CSS_ANIMATION_TIME_MS,
));
onDestroy(_clearTimeout);
onMount(_setTimeout);
$: componentClass = cn(
'vtmn-toast',
'show',
timeout > 0 && 'show animate-delay',
withIcon && 'vtmn-toast--with-icon-info',
className,
);
</script>

<div class={componentClass} role="status" {...$$restProps}>
<div
class={componentClass}
style:--vtmn-animation_overlay-duration={typeof timeout === 'number' &&
timeout < Infinity
? `${timeout}ms`
: `${INFINITE_TIMEOUT_MS}ms`}
role="status"
{...$$restProps}
>
<div class="vtmn-toast_content">{content}</div>
{#if withCloseButton}
<VtmnButton
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const VTMN_TOAST_TIMEOUT = 5000;
export const VTMN_TOAST_TIMEOUT = 4500;
export const INFINITE_TIMEOUT_MS = 9999000;
export const CSS_ANIMATION_TIME_MS = 500; // sum total animation css + safety threshold
Loading

0 comments on commit 15ccc52

Please sign in to comment.