Dialogs
Dialogs provide important prompts in a user flow. They inform users about critical information, require decisions, or involve multiple tasks.
Dialogs focus user attention exclusively on one task or a piece of information via a modal overlay. Expressive dialogs use spring-based motion for entrance/exit animations and clear typography hierarchy.
Introduction
The MD3 Expressive Dialog is a versatile modal component that ranges from simple confirmation alerts to complex full-screen forms. It leverages Radix UI for robust accessibility and Framer Motion for premium, critically-damped spring animations that make the UI feel alive and responsive.
Anatomy
-
Scrim (Overlay): A semi-transparent background that dims the underlying UI.
-
Container: The panel holding the content. Uses rounded corners (28dp) to match the MD3 expressive language.
-
Icon (Optional): A visual indicator placed at the top for emphasis (e.g., Warning, Success).
-
Title: A clear, concise heading describing the purpose.
-
Description / Body: The main content area, which can be scrollable.
-
Footer / Actions: Buttons for the user to confirm or dismiss the prompt.
Variants
Basic Dialog
A standard modal for simple messages or confirmations.
Icon Dialog
Adds an icon at the top for additional context and visual weight.
Full-screen Dialog
Covers the entire viewport. Best for complex mobile-first tasks like creating a new record or extensive form filling.
Features
Scrollable Body
Use DialogBody to create a scrollable region while keeping the title and footer sticky.
Expressive Motion
Dialogs use a spring animation that feels "emphasized" and tactile, transitioning smoothly from a slightly scaled-down state to full size.
Usage
Basic Usage
import {
Dialog,
DialogTrigger,
DialogPortal,
DialogOverlay,
DialogContent,
DialogTitle,
DialogDescription,
DialogFooter,
Button
} from "@bug-on/m3-expressive";
export function Example() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogPortal>
<DialogOverlay />
<DialogContent>
<DialogTitle>Confirm Action</DialogTitle>
<DialogDescription>
Are you sure you want to proceed with this operation?
</DialogDescription>
<DialogFooter>
<Button colorStyle="text">Cancel</Button>
<Button>Confirm</Button>
</DialogFooter>
</DialogContent>
</DialogPortal>
</Dialog>
);
}
Best Practices
Do
- Use Dialogs for critical information that requires a decision.
- Keep the title concise and the description focused.
- Use Full-screen dialogs for complex tasks on mobile devices.
- Ensure the primary action is clear (e.g., using a high-emphasis button).
Don't
- Don't use a Dialog for information that is already visible on the main screen.
- Don't use too many Dialogs in a single user flow; it can be disruptive.
- Avoid long-running tasks inside a Dialog unless you provide a clear progress indicator.
Accessibility
- Keyboard:
Tabcycles focus inside the dialog.Esccloses the dialog. - Roles: Uses
role="dialog"orrole="alertdialog"depending on content. - Linking: Automatically links
DialogTitleandDialogDescriptionvia ARIA attributes. - Restoration: Focus is restored to the trigger element when the dialog closes.
API Reference
Dialog
Root component.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Open state change callback. |
DialogContent
The main container.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Renders as the child element. |
className | string | — | Custom classes. |
DialogFullScreenContent
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Required. Header title. |
actionLabel | string | — | Label for primary action. |
onAction | () => void | — | Primary action callback. |