Skip to content

feat(ui): add Mosaic AlertDialog - #9433

Open
maxyinger wants to merge 3 commits into
max/dialog-stack-motionfrom
max/mosaic-alert-dialog
Open

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

Conversation

@maxyinger

@maxyinger maxyinger commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

https://swingset-git-max-mosaic-alert-dialog.clerkstage.dev/components/alert-dialog

Description

  • Adds the Mosaic AlertDialog
    • extends mosaic Dialog with some baked in opinions
    • new AlertDialog.Actions api surface on top of Dialog
    • required title and description

Baked in behavior on dialog

prop value
role 'alertdialog'
closedBy 'closerequest'
size 'prompt'

Preview

Screenshot 2026-08-13 at 4 36 49 PM

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:

@changeset-bot

changeset-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 05ac5ec

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 11:11pm
swingset Ready Ready Preview Aug 13, 2026 11:11pm

Request Review

@github-actions github-actions Bot added the ui label Aug 13, 2026
maxyinger added a commit that referenced this pull request Aug 13, 2026
Scope `DialogPartNameContext` to the alert's popup, so a plain `Dialog`
nested inside one no longer inherits the name, and share `Dialog`'s
content resolver instead of copying it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@maxyinger
maxyinger force-pushed the max/mosaic-alert-dialog branch from 8adf099 to 1b32869 Compare August 13, 2026 19:58
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-08-13T23:16:46.248Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 0
🔴 Breaking changes 0
🟡 Non-breaking changes 0
🟢 Additions 0

No API Changes Detected

All packages have stable APIs with no detected changes.


Report generated by Break Check

Last ran on 05ac5ec.

@pkg-pr-new

pkg-pr-new Bot commented Aug 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9433

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9433

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9433

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9433

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9433

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9433

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9433

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9433

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9433

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9433

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9433

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9433

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9433

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9433

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9433

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9433

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9433

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9433

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9433

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9433

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9433

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9433

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9433

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9433

commit: 05ac5ec

maxyinger added a commit that referenced this pull request Aug 13, 2026
Scope `DialogPartNameContext` to the alert's popup, so a plain `Dialog`
nested inside one no longer inherits the name, and share `Dialog`'s
content resolver instead of copying it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@maxyinger
maxyinger force-pushed the max/mosaic-alert-dialog branch from 1b32869 to 2be6c73 Compare August 13, 2026 22:24
maxyinger and others added 3 commits August 13, 2026 17:08
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".
The designs give every `prompt` the same footer, alert dialogs included: one
full-width button, or two at even halves with a 0.75rem gap. Not a pair sized to
their labels against the inline end, which is what this shipped as.

So the media branch goes, and the row gets shorter rather than longer:
`grid-auto-columns: 1fr` unconditionally already means one button fills the row
and two split it, with nothing to switch on at 48rem and no edge case waiting for
a third. The phone layout was this all along — it is now simply the layout.
Scope `DialogPartNameContext` to the alert's popup, so a plain `Dialog`
nested inside one no longer inherits the name, and share `Dialog`'s
content resolver instead of copying it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment on lines +6 to +20
/**
* The response row. An alert dialog exists to be answered, so its buttons are anatomy rather
* than content — the one part `Dialog` deliberately does not ship, because a dialog's footer is
* whatever the consumer composes and an alert dialog's is always the same two choices.
*
* One layout at every width, because that is the convention for a `prompt` generally rather than
* a rule about alert dialogs: its buttons span the surface, one full width or two at even halves.
* A right-aligned pair sized to its labels was tried first and is what the designs do not do.
*
* A GRID rather than a flex row, and that is what makes both cases the same declaration. Filling
* the row needs `flex: 1` on each CHILD, which a parent cannot set — StyleX has no child
* selector, and reaching into the children would mean every call site remembering to pass
* something. `grid-auto-flow: column` with `grid-auto-columns: 1fr` puts it on the container
* instead: every button takes an equal share of the row, so one fills it and two split it, with
* no branch and nothing for a third to break.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fuggin opus.

All these styles are more comments than style. I kinda want to strip them out, but also maybe they're useful context for future agents editing 🤷

any thoughts?

* The row holding the answer. Render the cancel first — see `alert-dialog.styles.ts` for why that
* ordering is what focuses it on open.
*/
const Actions = React.forwardRef<HTMLDivElement, AlertDialogActionsProps>(function AlertDialogActions(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

almost wonder if this should just live in Dialog since we'll use in on other prompt sized dialogs for inputs that will have the same styled actions 🤔 . easy swap if so

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