Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(@vtmn/svelte, @vtmn/css): fix timeout on overlays components #1480

Merged
merged 4 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading