Skip to content

feat(ui): add Mosaic AlertDialog - #9433

Open
maxyinger wants to merge 1 commit into
max/dialog-stack-motionfrom
max/mosaic-alert-dialog
Open

feat(ui): add Mosaic AlertDialog#9433
maxyinger wants to merge 1 commit into
max/dialog-stack-motionfrom
max/mosaic-alert-dialog

Conversation

@maxyinger

Copy link
Copy Markdown
Collaborator

Description

Adds the Mosaic AlertDialog — a Dialog that interrupts to ask for a decision and waits for one. Third of the stacking / close-confirmation stack, based on #9432 (which is based on #9427). Review that one first; the diff here is only the new component.

Base UI's shape: the parts are Dialog's parts minus dismissibility. The three props that would let it stop being an alert dialog are removed from the type rather than defaulted — role is alertdialog, closedBy is closerequest (an outside press can't answer a question; Escape still can), and size is prompt. Every part except Popup and Actions is Dialog's own component rather than a wrapper around it, so there's one implementation of each and no way for the two to drift.

There's no Cancel / Action part, matching Base UI: the cancel is AlertDialog.Close and the action is a plain Button. That also removed the need for initialFocus — the cancel is the first child of the actions row, so it's the first tabbable element and the alert opens focused on it. No CloseButton either, for the same reason an outside press doesn't dismiss: a corner X is a way out without answering.

AlertDialog.Actions is the one addition, since Base UI leaves that div to the consumer's CSS. It's a grid rather than a flex row, which puts the phone layout on the container instead of on every button: grid-auto-columns is 1fr below 48rem, where a prompt is a full-width sheet and the buttons split the row evenly, and auto above it, where the tracks size to their labels and sit at the inline end. StyleX has no child selector, so flex: 1 per button wasn't reachable from the parent.

A Title and a Description are both required and both warn in development when missing — an alert dialog's description is announced with its name at the moment it interrupts, so without one the choice reads as "Cancel" or "Delete" with nothing saying what is being deleted. Two supporting fixes came out of that: the existing accessible-name warning skipped any role but dialog, which would have made it silently inert for every alert dialog, and it now names the component it's complaining about instead of always saying Dialog.

The wrapper accepts finalFocus (and initialFocus), which an alert needs more than a dialog does: it's usually raised by something that happened rather than by a trigger, so there's nothing for focus to return to. The swingset DiscardChanges story passes the field's ref, so answering "keep editing" puts the caret back where the work was.

No call sites migrate here. destructive.tsx and the org-profile edit view adopt this in PR 5, after the close-confirmation APIs land in PR 4.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

A Dialog that interrupts to ask for a decision and waits for one. Base UI's
shape: the same parts as Dialog, with the three props that would let it stop
being an alert dialog removed rather than defaulted — `role` is `alertdialog`,
`closedBy` is `closerequest`, `size` is `prompt`. Everything else is Dialog's
own component rather than a wrapper around it, so there is one implementation
of each and no way for the two to drift.

No `CloseButton` part, for the same reason an outside press cannot dismiss it:
a corner X is a way out without answering.

`AlertDialog.Actions` is the one addition — the response row, which is anatomy
here in a way a dialog's footer is not. A grid rather than a flex row, because
the phone layout is a property on the container instead of something every
button has to be told: `grid-auto-columns` is `1fr` under the sheet band, so
the buttons split the row and span it, and `auto` above it, where the tracks
size to their labels and sit at the inline end. Full-width beats a right-aligned
pair floating against one edge of a screen-wide sheet.

The cancel goes first, which makes it the first tabbable element and therefore
what the alert opens focused on — the least destructive choice, with no
`initialFocus` plumbing, and with the keyboard order agreeing with the screen.

Title and Description are both required, and both warn in development when
missing: an alert dialog's description is announced with its name at the moment
it interrupts, so without one the user is choosing between "Cancel" and "Delete"
with nothing saying what is being deleted. The existing name warning skipped any
role but `dialog`, which would have made it silently inert here, and it now
names the component it is complaining about instead of always saying "Dialog".
@changeset-bot

changeset-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d768246

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

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

@vercel

vercel Bot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview Aug 13, 2026 3:58am
swingset Error Error Aug 13, 2026 3:58am

Request Review

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant