Content
- Title: a question naming the object. Body: what happens, and whether it can be undone.
- Button: the same verb as the title. Cancel is always "Cancel".
The one "Are you sure?" dialog, for actions worth a second look.
import { … } from "@brdgapp/ui/components/confirm-dialog"ConfirmDialog is Bridge's one "are you sure?" dialog, for actions worth a second look, such as stopping sharing or disconnecting an account. It asks a question, says what will happen, and offers Cancel and a confirm button that names the action. The usual mistake is the browser's window.confirm, or a confirm button that just says OK.
destructive when it removes something: red button and a warning icon.window.confirm.One of each
Bridge has one button, one label, one menu, one tooltip, one confirm dialog and one table. Before building a control, look for it here. Never hand-make a second version (a <button> with pill classes, a <span> chip, a new kebab), even if it looks the same today: copies drift.
Say what happens
Buttons start with a verb and name the object: "Stop sharing", not "OK" or "Submit". A confirm dialog asks a question about the specific thing and its button repeats the verb. Errors say what happened and what to do next.
Stop sharing with Leah Okonkwo?
Leah Okonkwo will no longer see your network.
Drawn in place and smaller. The real dialog opens over the page.
Backdrop. Dims and blurs the page.
Panel. Up to 384px wide, raised surface, 16px corners, the dialog shadow.
Warning icon. destructive only: a red triangle in a soft red circle.
Title. A question, 16px Bold.
Body. What happens, 13px.
Buttons. Cancel (secondary) and the confirm button (primary, or destructive), each half the width.
Confirm runs a pretend request: while it spins, the dialog can't be dismissed.
| Open | Busy | |
|---|---|---|
| Destructive | ||
| Not destructive |
| State | What happens |
|---|---|
| Open | Focus moves into the dialog; the page behind can't be reached. |
| Busy | The confirm button spins; Cancel, Esc and the backdrop do nothing until it finishes. |
| Closed | Focus returns to the button that opened it. |
onConfirm, then closes. While busy, nothing can dismiss it, so the person sees the outcome.Do
Ask about the specific thing: "Stop sharing with Leah Okonkwo?"Don't
Ask "Are you sure?"Do
Name the action on the button: "Stop sharing".Don't
Label it OK, Yes or Confirm.| Keys | Action |
|---|---|
| Tab | Moves between Cancel and confirm, and stays inside the dialog. |
| Esc | Cancels (unless busy). |
ConfirmDialog
The dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Whether it shows. |
onClose | () => void | — | Called on Cancel, Esc, or after confirming. |
title | string | — | The question. |
body | ReactNode | — | What happens. |
confirmLabel | string | — | The action. |
confirmIcon | ReactNode | — | An icon on the confirm button. |
destructive | boolean | false | Red button and warning icon. |
busy | boolean | false | Spinner; can't be dismissed. |
onConfirm | () => void | Promise<void> | — | Do the action. |
What it's built from and where it's used, read from the code. When you change it, check these too.
Where the code still differs from the system. Follow the system, not the gap.
div with no focus trap: keyboard users could tab behind it. Fixed by Base UI.StopSharingConfirmDialog duplicates this dialog with fixed copy. It should move to ConfirmDialog.components.md → ConfirmDialog, StopSharingButton; src/components/ui/confirm-dialog.tsx.