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

Feature: configurable dismiss timer duration #89

Merged
merged 14 commits into from
Dec 30, 2024
25 changes: 25 additions & 0 deletions site/pages/docs/toast.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ toast('Hello World', {
role: 'status',
'aria-live': 'polite',
},

removeDelay: 1000,
});
```

Expand Down Expand Up @@ -159,6 +161,29 @@ toast.dismiss();

To remove toasts instantly without any animations, use `toast.remove`.

#### Configure toasts' remove delay

```js
toast.custom(
(t) => (
// custom jsx here.
),
{ removeDelay: 500 }
);
```

By default, the remove operation is delayed by 1000ms. This is how long a toast should be kept in the DOM after beeing dismissed. It is used to play the exit animation. This duration (number in milliseconds) can be configured when calling the toast.

Or, for all toasts, using the Toaster like so:

```js
<Toaser
toastOptions={{
removeDelay: 500,
}}
/>
```

#### Remove toasts instanstly

```js
Expand Down
1 change: 1 addition & 0 deletions site/pages/docs/toaster.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This component will render all toasts. Alternatively you can create own renderer
// Define default options
className: '',
duration: 5000,
removeDelay: 1000,
style: {
background: '#363636',
color: '#fff',
Expand Down
17 changes: 12 additions & 5 deletions src/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { DefaultToastOptions, Toast, ToastType } from './types';

const TOAST_LIMIT = 20;
const REMOVE_DELAY = 1000;

export enum ActionType {
ADD_TOAST,
Expand Down Expand Up @@ -50,7 +51,7 @@ interface State {

const toastTimeouts = new Map<Toast['id'], ReturnType<typeof setTimeout>>();

const addToRemoveQueue = (toastId: string) => {
const addToRemoveQueue = (toastId: string, removeDelay = REMOVE_DELAY) => {
if (toastTimeouts.has(toastId)) {
return;
}
Expand All @@ -61,7 +62,7 @@ const addToRemoveQueue = (toastId: string) => {
type: ActionType.REMOVE_TOAST,
toastId: toastId,
});
}, 1000);
}, removeDelay);

toastTimeouts.set(toastId, timeout);
};
Expand Down Expand Up @@ -105,10 +106,13 @@ export const reducer = (state: State, action: Action): State => {

// ! Side effects ! - This could be execrated into a dismissToast() action, but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId);
addToRemoveQueue(
toastId,
state.toasts.find((t) => t.id === toastId)?.removeDelay
);
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id);
addToRemoveQueue(toast.id, toast.removeDelay);
});
}

Expand Down Expand Up @@ -192,6 +196,10 @@ export const useStore = (toastOptions: DefaultToastOptions = {}): State => {
...toastOptions,
...toastOptions[t.type],
...t,
removeDelay:
t.removeDelay ||
toastOptions[t.type]?.removeDelay ||
toastOptions?.removeDelay,
duration:
t.duration ||
toastOptions[t.type]?.duration ||
Expand All @@ -203,7 +211,6 @@ export const useStore = (toastOptions: DefaultToastOptions = {}): State => {
...t.style,
},
}));

return {
...state,
toasts: mergedToasts,
Expand Down
2 changes: 2 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface Toast {
duration?: number;
pauseDuration: number;
position?: ToastPosition;
removeDelay?: number;

ariaProps: {
role: 'status' | 'alert';
Expand All @@ -65,6 +66,7 @@ export type ToastOptions = Partial<
| 'style'
| 'position'
| 'iconTheme'
| 'removeDelay'
>
>;

Expand Down