Skip to content

feat(Modal): add nesting behaviors and fix third-party overlay dismissal#1896

Draft
stephenjwatkins wants to merge 7 commits into
mainfrom
third-party-nested
Draft

feat(Modal): add nesting behaviors and fix third-party overlay dismissal#1896
stephenjwatkins wants to merge 7 commits into
mainfrom
third-party-nested

Conversation

@stephenjwatkins

Copy link
Copy Markdown
Member

📝 Changes

Adds control over how nested modals stack, and fixes a dismissal bug for modals that host third-party overlays.

Nesting behaviors (feature). New optional childNestingBehavior and selfNestingBehavior props on Modal.Trigger and ModalContainer control how a modal stacks relative to the modal it's nested under. A connection resolves to one of:

  • stack (default) — both modals keep their own backdrops; matches today's behavior, so existing modals are unchanged.
  • stack-shared-backdrop — the nested modal suppresses its backdrop so only the lowest backdrop shows.
  • replace — the nested modal hides the modal beneath it so only the topmost is visible.

Configure from either end: childNestingBehavior is set on the parent and cascades down the tree; selfNestingBehavior is set on the child, is local (does not cascade), and overrides the parent's childNestingBehavior for that one connection — useful for surgically adjusting a single nested modal without touching its parent.

Third-party overlay dismissal (fix). Previously the modal box was tagged data-react-aria-top-layer, which made react-aria treat every click inside the modal as "not outside," so nested react-aria overlays (e.g. Select, Menu) wouldn't close on outside click. The box now uses data-live-announcer instead, which ariaHideOutside honors to keep the box visible under a surrounding modal without breaking outside-click dismissal. A new global shouldCloseOnInteractOutside also ensures clicking a nested modal never dismisses the one beneath it, while backdrop clicks and genuine third-party overlays (e.g. Stripe) still behave correctly.

Notes for reviewers

  • No breaking changes. The new props are optional and default to today's behavior. Removed context fields (hasOpenNestedModal/setHasOpenNestedModal) were internal-only and unused on main.

  • New nesting logic is isolated in a dedicated useModalNesting hook; the only shared-path change (shouldCloseOnInteractOutside) is behavior-preserving for existing single modals (verified: clicking a Select option or the modal body does not dismiss a standard modal; backdrop dismissal is unchanged).

  • Try the Modal → Nested story; the childNestingBehavior control switches between all three modes live.

    ✅ Checklist

    Easy UI has certain UX standards that must be met. In general, non-trivial changes should meet the following criteria:

    • Visuals match Design Specs in Figma
    • Stories accompany any component changes
    • Code is in accordance with our style guide
    • Design tokens are utilized
    • Unit tests accompany any component changes
    • TSDoc is written for any API surface area
    • Specs are up-to-date
    • Console is free from warnings
    • No accessibility violations are reported
    • Cross-browser check is performed (Chrome, Safari, Firefox)
    • Changeset is added

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant