Dialog
Preview appears after the next Storybook update.
<Dialog />When to use
Use it for
- A task of one to three fields that belongs to the current page and needs the user's full attention.
- Reviewing something before committing it, like release notes before Publish.
- Size sm for one field, md (default) for short forms, lg for reading or comparing content.
- Plain-script pages without React render it with dialogHtml() from @bridge-ds/react/dom and call bindDialogs() once: the same look, focus trap, Escape, scrim and focus return. Never a homemade modal or a restyled native dialog.
Not for
- Confirming a destructive action: use AlertDialog, which cannot be dismissed by clicking outside.
- Details the user wants to read next to the page, like a token's history: use Drawer.
- A hint or a small menu anchored to a control: use Popover or Menu.
- Long multi-step flows: give them a page. Stacked dialogs lose people.
Do and don't
Every example is rendered with the real component, so it always matches what ships.
Title says the task, the primary button repeats the verb
"Rename token" opens a dialog titled "Rename token" whose primary action is "Rename token". Users always know where they are.
Keep the footer for actions only
Alternatives first, primary last, aligned to the end. Explanations go in the description or the body.
A dialog for information the page could show inline
Interrupting to say "Saved" costs a click. Use a Toast or an inline Alert.
Vague footer labels
"OK" and "Yes" make users reread the title to know what they agree to.
Accessibility
- Base UI Dialog: role dialog, aria-modal, named by the title and described by the description.
- Focus moves into the dialog when it opens (the first focusable element, or initialFocus) and is trapped there.
- Escape, the close button and a click on the scrim close it; focus returns to the trigger.
- The page behind is inert and scroll is locked while the dialog is open.
- The body scrolls on its own when content is long, so the title and the actions stay visible.
- Motion is a 200ms fade and a slight rise; with reduced motion it appears instantly.
Content guidelines
- Title: the task as a verb phrase in sentence case, no period: "Invite reviewer".
- Description: one or two sentences on what happens next. Skip it if the title says enough.
- Primary button repeats the title's verb. Secondary is "Cancel".
- The close button label says what it closes: "Close dialog".
From the code Generated from the component, not editable here.
Anatomy and tokens
Read from packages/react/src/components/Dialog/Dialog.module.css at build time. Every value is a token: open one to see its alias chain in both themes.
- Scrim (dialog.scrim)
.backdrop - Positioning layer
.viewport - Surface (dialog.bg, dialog.radius, dialog.shadow)
.popup - Surface (dialog.bg, dialog.radius, dialog.shadow)
.popup[data-starting-style], .popup[data-ending-style] - Surface (dialog.bg, dialog.radius, dialog.shadow)
.popup[data-ending-style] - Size sm (384px)
.sm - Size md (560px, default)
.md - Size lg (720px)
.lg - Header
.header - heading
.heading - Title
.title - Description
.description - Close button
.close - withClose
.withClose - Scrolling body
.body - Footer with actions
.footer - Header
.header:last-child
Motion and interaction
Dialog animates on open and close. Try it in the preview at the top.
| When | What changes | Duration | Easing |
|---|---|---|---|
| Open | Fade and movement | motion.duration.moderate200 ms | motion.easing.enterstarts fast, lands softly |
| Close | Fade and movement | motion.duration.fast150 ms | motion.easing.exitstarts softly, leaves fast |
With reduced motion turned on, every change happens at once.
From the code Generated from the component, not editable here.
Props
Parsed from the TypeScript types in packages/react/src/components/Dialog/Dialog.tsx, so this table cannot drift from the code.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | none | Controlled open state. |
defaultOpen | boolean | none | Initial open state when uncontrolled. |
onOpenChange | (open: boolean) => void | none | Called when the dialog opens or closes (Escape, scrim click, close button, DialogClose). |
disablePointerDismissal | boolean | false | Keep the dialog open when the user clicks the scrim. Use for forms with unsaved input. |
children | ReactNode | none | DialogTrigger and DialogContent. |
Playground
Dialog has no typed options to play with: it is a container. Compose it with other components and any native attribute. Here it is in both themes.
Workbench
For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open Dialog in Storybook).
Embed Storybook stories here (4)
Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay empty.
Default
LongContent
Controlled
AllStates
From the code Generated from the component, not editable here.
Changelog
- New
The measure now writes the Figma sets drawn under a component's folder as their own entries, so Claude can fix them: popups drawn open (Dialog/Popup, AlertDialog/Popup, Drawer/Popup, Menu/Popup, Popover/Popup, Tooltip/Popup, and Select/Popup or Combobox/Popup, measured open when the stories show them closed) and sets that fix a prop (Pagination/Full, Pagination/Compact, Progress/Linear)
v1.0.0, Nov 11, 2026
- New
@bridge-ds/react/domgains the Dialog for pages without React at runtime:dialogHtml()renders the exact markup of<DialogContent>(same classes, same look), andbindDialogs(),openDialog(),closeDialog(),isDialogOpen()anddialogReturnValue()give it the React Dialog behavior: focus moves in and is trapped, the page behind is inert and does not scroll, Escape and the scrim close it, focus returns to the trigger,aria-modal,open,cancelandcloseevents, and a<form method="dialog">inside closes it with the submit button's valuev1.0.0, Nov 11, 2026
- New
Overlays: Dialog (sizes, scrolling body, footer, close last in focus order), AlertDialog (destructive confirmations, async confirm), Drawer (start, end, bottom with swipe), Popover, Tooltip with TooltipProvider, Menu (icons, shortcuts, groups, submenus, checkbox and radio items, danger items)
v1.0.0, Nov 11, 2026
- New
Add a product, v3: one dialog, and the product is in the team at once
v1.0.0, Nov 11, 2026
- New
Invite collaborators: a dialog from the team menu and Settings that takes several work emails, a role picker (Can view, Can edit, Reviewer as Designer or Developer, Admin) and lists who has access with Resend
v1.0.0, Nov 11, 2026
- New
Studio: "Create a new team" in the team chip menu now opens a dialog over the page instead of leaving for the launcher on Studio home, so you keep your place
v1.0.0, Nov 11, 2026
- Fix
Journey fixes: the site reads "Open Studio" for a GitHub sign-in too; "Welcome back" names the person, their team and role; Bring it in reads "brought in the latest product" in the activity; the invite dialog says Done once invites went out; Add a product links admins to give Bridge access and reads the list again on return; Settings > Members waits for the session instead of painting a stand-in list
v1.0.0, Nov 11, 2026
- Fix
The sample team shows Send to Figma to its visitor even without a Figma file, and its demo dialog says what each action does on a real team ("Send to Figma puts this screen in your team's Figma file...") before "Get started"
v1.0.0, Nov 11, 2026
- Fix
Home tour: a step no longer sits on top of an open dialog (Search, Add a product, Start an exploration, Account)
v1.0.0, Nov 11, 2026
- Fix
One face per email member everywhere: the account menu, the header, Members, the invite dialog, exploration cards and rows, the review page and an exploration's activity all draw the face of the member's name (
~name), never their email, a row index, the Bridge app's avatar or a GitHub account that happens to share their namev1.0.0, Nov 11, 2026
- Fix
Email designers explore with Claude: the Bridge connector signs them in with their Bridge account (no GitHub) and acts through the email contributors' proxy; on their own exploration branches in the design team's copy they may save prototype code (never CI, hosting settings or node_modules); the exploration page and the start dialog show them the Claude app only
v1.0.0, Nov 11, 2026
- Fix
Studio setup: "Invite your team" now invites people by email with a role (the Invite collaborators dialog) instead of sharing a link
v1.0.0, Nov 11, 2026
- Fix
Studio team chip, Recent teams: a team joins the list only after its page read the repository (public, read, write, admin or outside contributor), never because someone typed it in the launcher or the Create a new team dialog, and a team GitHub answers 404 for leaves it
v1.0.0, Nov 11, 2026