Skip to content

[modal] feature: update to native <dialog> with showModal() - #154

Merged
marlonmarcello merged 15 commits into
mainfrom
copilot/update-dialog-element-showmodal
Oct 26, 2026
Merged

marlonmarcello merged 15 commits into
mainfrom
copilot/update-dialog-element-showmodal

Conversation

Copilot AI commented Mar 18, 2026 •

Copy link
Copy Markdown
Contributor

Description

The modal was using a <div role="dialog"> with a hand-rolled focus trap (sentinel elements + manual focus cycling). The native <dialog> element + showModal() handles focus trapping, top-layer stacking, and modal semantics natively — and is baseline-available in all modern browsers including Safari 15+.

Solution

  • Native <dialog>/showModal() replaces the manual focus trap; ModalInner and ModalBackdrop are removed.
  • Children render directly, centered in a dynamically sized viewport dialog. Native ::backdrop replaces the overlay, and backdrop clicks are handled internally.
  • Simplified close-button styling and hook transitions; dialogRef synchronizes native closing with state, URL hash, and focus restoration.

Additional Notes

Important

animate-presence animation support is not included in this refactor. Related examples and handling have been removed; follow-up work is tracked in #155.

@changeset-bot

changeset-bot Bot commented Mar 18, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5215b32

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@wethegit/react-modal Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Co-authored-by: marlonmarcello <1956448+marlonmarcello@users.noreply.github.com>
Copilot AI changed the title [WIP] Update to use dialog and showModal method [modal] feature: update to native <dialog> with showModal() Mar 18, 2026
Copilot AI requested a review from marlonmarcello March 18, 2026 00:36
@marlonmarcello
marlonmarcello requested a balanced review from Copilot October 23, 2026 16:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Native modality disrupts return-focus behavior, and incomplete browser-style resets change backdrop and text colors.

3 open issues
What changed in this PR

Migrates the modal component to native <dialog> and showModal(), replacing custom focus trapping with browser-managed modality.

Changes:

  • Opens the native dialog on mount and prevents native cancellation from bypassing React state.
  • Removes focus-trap helpers and positioning styles, and adds dialog style resets.
  • Updates accessibility documentation and lockfile version metadata.
File Description
src/​lib/​components/​modal/​modal.tsx Removes the positioning class wrapper.
src/​lib/​components/​modal/​modal.module.scss Deletes obsolete positioning styles.
src/​lib/​components/​modal-visually-hidden/​modal-visually-hidden.tsx Deletes the focus-cycling helper.
src/​lib/​components/​modal-visually-hidden/​modal-visually-hidden.module.scss Deletes hidden-helper styles.
src/​lib/​components/​modal-visually-hidden/​index.tsx Removes the helper export.
src/​lib/​components/​modal-inner/​modal-inner.tsx Implements native dialog opening and cancel handling.
src/​lib/​components/​modal-inner/​modal-inner.module.scss Adds native dialog style resets.
src/​lib/​components/​modal-focus-bounds/​modal-focus-bounds.tsx Deletes focus-boundary sentinels.
src/​lib/​components/​modal-focus-bounds/​modal-focus-bounds.module.scss Deletes sentinel styles.
src/​lib/​components/​modal-focus-bounds/​index.tsx Removes the sentinel export.
README.md Documents native focus trapping.
package-lock.json Updates root package version metadata to 3.2.0.

Review effort: Balanced

Comment thread src/lib/components/modal-inner/modal-inner.tsx Outdated
Comment thread src/lib/components/modal-inner/modal-inner.module.scss Outdated
Comment thread src/lib/components/modal-inner/modal-inner.module.scss Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Native closing can affect an unrelated dialog, and reopening during an exit transition can leave the retained dialog without native modality.

2 open issues
3 resolved since last review

Review effort: Balanced

Comment thread src/lib/components/modal-inner/modal-inner.tsx Outdated
Comment thread src/lib/hooks/use-modal.ts Outdated
Co-authored-by: marlonmarcello <1956448+marlonmarcello@users.noreply.github.com>
@marlonmarcello

Copy link
Copy Markdown
Member

@copilot update the description of this PR to include the updates we made since it was created. Also make an important note that animation with animate presence is currently not included in this refactor and also go ahead and remove the code and logic that handles that. we will address that in #155

Co-authored-by: marlonmarcello <1956448+marlonmarcello@users.noreply.github.com>

Copilot AI commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot update the description of this PR to include the updates we made since it was created. Also make an important note that animation with animate presence is currently not included in this refac...

Removed the animate-presence example, unused transition styles/dependency, and retained-dialog reopening logic in 23f2012. README now explicitly defers animation support to #155. Lint, TypeScript, build, browser checks, and CodeQL passed.

I couldn't edit the PR body with the available tools; GitHub browser access is blocked. Updated description summary:

  • Native <dialog>/showModal() replaces the manual focus trap; ModalInner and ModalBackdrop are removed.
  • Children render directly, centered in a dynamically sized viewport dialog. Native ::backdrop replaces the overlay, and backdrop clicks are handled internally.
  • Simplified close-button styling and hook transitions; dialogRef synchronizes native closing with state, URL hash, and focus restoration.
  • README and demos reflect the new API; a major changeset records the breaking changes.
  • Important: animate-presence animation support is not included in this refactor. Related examples and handling have been removed; follow-up work is tracked in [react-modal] feature: use @starting-style for entry animation #155.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Native cancellation, backdrop hit testing, and portal-target changes have unresolved correctness issues.

2 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Reopen replacement dialog when renderTo changes

src/​lib/​components/​modal/​modal.tsx:35

Changing renderTo while Modal remains mounted recreates the portal's dialog element, but the ref object stays the same, so this effect does not run again. The replacement dialog stays closed and hidden while isOpen and any URL hash still indicate an open modal. Include renderTo in the dependencies so the replacement dialog receives showModal().

2 resolved since last review

Review effort: Balanced

Comment thread src/lib/components/modal/modal.tsx Outdated
Comment thread src/lib/components/modal/modal.tsx Outdated
Comment thread src/lib/components/modal/modal.tsx

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Clicks inside nested portaled dialogs can incorrectly dismiss the parent modal.

1 open issue
2 resolved since last review

Review effort: Balanced

Comment thread src/lib/components/modal/modal.tsx Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Marlon U. Marcello <marlon.marcello@gmail.com>
@marlonmarcello
marlonmarcello merged commit 153a1a0 into main Oct 26, 2026
6 checks passed
@marlonmarcello
marlonmarcello deleted the copilot/update-dialog-element-showmodal branch October 26, 2026 20:32
@github-actions github-actions Bot mentioned this pull request Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants