[Popover] Outside press / iframe: non-modal Popover stays open when interacting inside a same-origin iframe
- Dominant language
- TypeScript
- Stars
- 10.9k
- Forks
- 543
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 101
Description
# Bug report
## Current behavior
A **Popover** opened in the parent document stays open when the user presses inside a **same-origin iframe**.
Pressing parent chrome outside the iframe dismisses correctly.
**Correction after re-checking:** `Menu` and `Select` do **not** show this problem in the same setup — they close when focus moves into the iframe (`FloatingFocusManager` focus-out). The failure is specific to **Popover** (default `modal={false}`), which uses:
```js
outsidePressEvent: {
mouse: modal === 'trap-focus' ? 'sloppy' : 'intentional',
touch: 'sloppy',
}
```
So mouse dismiss is **`intentional`** (waits for `click`), not **`sloppy`** (`pointerdown`). Parent `document` never receives iframe presses, so the intentional outside-click path never runs. Focus-out alone also does not close the Popover in this cross-document case (unlike Menu/Select in practice).
Related but different: #629 covered components *rendered inside* a non-main document. This issue is: Popover in the main document, interaction inside a sibling iframe.
## Expected behavior
Pressing inside a related same-origin iframe should dismiss an open parent-document Popover (e.g. as `REASONS.outsidePress` or a documented equivalent), consistent with Menu/Select closing when the user moves into the iframe.
Possible directions:
1. Treat same-origin iframe interaction as outside press for Popover’s intentional mode (listen in `iframe.contentDocument` / bridge to `frameElement`), or
2. Align Popover focus-out dismiss with Menu/Select when focus moves to an iframe, or
3. Expose `additionalDocuments` / similar on `useDismiss` so hosts can opt in
## Reproducible example
```tsx
function App() {
return (
<>
Open
Shell popover
</>
);
}
```
Steps:
1. Open the popover.
2. Click inside the iframe.
3. Observe: popover stays open.
4. Compare with `Menu` / `Select` in the same layout — those close.
5. Click parent chrome outside the iframe — popover closes.
## Base UI version
v1.6.0 (`@base-ui/react`)
## Which browser are you using?
Chrome
## Which OS are you using?
macOS
## Additional context
Host workaround that unblocks Popover (intentional needs `click`; `pointerdown` alone is not enough):
```ts
frameDocument.addEventListener('pointerdown', (e) => {
const host = frameDocument.defaultView?.frameElement;
if (!(host instanceof Element)) return;
host.dispatchEvent(
new PointerEvent('pointerdown', {
bubbles: true,
cancelable: true,
composed: true,
pointerId: e.pointerId,
pointerType: e.pointerType || 'mouse',
button: e.button,
buttons: e.buttons,
clientX: e.clientX,
clientY: e.clientY,
}),
);
host.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
composed: true,
button: e.button,
buttons: e.buttons,
clientX: e.clientX,
clientY: e.clientY,
view: window,
}),
);
}, true);
```
Happy to add a StackBlitz if useful.
**Search keywords**: Popover, useDismiss, outsidePress, intentional, iframe
Contributor guide
Research direction
Start at Popover’s useDismiss configuration and compare its iframe and focus behavior with Menu and Select’s FloatingFocusManager handling. Reproduce the provided same-origin iframe example, then verify that interaction inside the iframe dismisses the Popover while parent-document outside-press behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100