From 2af7418f5a522d003f2d0788e107201179e51c00 Mon Sep 17 00:00:00 2001 From: dana-y Date: Thu, 16 Oct 2025 00:20:14 +0900 Subject: [PATCH 1/5] feat: add globalLimit option to control the maximum number of toasts displayed --- src/components/Toasts.tsx | 4 +++- src/core/store.ts | 6 +++++- src/core/types.ts | 2 ++ website/docs/components/toasts.md | 7 +++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/Toasts.tsx b/src/components/Toasts.tsx index d9f4fd2..845e2ae 100644 --- a/src/components/Toasts.tsx +++ b/src/components/Toasts.tsx @@ -38,6 +38,7 @@ type Props = { }; globalAnimationType?: ToastAnimationType; globalAnimationConfig?: ToastAnimationConfig; + globalLimit?: number; fixAndroidInsets?: boolean; }; @@ -52,9 +53,10 @@ export const Toasts: FunctionComponent = ({ defaultStyle, globalAnimationType, globalAnimationConfig, + globalLimit, fixAndroidInsets = true, }) => { - const { toasts, handlers } = useToaster({ providerKey }); + const { toasts, handlers } = useToaster({ providerKey, limit: globalLimit }); const { startPause, endPause } = handlers; const insets = useSafeAreaInsets(); const safeAreaFrame = useSafeAreaFrame(); diff --git a/src/core/store.ts b/src/core/store.ts index d31022a..efa6f5c 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -81,7 +81,7 @@ export const reducer = (state: State, action: Action): State => { case ActionType.ADD_TOAST: return { ...state, - toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), + toasts: [action.toast, ...state.toasts], }; case ActionType.UPDATE_TOAST: @@ -181,6 +181,7 @@ const defaultTimeouts: { export const useStore = (toastOptions: DefaultToastOptions = {}): State => { const [state, setState] = useState(memoryState); + useEffect(() => { listeners.push(setState); return () => { @@ -191,6 +192,8 @@ export const useStore = (toastOptions: DefaultToastOptions = {}): State => { }; }, [state]); + const limit = toastOptions.limit ?? TOAST_LIMIT; + const mergedToasts = state.toasts .filter( (t) => @@ -198,6 +201,7 @@ export const useStore = (toastOptions: DefaultToastOptions = {}): State => { t.providerKey === toastOptions?.providerKey || t.providerKey === 'PERSISTS' ) + .slice(0, limit) .map((t) => ({ ...toastOptions, ...toastOptions[t.type], diff --git a/src/core/types.ts b/src/core/types.ts index 2f05832..2250108 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -62,6 +62,7 @@ export interface Toast { height?: number; width?: number; maxWidth?: number; + limit?: number; onPress?: (toast: Toast) => void; onHide?: (toast: Toast, reason: DismissReason) => void; onShow?: (toast: Toast) => void; @@ -90,6 +91,7 @@ export type ToastOptions = Partial< | 'styles' | 'height' | 'width' + | 'limit' | 'customToast' | 'disableShadow' | 'providerKey' diff --git a/website/docs/components/toasts.md b/website/docs/components/toasts.md index 5f9dd18..7b1bb09 100644 --- a/website/docs/components/toasts.md +++ b/website/docs/components/toasts.md @@ -28,6 +28,13 @@ Set the global animation config for all toasts. This can be overridden by the to ``` +### globalLimit +`number | undefined` + +Set the global limit for the number of toasts that can be shown at once. When this limit is reached, the oldest toast will be removed to make room for the new one. + + + ### overrideDarkMode `boolean | undefined` From 63c7aca2ceff0aac90285b8505b79581b8c0e4b3 Mon Sep 17 00:00:00 2001 From: Nick DeBaise Date: Mon, 20 Oct 2025 21:39:43 -0400 Subject: [PATCH 2/5] Use optional chaining for toastOptions.limit --- src/core/store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/store.ts b/src/core/store.ts index 873a183..e849185 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -198,7 +198,7 @@ export const useStore = (toastOptions: DefaultToastOptions = {}): State => { }; }, [state]); - const limit = toastOptions.limit ?? TOAST_LIMIT; + const limit = toastOptions?.limit ?? TOAST_LIMIT; const mergedToasts = state.toasts .filter( From 152676e85efccbefe785bcbaf2026fb5d8e943c2 Mon Sep 17 00:00:00 2001 From: Nick DeBaise Date: Mon, 20 Oct 2025 21:45:02 -0400 Subject: [PATCH 3/5] fix: fix up merge conflict. Note-to-self: Do not use Github web UI for merginggit add --- src/components/Toasts.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/Toasts.tsx b/src/components/Toasts.tsx index 2a6a3d3..8aa5409 100644 --- a/src/components/Toasts.tsx +++ b/src/components/Toasts.tsx @@ -56,12 +56,9 @@ export const Toasts: FunctionComponent = ({ defaultStyle, globalAnimationType, globalAnimationConfig, - globalLimit, - fixAndroidInsets = true, -}) => { - const { toasts, handlers } = useToaster({ providerKey, limit: globalLimit }); defaultPosition, defaultDuration, + globalLimit, fixAndroidInsets = true, }) => { const { toasts, handlers } = useToaster({ @@ -69,6 +66,7 @@ export const Toasts: FunctionComponent = ({ duration: defaultDuration, position: defaultPosition, animationType: globalAnimationType, + limit: globalLimit, }); const { startPause, endPause } = handlers; const insets = useSafeAreaInsets(); From aba907fea84676d8a74615eb4de5f50c4b5cddab Mon Sep 17 00:00:00 2001 From: dana-y Date: Wed, 22 Oct 2025 18:08:55 +0900 Subject: [PATCH 4/5] feat: add unit test for toast limit functionality based on globalLimit prop --- __tests__/src/components/Toasts.test.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/__tests__/src/components/Toasts.test.tsx b/__tests__/src/components/Toasts.test.tsx index c14fc8a..920dda6 100644 --- a/__tests__/src/components/Toasts.test.tsx +++ b/__tests__/src/components/Toasts.test.tsx @@ -135,4 +135,18 @@ describe('', () => { const toastElement = getByText('Top Toast'); expect(toastElement).toBeTruthy(); }); + + it('applies toast limit from globalLimit prop', () => { + const { getByText, queryByText } = render(); + + act(() => { + toast('Toast 1', { id: '1' }); + toast('Toast 2', { id: '2' }); + toast('Toast 3', { id: '3' }); + }); + + expect(getByText('Toast 2')).toBeTruthy(); + expect(getByText('Toast 3')).toBeTruthy(); + expect(queryByText('Toast 1')).toBeNull(); + }); }); From e7071d37e8f2bf030ad1d18fae25dd0e9d637637 Mon Sep 17 00:00:00 2001 From: dana-y Date: Wed, 22 Oct 2025 18:09:18 +0900 Subject: [PATCH 5/5] fix: update toast dismissal method in tests from dismiss() to remove() for consistency --- __tests__/src/components/Toasts.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/src/components/Toasts.test.tsx b/__tests__/src/components/Toasts.test.tsx index 920dda6..6be92fb 100644 --- a/__tests__/src/components/Toasts.test.tsx +++ b/__tests__/src/components/Toasts.test.tsx @@ -32,7 +32,7 @@ describe('', () => { afterEach(() => { jest.clearAllMocks(); act(() => { - toast.dismiss(); + toast.remove(); }); });