-
-
Notifications
You must be signed in to change notification settings - Fork 265
[popover] Support detached triggers and multiple triggers per popover #2336
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
Merged
michaldudak
merged 171 commits into
mui:master
from
michaldudak:popover-detached-triggers
Oct 6, 2025
Merged
[popover] Support detached triggers and multiple triggers per popover #2336
michaldudak
merged 171 commits into
mui:master
from
michaldudak:popover-detached-triggers
Oct 6, 2025
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit: |
Bundle size report
|
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
romgrk
reviewed
Jul 23, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
breaking change
Introduces changes that are not backward compatible.
component: popover
Changes related to the popover component.
type: enhancement
It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Made it possible to render Popover triggers outside of Popover.Root and having multiple triggers controlling the same Popover.
Detached triggers
When a trigger is placed outside of the root, it must have a
handlepassed in. The samehandleshould be passed to the Popover.Root. The handle is created by the parameterlessPopover.createHandle()function.Payloads
As a popover may have multiple triggers (internal or external), it's useful to determine which of them caused the popover to open. This is done with the
payloadprop on the Trigger part. A payload of an active trigger is accessible as a parameter of the Root child render function:It is possible to make the Trigger's and Root's payload strongly typed by specifying a type parameter on the
createHandlefunction.Strong typing of the payload is only possible with detached triggers. Even though it's possible to define
payloadon internal triggers, it'll have to be cast to the right type manually.Controlled mode
The
openprop still controls the open state of the component, and is now accompanied by thetriggerIdprop. This pair of props controls whether the popup is open and what the active trigger is. If there's only one trigger associated with the popover,triggerIdis not required.The
onOpenChangecallback has a new parameter,triggerId, that can be used to update the controlled state. So while there are two state props,openandtriggerId, they are both updated with the sameonOpenChangecallback.openOnHover,delay, andcloseDelayprops were moved from Popover.Root to Popover.Trigger, as they can be different per trigger.Technical notes
The main change that enabled detached triggers was migration to the Store for state management. The
handlecreated by thecreateHandlemethod is a subclass of the Store. Ifhandleis not present, the Root creates a new Store instance.All the shared state was moved from context to the Store, and the Store itself is shared via the context now.
Preview
https://deploy-preview-2336--base-ui.netlify.app/react/components/popover#detached-triggers
https://deploy-preview-2336--base-ui.netlify.app/experiments/popover/popovers