View docs [here](https://radix-ui.com/primitives/docs/components/dialog).
@radix-ui/react-dialog is an unstyled, low-level React component library for building accessible modal and non-modal dialogs. With over 18 million weekly downloads, it's become a foundational primitive for design systems and applications that need robust dialog functionality without opinionated styling. The package handles the complex accessibility concerns of dialogs automatically, including focus trapping, keyboard navigation, screen reader announcements, and proper ARIA attributes.
The library is part of Radix UI's Primitives collection, which provides headless UI components that developers can style however they want. This approach separates behavior from presentation, giving you full control over appearance while ensuring the underlying functionality meets WCAG accessibility standards. The component automatically portals dialog content to document.body, preventing z-index and overflow issues common with inline modals.
Radix Dialog implements the WAI-ARIA Dialog pattern, managing focus states, escape key handling, and click-outside behavior. It supports both controlled and uncontrolled modes, allowing integration with form libraries and state management systems. The composable API breaks dialogs into granular parts (Root, Trigger, Overlay, Content, Title, Description, Close) that you wire together, making the behavior explicit and customizable.
Developers building component libraries, design systems, or applications needing accessible dialogs choose this package because it solves the hard accessibility and DOM management problems while leaving styling decisions entirely to the consumer. It's particularly popular among teams migrating away from heavyweight UI libraries who want more control over their component layer.
import * as Dialog from '@radix-ui/react-dialog';
import { useState } from 'react';
import './dialog-styles.css';
function UserProfileDialog() {
const [username, setUsername] = useState('');
const [open, setOpen] = useState(false);
const handleSave = () => {
console.log('Saving username:', username);
setOpen(false);
};
return (
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Trigger asChild>
<button className="trigger-button">
Edit Profile
</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="dialog-overlay" />
<Dialog.Content className="dialog-content">
<Dialog.Title className="dialog-title">
Edit Profile
</Dialog.Title>
<Dialog.Description className="dialog-description">
Make changes to your profile information.
</Dialog.Description>
<div className="form-field">
<label htmlFor="username">Username</label>
<input
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter username"
/>
</div>
<div className="dialog-actions">
<Dialog.Close asChild>
<button className="button-secondary">
Cancel
</button>
</Dialog.Close>
<button
className="button-primary"
onClick={handleSave}
>
Save Changes
</button>
</div>
<Dialog.Close asChild>
<button className="icon-button" aria-label="Close">
✕
</button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}Authentication flows: Create login, signup, or password reset modals that trap focus and prevent interaction with the underlying page until the user completes or cancels the authentication process.
Confirmation dialogs: Build delete confirmations, unsaved changes warnings, or destructive action prompts that require explicit user acknowledgment before proceeding with an operation.
Forms and data entry: Display complex forms in overlay dialogs for actions like creating new records, editing profiles, or filtering datasets without navigating away from the current page context.
Media viewers and galleries: Implement lightbox-style image or video viewers that overlay fullscreen content while maintaining keyboard navigation and proper focus management for accessibility.
Contextual information panels: Show detailed information, help documentation, or settings panels in non-modal dialogs that users can interact with while still accessing the main application interface.
npm install @radix-ui/react-dialogpnpm add @radix-ui/react-dialogbun add @radix-ui/react-dialog