Skip to content

[drawer] Prevent dialogs from affecting nested drawer stack#4493

Merged
atomiks merged 8 commits intomui:masterfrom
atomiks:codex/drawer-dialog-nesting-fix
Apr 7, 2026
Merged

[drawer] Prevent dialogs from affecting nested drawer stack#4493
atomiks merged 8 commits intomui:masterfrom
atomiks:codex/drawer-dialog-nesting-fix

Conversation

@atomiks
Copy link
Copy Markdown
Contributor

@atomiks atomiks commented Mar 31, 2026

Fixes #4492

This keeps drawer-specific nesting visuals tied to nested drawers instead of generic nested dialogs. A dialog opened inside a nested drawer no longer increments --nested-drawers or retriggers the parent drawer stack animation.

Changes

  • Track nested drawer count separately from dialog nesting state in the drawer context.
  • Use the drawer-only count for drawer popup and viewport nested-stack behavior.
  • Add a regression test for the Drawer -> Drawer -> Dialog case.

@atomiks atomiks added type: bug It doesn't behave as expected. component: drawer Changes related to the drawer component. labels Mar 31, 2026 — with ChatGPT Codex Connector
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 31, 2026

commit: 78f4402

@mui-bot
Copy link
Copy Markdown

mui-bot commented Mar 31, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+335B(+0.07%) 🔺+104B(+0.07%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 31, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 78f4402
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/69d4efb826692e0009bc0980
😎 Deploy Preview https://deploy-preview-4493--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.

@atomiks atomiks marked this pull request as ready for review March 31, 2026 11:26
@atomiks atomiks force-pushed the codex/drawer-dialog-nesting-fix branch 4 times, most recently from 3789b18 to 3c7032c Compare April 2, 2026 06:25
@atomiks atomiks force-pushed the codex/drawer-dialog-nesting-fix branch from ef5b101 to 3e7a3fb Compare April 2, 2026 12:00
atomiks

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor Author

atomiks commented Apr 3, 2026

Codex Review (GPT-5.4)

This is a focused bug-fix PR that separates drawer-specific nesting visuals from generic dialog nesting while preserving the broader dialog stack semantics. I reviewed the full branch against a freshly fetched master base, including the follow-up test hardening, and did not find any actionable issues in the current five-commit branch.

1. Bugs / Issues (None)

I did not find any branch-relevant bugs or regressions in the final diff.

2. Root Cause & Patch Assessment

nestedOpenDrawerCount is now tracked separately from nestedOpenDialogCount, which fixes the reported Drawer -> Drawer -> Dialog and Drawer -> Drawer -> AlertDialog cases without conflating drawer visuals with generic dialog nesting.

Drawer.Root opts into drawer semantics via DialogRootTypeContext, while Dialog.Root and AlertDialog.Root reset descendants back to regular dialog semantics so the drawer-only flag does not leak past the drawer boundary.

The follow-up test change now checks the fixed-height handoff directly instead of relying on browser transition events, which makes the regression coverage more stable without weakening what it proves.

3. Pattern Consistency Assessment

The implementation stays localized to the existing shared dialog store flow instead of introducing drawer-only parallel plumbing. Generic dialog topmost behavior still follows the full dialog nesting count, while drawer popup and viewport visuals consume the new drawer-only count where that distinction actually matters.

6. Test Coverage Assessment

I ran:

  • pnpm test:jsdom DrawerPopup --no-watch
  • pnpm test:chromium DrawerPopup --no-watch

Both passed on the final branch head. The regression suite now covers nested Dialog and AlertDialog semantics, immediate nested-state clearing on close, close-during-ending behavior, fixed-height retention during close, and reopen ordering.

Recommendation

Approve ✅

The fix addresses the right root cause, keeps the blast radius contained, and the final regression suite now exercises the semantics and close-handoff paths in a way that is both meaningful and locally stable.


Claude Review (Opus 4.6)

Summary: The PR separates drawer-specific nesting count from generic dialog nesting count, so that a Dialog or AlertDialog opened inside a nested drawer doesn't increment --nested-drawers or retrigger parent drawer stack animations.

Approach

The fix introduces a DialogRootTypeContext (boolean, default false) to tag whether the current DialogRoot is acting as a drawer:

  • DrawerRoot wraps its Dialog.Root with <DialogRootTypeContext.Provider value> (i.e. true)
  • DialogRoot and AlertDialogRoot wrap children with <DialogRootTypeContext.Provider value={false}>, resetting the flag for descendants

useDialogRoot now tracks ownNestedOpenDrawers alongside ownNestedOpenDialogs. When notifying a parent, the child passes both counts: (ownNestedOpenDialogs + 1, ownNestedOpenDrawers + (isDrawer ? 1 : 0)). DrawerPopup and DrawerViewport then read nestedOpenDrawerCount instead of nestedOpenDialogCount for drawer-specific visuals.

Correctness

I traced through the nesting propagation for several scenarios:

Scenario nestedOpenDrawerCount at A Correct?
Drawer A → Drawer B → Dialog C opens 1 (only B) Yes
Drawer A → Drawer B → Drawer D opens 2 (B + D) Yes
Drawer A → Drawer B → AlertDialog E opens 1 (only B) Yes

The counting logic correctly propagates up the tree. Each layer adds 1 to dialogCount for itself and conditionally adds 1 to drawerCount only if isDrawer is true.

Issues Found

None blocking. Two minor observations:

  1. DialogRootTypeContext naming — The name stores a boolean that means "is this a drawer?", which is somewhat indirect. A name like IsDrawerContext would be more self-documenting. Low priority given it's internal-only.

  2. AlertDialogRoot change to optional parent lookup — AlertDialogRoot.tsx: useDialogRootContext() → useDialogRootContext(true). This silences the throw from the existing hook when AlertDialogRoot isn't nested inside a dialog. This is a correct alignment with DialogRoot's existing behavior, but worth being intentional about — it subtly changes AlertDialogRoot from "must be nested" to "may be nested" at the hook level (the component already allowed top-level usage, so this was arguably a latent bug).

Pattern Consistency

  • The approach stays within the existing shared dialog store flow rather than introducing drawer-specific parallel plumbing.
  • Generic dialog isTopmost behavior still follows the full nestedOpenDialogCount; only drawer popup/viewport visuals use the new drawer-only count.
  • The DrawerRootContext.ts diff is just a JSDoc field reorder — no functional change.

Test Coverage

Tests are comprehensive and well-structured:

  • Dialog and AlertDialog inside nested drawers don't inflate --nested-drawers
  • Parent nested state clears immediately on close
  • Close-during-animation behavior (properly gated with it.skipIf(isJSDOM))
  • Fixed height retention during close
  • Reopen ordering restores height before nested state

Bundle Impact

+116B gzipped (+0.08%) — negligible.

Verdict

Approve — clean, minimal fix that correctly addresses the root cause with appropriate test coverage.

@atomiks atomiks merged commit d15ca63 into mui:master Apr 7, 2026
23 checks passed
@atomiks atomiks deleted the codex/drawer-dialog-nesting-fix branch April 7, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: drawer Changes related to the drawer component. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[drawer] Dialog inside a drawer is registered as a nested drawer

2 participants