feat(toast): support multiple ToastProvider
Related Issue #5559 Related PR #5602 #5590
๐ Description
This PR adopts the multi toaster design from react-hot-toast and adds support for multiple ToastProvider. It might provide an alternative solution to the above issues and PRs.
โณ๏ธ Current behavior (updates)
All the ToastProvider instance shares the same ToastQueue. If there are multiple ToastProvider instances, call addToast once would cause all the ToastProvider instance to render the same toast, and hence create duplicate toasts.
๐ New behavior
Each ToastProvider instance has their own ToastQueue and an unique ID field toasterId (default to heroui) is used to distinguish each of them. addToast and closeToast API also receives this toasterId field to control the add and close behavior of the corresponding ToastProvider.
๐ฃ Is this a breaking change (Yes/No):
Only a bit change on params, so kind of a no.
๐ Additional Information
Please see the storybook Multi Toaster example for demo.
Summary by CodeRabbit
-
New Features
- Support multiple ToastProviders with unique IDs and independent toast queues; toasts can be targeted, closed, and cleared per provider via a toasterId prop.
-
Documentation
- Added a Storybook/demo showing two providers with separate queues and controls.
-
Tests
- Added a unit test verifying multiple ToastProvider instances operate independently and scope placement/content.
-
Chores
- Added a changeset for a patch release of the toast package.
๐ฆ Changeset detected
Latest commit: c6ab38f2c75c33c40aa922e6e836a75b25f371d6
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 2 packages
| Name | Type |
|---|---|
| @heroui/toast | Patch |
| @heroui/react | Patch |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
@ChaserZ98 is attempting to deploy a commit to the HeroUI Inc Team on Vercel.
A member of the Team first needs to authorize it.
Walkthrough
Adds support for multiple ToastProvider instances by introducing per-toaster queues keyed by toasterId, updating toast API signatures and ToastProvider to accept toasterId, and adding stories, tests, docs, and a changeset for the feature.
Changes
| Cohort / File(s) | Summary |
|---|---|
Toast provider & queue routingpackages/components/toast/src/toast-provider.tsx |
Replace single global queue with globalToastQueues keyed by toasterId. Update getToastQueue (overloads), addToast, closeToast, closeAll to accept/use toasterId. ToastProvider gains toasterId prop (defaults to defaultToasterId) and binds to per-id queue. |
Toast props surfacepackages/components/toast/src/use-toast.ts |
Add public toasterId?: string to ToastProps to target a specific ToastProvider. |
Stories / examplespackages/components/toast/stories/toast.stories.tsx, apps/docs/content/components/toast/multiple-ToastProvider.raw.jsx, apps/docs/content/components/toast/multiple-ToastProvider.ts, apps/docs/content/docs/components/toast.mdx, apps/docs/content/components/toast/index.ts |
Add a MultiToaster story and docs example demonstrating two ToastProvider instances with distinct toasterIds and buttons that call addToast({ toasterId, ... }). Export the example in docs content and include it in toastContent. |
Testspackages/components/toast/__tests__/toast.test.tsx |
Add unit test "should work with multiple ToastProvider" validating isolation and correct routing/placement for two providers keyed by toasterId. |
Release metadata.changeset/great-keys-admire.md |
Add changeset for @heroui/toast patch release describing support for multiple ToastProvider instances via unique IDs. |
Sequence Diagram(s)
sequenceDiagram
participant UI as Caller (e.g., Button)
participant API as addToast / closeToast / closeAll
participant Map as globalToastQueues
participant TP as ToastProvider (toasterId)
UI->>API: addToast({ toasterId, ... })
API->>Map: get/create queue for toasterId
Map-->>API: ToastQueue
API-->>TP: enqueue toast in matching ToastQueue
TP->>TP: render region for its toasterId
UI->>API: closeToast({ key, toasterId })
API->>Map: get queue for toasterId
API-->>TP: close toast by key
UI->>API: closeAll(toasterId)
API->>Map: get queue for toasterId
API-->>TP: close all visible toasts
Estimated code review effort
๐ฏ 3 (Moderate) | โฑ๏ธ ~20 minutes
Possibly related PRs
- heroui-inc/heroui#4919 โ Touches
ToastPropsinpackages/components/toast/src/use-toast.ts(also modifies the public toast API), which may overlap with thetoasterIdaddition.
Suggested labels
๐ Status: To Review
Suggested reviewers
- jrgarciadev
- wingkwong
- macci001
[!TIP]
๐ Remote MCP (Model Context Protocol) integration is now available!
Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.
โจ Finishing Touches
- [ ] ๐ Generate Docstrings
๐งช Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
๐ชง Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
-
I pushed a fix in commit <commit_id>, please review it. -
Open a follow-up GitHub issue for this discussion.
-
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. - PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:-
@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase. -
@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
-
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
CodeRabbit Commands (Invoked using PR/Issue comments)
Type @coderabbitai help to get the list of available commands.
Other keywords and placeholders
- Add
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
Status, Documentation and Community
- Visit our Status Page to check the current availability of CodeRabbit.
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
@heroui/accordion
npm i https://pkg.pr.new/@heroui/accordion@5606
@heroui/alert
npm i https://pkg.pr.new/@heroui/alert@5606
@heroui/autocomplete
npm i https://pkg.pr.new/@heroui/autocomplete@5606
@heroui/avatar
npm i https://pkg.pr.new/@heroui/avatar@5606
@heroui/badge
npm i https://pkg.pr.new/@heroui/badge@5606
@heroui/breadcrumbs
npm i https://pkg.pr.new/@heroui/breadcrumbs@5606
@heroui/button
npm i https://pkg.pr.new/@heroui/button@5606
@heroui/calendar
npm i https://pkg.pr.new/@heroui/calendar@5606
@heroui/card
npm i https://pkg.pr.new/@heroui/card@5606
@heroui/checkbox
npm i https://pkg.pr.new/@heroui/checkbox@5606
@heroui/chip
npm i https://pkg.pr.new/@heroui/chip@5606
@heroui/code
npm i https://pkg.pr.new/@heroui/code@5606
@heroui/date-input
npm i https://pkg.pr.new/@heroui/date-input@5606
@heroui/date-picker
npm i https://pkg.pr.new/@heroui/date-picker@5606
@heroui/divider
npm i https://pkg.pr.new/@heroui/divider@5606
@heroui/drawer
npm i https://pkg.pr.new/@heroui/drawer@5606
@heroui/dropdown
npm i https://pkg.pr.new/@heroui/dropdown@5606
@heroui/form
npm i https://pkg.pr.new/@heroui/form@5606
@heroui/image
npm i https://pkg.pr.new/@heroui/image@5606
@heroui/input
npm i https://pkg.pr.new/@heroui/input@5606
@heroui/input-otp
npm i https://pkg.pr.new/@heroui/input-otp@5606
@heroui/kbd
npm i https://pkg.pr.new/@heroui/kbd@5606
@heroui/link
npm i https://pkg.pr.new/@heroui/link@5606
@heroui/listbox
npm i https://pkg.pr.new/@heroui/listbox@5606
@heroui/menu
npm i https://pkg.pr.new/@heroui/menu@5606
@heroui/modal
npm i https://pkg.pr.new/@heroui/modal@5606
@heroui/navbar
npm i https://pkg.pr.new/@heroui/navbar@5606
@heroui/number-input
npm i https://pkg.pr.new/@heroui/number-input@5606
@heroui/pagination
npm i https://pkg.pr.new/@heroui/pagination@5606
@heroui/popover
npm i https://pkg.pr.new/@heroui/popover@5606
@heroui/progress
npm i https://pkg.pr.new/@heroui/progress@5606
@heroui/radio
npm i https://pkg.pr.new/@heroui/radio@5606
@heroui/ripple
npm i https://pkg.pr.new/@heroui/ripple@5606
@heroui/scroll-shadow
npm i https://pkg.pr.new/@heroui/scroll-shadow@5606
@heroui/select
npm i https://pkg.pr.new/@heroui/select@5606
@heroui/skeleton
npm i https://pkg.pr.new/@heroui/skeleton@5606
@heroui/slider
npm i https://pkg.pr.new/@heroui/slider@5606
@heroui/snippet
npm i https://pkg.pr.new/@heroui/snippet@5606
@heroui/spacer
npm i https://pkg.pr.new/@heroui/spacer@5606
@heroui/spinner
npm i https://pkg.pr.new/@heroui/spinner@5606
@heroui/switch
npm i https://pkg.pr.new/@heroui/switch@5606
@heroui/table
npm i https://pkg.pr.new/@heroui/table@5606
@heroui/tabs
npm i https://pkg.pr.new/@heroui/tabs@5606
@heroui/toast
npm i https://pkg.pr.new/@heroui/toast@5606
@heroui/tooltip
npm i https://pkg.pr.new/@heroui/tooltip@5606
@heroui/user
npm i https://pkg.pr.new/@heroui/user@5606
@heroui/react
npm i https://pkg.pr.new/@heroui/react@5606
@heroui/system
npm i https://pkg.pr.new/@heroui/system@5606
@heroui/system-rsc
npm i https://pkg.pr.new/@heroui/system-rsc@5606
@heroui/theme
npm i https://pkg.pr.new/@heroui/theme@5606
@heroui/use-aria-accordion
npm i https://pkg.pr.new/@heroui/use-aria-accordion@5606
@heroui/use-aria-accordion-item
npm i https://pkg.pr.new/@heroui/use-aria-accordion-item@5606
@heroui/use-aria-button
npm i https://pkg.pr.new/@heroui/use-aria-button@5606
@heroui/use-aria-link
npm i https://pkg.pr.new/@heroui/use-aria-link@5606
@heroui/use-aria-modal-overlay
npm i https://pkg.pr.new/@heroui/use-aria-modal-overlay@5606
@heroui/use-aria-multiselect
npm i https://pkg.pr.new/@heroui/use-aria-multiselect@5606
@heroui/use-aria-overlay
npm i https://pkg.pr.new/@heroui/use-aria-overlay@5606
@heroui/use-callback-ref
npm i https://pkg.pr.new/@heroui/use-callback-ref@5606
@heroui/use-clipboard
npm i https://pkg.pr.new/@heroui/use-clipboard@5606
@heroui/use-data-scroll-overflow
npm i https://pkg.pr.new/@heroui/use-data-scroll-overflow@5606
@heroui/use-disclosure
npm i https://pkg.pr.new/@heroui/use-disclosure@5606
@heroui/use-draggable
npm i https://pkg.pr.new/@heroui/use-draggable@5606
@heroui/use-form-reset
npm i https://pkg.pr.new/@heroui/use-form-reset@5606
@heroui/use-image
npm i https://pkg.pr.new/@heroui/use-image@5606
@heroui/use-infinite-scroll
npm i https://pkg.pr.new/@heroui/use-infinite-scroll@5606
@heroui/use-intersection-observer
npm i https://pkg.pr.new/@heroui/use-intersection-observer@5606
@heroui/use-is-mobile
npm i https://pkg.pr.new/@heroui/use-is-mobile@5606
@heroui/use-is-mounted
npm i https://pkg.pr.new/@heroui/use-is-mounted@5606
@heroui/use-measure
npm i https://pkg.pr.new/@heroui/use-measure@5606
@heroui/use-pagination
npm i https://pkg.pr.new/@heroui/use-pagination@5606
@heroui/use-real-shape
npm i https://pkg.pr.new/@heroui/use-real-shape@5606
@heroui/use-ref-state
npm i https://pkg.pr.new/@heroui/use-ref-state@5606
@heroui/use-resize
npm i https://pkg.pr.new/@heroui/use-resize@5606
@heroui/use-safe-layout-effect
npm i https://pkg.pr.new/@heroui/use-safe-layout-effect@5606
@heroui/use-scroll-position
npm i https://pkg.pr.new/@heroui/use-scroll-position@5606
@heroui/use-ssr
npm i https://pkg.pr.new/@heroui/use-ssr@5606
@heroui/use-theme
npm i https://pkg.pr.new/@heroui/use-theme@5606
@heroui/use-update-effect
npm i https://pkg.pr.new/@heroui/use-update-effect@5606
@heroui/use-viewport-size
npm i https://pkg.pr.new/@heroui/use-viewport-size@5606
@heroui/aria-utils
npm i https://pkg.pr.new/@heroui/aria-utils@5606
@heroui/dom-animation
npm i https://pkg.pr.new/@heroui/dom-animation@5606
@heroui/framer-utils
npm i https://pkg.pr.new/@heroui/framer-utils@5606
@heroui/react-rsc-utils
npm i https://pkg.pr.new/@heroui/react-rsc-utils@5606
@heroui/react-utils
npm i https://pkg.pr.new/@heroui/react-utils@5606
@heroui/shared-icons
npm i https://pkg.pr.new/@heroui/shared-icons@5606
@heroui/shared-utils
npm i https://pkg.pr.new/@heroui/shared-utils@5606
@heroui/stories-utils
npm i https://pkg.pr.new/@heroui/stories-utils@5606
@heroui/test-utils
npm i https://pkg.pr.new/@heroui/test-utils@5606
commit: c6ab38f
@ChaserZ98 can you help resolve the conflicts?
@wingkwong Can you take a look at my comment here? I have some problems understanding the new implementation. I doubt if I could resolve the conflict without an answer for them.
@wingkwong Can you take a look at my comment here? I have some problems understanding the new implementation. I doubt if I could resolve the conflict without an answer for them.
Sorry I missed. I replied in the comment. You may also ping me at discord (same userid ) for faster communication.