You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`defaultOpen`|`boolean`|`false`| Initial open state (uncontrolled) |
144
-
|`onOpenChange`|`(open: boolean, details: DialogOpenChangeDetails) => void`| — | Called when open state changes; `details` names the trigger behind it |
145
-
|`modal`|`boolean`|`true`| Traps focus and blocks page interaction |
146
-
|`closedBy`|`'any' \| 'closerequest' \| 'none'`|`'any'`| Which gestures dismiss the dialog |
147
-
|`handle`|`DialogHandle`| — | Connects detached triggers (see `Dialog.createHandle()`) |
148
-
|`triggerId`|`string \| null`| — | Controls which trigger the open is attributed to |
149
-
|`children`|`ReactNode \| ({ payload }) => ReactNode`| — | Content, or a render function of the active trigger's `payload`|
|`defaultOpen`|`boolean`|`false`| Initial open state (uncontrolled) |
144
+
|`onOpenChange`|`(open: boolean, details: DialogOpenChangeDetails) => void`| — | Called when open state changes; `details` names the trigger behind it |
145
+
|`modal`|`boolean`|`true`| Traps focus and blocks page interaction |
146
+
|`role`|`'dialog' \| 'alertdialog'`|`'dialog'`| The popup's ARIA role |
147
+
|`closedBy`|`'any' \| 'closerequest' \| 'none'`|`'any'`| Which gestures dismiss the dialog |
148
+
|`handle`|`DialogHandle`| — | Connects detached triggers (see `Dialog.createHandle()`) |
149
+
|`triggerId`|`string \| null`| — | Controls which trigger the open is attributed to |
150
+
|`children`|`ReactNode \| ({ payload }) => ReactNode`| — | Content, or a render function of the active trigger's `payload`|
150
151
151
152
#### `closedBy`
152
153
@@ -218,18 +219,34 @@ No additional props beyond standard HTML attributes and the `render` prop.
|`data-open` / `data-closed`| Trigger, Backdrop, Viewport, Popup | Open state |
220
221
|`data-nested`| Backdrop, Viewport, Popup | Opened from inside another floating element |
222
+
|`data-stacked`| Backdrop, Popup | Layered over an open dialog |
223
+
|`data-stack-base`| Popup | Has an open dialog layered over it |
221
224
222
-
`data-nested` is what a stacked overlay styles itself from — chiefly so backdrops don't composite
223
-
into an ever-darker scrim as the stack grows. It reflects any floating ancestor, not strictly a
224
-
dialog one: the `FloatingTree` a Menu or Popover establishes counts too.
225
+
`data-nested` reflects any floating ancestor: the `FloatingTree` a Menu or Popover establishes
226
+
counts too.
227
+
228
+
`data-stacked` and `data-stack-base` are narrower, and are what stacking styles should use. They
229
+
describe dialog-on-dialog specifically, in the two directions of the same relationship — the one
230
+
on top, and the one it covers. A dialog opened from a menu item is `data-nested` but not
231
+
`data-stacked`: it has a floating ancestor, yet it sits on the bare page and still owns its scrim.
232
+
233
+
Both can be set at once, and that is the ordinary case rather than an edge — in a panel → prompt →
234
+
alert stack, the middle dialog is stacked on one surface while another is stacked on it.
235
+
236
+
`data-stacked` exists chiefly so the stack shows one scrim: the dialog on top drops its own
237
+
backdrop instead of compositing a darker one per level. `data-stack-base` is for whatever the
238
+
surface underneath does to signal depth.
239
+
240
+
`data-stacked` holds for as long as the dialog underneath is on screen, exit transition included —
241
+
otherwise the one on top would paint a second scrim over the fading original.
225
242
226
243
The headless parts are unstyled. Target a part with your own className (or `render` prop) and combine it with the `data-*` state attributes above.
227
244
228
245
## Important Notes
229
246
230
247
-**`Dialog.Popup` should be a child of `Dialog.Viewport`** for centered, scroll-locked modal behavior. The viewport hosts the fixed overlay container; the popup alone does not handle positioning or scroll lock.
231
248
-**Title and Description are optional but recommended.** If omitted, `aria-labelledby` / `aria-describedby` are simply absent from the popup.
232
-
-**Nested dialogs are supported**, and covered by tests. The `FloatingTree` pattern handles it: `useDismiss` blocks both Escape and outside-press on a parent while any child is open, and `FloatingOverlay`'s scroll lock is refcounted, so the body stays locked until the last dialog closes.
249
+
-**Nested dialogs are supported**, and covered by tests. The `FloatingTree` pattern handles it: `useDismiss` blocks both Escape and outside-press on a parent while any child is open, and `FloatingOverlay`'s scroll lock is refcounted, so the body stays locked until the last dialog closes. Style the stack with `data-stacked` / `data-stack-base`, not `data-nested`.
233
250
-**No positioning middleware.** Dialogs are centered via CSS, not Floating UI positioning.
234
251
235
252
## Authoring rule for new primitives
@@ -238,5 +255,5 @@ Each styleable surface = one part. Layout infrastructure (overlay, scroll lock,
0 commit comments