Skip to content

Conversation

@michaldudak
Copy link
Member

@michaldudak michaldudak commented Jul 21, 2025

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 handle passed in. The same handle should be passed to the Popover.Root. The handle is created by the parameterless Popover.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 payload prop on the Trigger part. A payload of an active trigger is accessible as a parameter of the Root child render function:

<Popover.Trigger handle={p1} payload={1} />

<Popover.Root handle={p1}>
  ({ payload }) => (...)
</Popover.Root>

It is possible to make the Trigger's and Root's payload strongly typed by specifying a type parameter on the createHandle function.
Strong typing of the payload is only possible with detached triggers. Even though it's possible to define payload on internal triggers, it'll have to be cast to the right type manually.

//                              ⯆ add this...
const p1 = Popover.createHandle<number>();

// ...

<Popover.Trigger handle={p1} payload={1} />

<Popover.Root handle={p1}>
  // ⯆ ...so this has proper type
  ({ payload }) => (...)
</Popover.Root>

Controlled mode

The open prop still controls the open state of the component, and is now accompanied by the triggerId prop. 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, triggerId is not required.
The onOpenChange callback has a new parameter, triggerId, that can be used to update the controlled state. So while there are two state props, open and triggerId, they are both updated with the same onOpenChange callback.

⚠️ Breaking changes

  • openOnHover, delay, and closeDelay props 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 handle created by the createHandle method is a subclass of the Store. If handle is 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

@michaldudak michaldudak added component: popover Changes related to the popover component. proof of concept labels Jul 21, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jul 21, 2025

vite-css-base-ui-example

pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/react@2336
pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/utils@2336

commit: feb8909

@mui-bot
Copy link

mui-bot commented Jul 21, 2025

Bundle size report

Bundle Parsed size Gzip size
@base-ui-components/react 🔺+7.94KB(+2.54%) 🔺+2.39KB(+2.40%)

Details of bundle changes

Generated by 🚫 dangerJS against 246dd66

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 23, 2025
@netlify
Copy link

netlify bot commented Jul 23, 2025

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit feb8909
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/68e3f49787c4cb00081e2e7f
😎 Deploy Preview https://deploy-preview-2336--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 25, 2025
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 28, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Oct 2, 2025
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Oct 6, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Oct 6, 2025
@michaldudak michaldudak merged commit 9a3c6f0 into mui:master Oct 6, 2025
20 checks passed
@github-project-automation github-project-automation bot moved this from In progress to Recently completed in Base UI public roadmap Oct 6, 2025
@michaldudak michaldudak deleted the popover-detached-triggers branch October 6, 2025 17:05
@mnajdova mnajdova added this to the v1.0.0 milestone Oct 22, 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.

Projects

Status: Recently completed

Development

Successfully merging this pull request may close these issues.

5 participants