diff --git a/docs/docs/Toaster.md b/docs/docs/Toaster.md index 7dd4051..e991e9a 100644 --- a/docs/docs/Toaster.md +++ b/docs/docs/Toaster.md @@ -66,4 +66,5 @@ You can provide default styles for all toasts by passing `style` and `className` | toastOptions | These will act as default options for all toasts. See [toast()](/toast) for all available options. | `{}` | | gap | Gap between toasts when expanded | `16` | | icons | Changes the default icons | `-` | +| pauseWhenPageIsHidden | Pauses toast timers when the app enters background. | `-` | | `swipToDismissDirection` | Swipe direction to dismiss (`left`, `up`). | `up` | diff --git a/docs/docs/sonner.md b/docs/docs/sonner.md index dbbd152..8da9a2f 100644 --- a/docs/docs/sonner.md +++ b/docs/docs/sonner.md @@ -46,7 +46,7 @@ | offset | βœ… | βœ… | | hotkey | πŸ•ΈοΈ | βœ… | | loadingIcon | ❌ | βœ… | -| pauseWhenPageIsHidden | ❌ | βœ… | +| pauseWhenPageIsHidden | βœ… | βœ… | | cn | ❌ | βœ… | **πŸ•ΈοΈ: Not applicable for native apps.** diff --git a/example/src/App.tsx b/example/src/App.tsx index a70947e..42b5a22 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -22,6 +22,7 @@ const App: React.FC = () => { error: πŸ’₯, }} toastOptions={{}} + pauseWhenPageIsHidden /> diff --git a/src/constants.ts b/src/constants.ts index fdbb85b..008c02f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,6 +11,7 @@ export const toastDefaultValues: { dismissible: boolean; unstyled: boolean; invert: boolean; + pauseWhenPageIsHidden: boolean; } = { duration: 4000, position: 'top-center', @@ -22,4 +23,5 @@ export const toastDefaultValues: { dismissible: true, unstyled: false, invert: false, + pauseWhenPageIsHidden: false, }; diff --git a/src/toast.tsx b/src/toast.tsx index 23ffbe3..51e85c8 100644 --- a/src/toast.tsx +++ b/src/toast.tsx @@ -48,6 +48,7 @@ export const Toast: React.FC = ({ styles: stylesCtx, classNames: classNamesCtx, icons, + pauseWhenPageIsHidden, } = useToastContext(); const unstyled = unstyledProps ?? unstyledCtx; @@ -64,6 +65,10 @@ export const Toast: React.FC = ({ const isResolvingPromise = React.useRef(false); const onBackground = React.useCallback(() => { + if (!pauseWhenPageIsHidden) { + return; + } + if (timer.current) { timeLeftOnceBackgrounded.current = duration - (Date.now() - timerStart.current!); @@ -71,24 +76,29 @@ export const Toast: React.FC = ({ timer.current = undefined; timerStart.current = undefined; } - }, [duration]); + }, [duration, pauseWhenPageIsHidden]); const onForeground = React.useCallback(() => { - if (timeLeftOnceBackgrounded.current) { - if (timeLeftOnceBackgrounded.current > 0) { - timer.current = setTimeout( - () => { - if (!isDragging.current) { - onAutoClose?.(id); - } - }, - Math.min(timeLeftOnceBackgrounded.current, 1000) // minimum 1 second to avoid weird behavior - ); - } else { - onAutoClose?.(id); - } + if (!pauseWhenPageIsHidden) { + return; + } + + if ( + timeLeftOnceBackgrounded.current && + timeLeftOnceBackgrounded.current > 0 + ) { + timer.current = setTimeout( + () => { + if (!isDragging.current) { + onAutoClose?.(id); + } + }, + Math.max(timeLeftOnceBackgrounded.current, 1000) // minimum 1 second to avoid weird behavior + ); + } else { + onAutoClose?.(id); } - }, [id, onAutoClose]); + }, [id, onAutoClose, pauseWhenPageIsHidden]); useAppStateListener( React.useMemo( diff --git a/src/toaster.tsx b/src/toaster.tsx index 567ae7b..413b8ec 100644 --- a/src/toaster.tsx +++ b/src/toaster.tsx @@ -42,6 +42,7 @@ export const ToasterUI: React.FC = ({ invert, toastOptions, icons, + pauseWhenPageIsHidden, ...props }) => { const [toasts, setToasts] = React.useState([]); @@ -147,6 +148,8 @@ export const ToasterUI: React.FC = ({ styles: toastOptions?.styles ?? {}, classNames: toastOptions?.classNames ?? {}, icons: icons ?? {}, + pauseWhenPageIsHidden: + pauseWhenPageIsHidden ?? toastDefaultValues.pauseWhenPageIsHidden, }), [ duration, @@ -158,6 +161,7 @@ export const ToasterUI: React.FC = ({ invert, toastOptions, icons, + pauseWhenPageIsHidden, ] ); diff --git a/src/types.ts b/src/types.ts index abede2c..4409de3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -110,6 +110,7 @@ export type ToasterProps = StyleProps & { loading?: React.ReactNode; }; swipToDismissDirection?: ToastSwipeDirection; + pauseWhenPageIsHidden?: boolean; }; export type AddToastContextHandler = ( @@ -129,6 +130,7 @@ export type ToasterContextType = Required< | 'classNames' | 'icons' | 'offset' + | 'pauseWhenPageIsHidden' > > & { addToast: AddToastContextHandler;