Modal
Centered overlay that blocks the interface until dismissed, focusing attention on key info or actions, ideal for confirmations, alerts, and quick approvals
Installation
Install the component via the CLI in one command.
npx shadcn@latest add @intentui/modal
Composed components
When you install this component via the CLI, it automatically loads all composed components, so you don’t need to add them individually.
Manual installation
Use this approach if you prefer to install and wire up the component yourself instead of using the CLI.
npm install react-aria-components
Anatomy
import { Button } from "@/components/ui/button"
import {
Modal,
ModalBody,
ModalClose,
ModalContent,
ModalDescription,
ModalFooter,
ModalHeader,
ModalTitle,
ModalTrigger,
} from "@/components/ui/modal"<Modal>
<ModalTrigger>Open Modal</ModalTrigger>
<ModalContent>
<ModalHeader>
<ModalTitle>Modal Title</ModalTitle>
<ModalDescription>Modal Description</ModalDescription>
</ModalHeader>
<ModalBody>Modal Body</ModalBody>
<ModalFooter>
<ModalClose>Close</ModalClose>
<Button>Confirm</Button>
</ModalFooter>
</ModalContent>
</Modal>Examples
Alert dialog
Alert dialogs are meant to interrupt the user with a critical message, so use 'em only when it's absolutely necessary. The fix? Set the role to alertdialog, and you're golden.
Notice how the modal is dismissible and the close button is hidden? That's 'cause the role is set to alertdialog.
<ModalOverlay isDismissable={false}/>Controlled
You can control the modal programmatically.
Sizes
The modal is set to lg by default. You can adjust it to any size from the available options.
Modal overlay styles
The overlay uses a subtle 1px blur by default. You can increase it or disable it entirely.
<Modal>
<Button intent="outline">Rename</Button>
<ModalContent overlay={{ className: "backdrop-blur-2xl" }}>If you want to turn it off, use backdrop-blur-none. If you do not need any blur at all, the recommended approach is to remove the blur class from the component defaults.
-"bg-bg/15 backdrop-blur-[1px] motion-reduce:backdrop-blur-0",
+"bg-bg/15",Or, you can override it per instance from the component usage:
<Modal>
<Button intent="outline">Rename</Button>
<ModalContent overlay={{ className: "backdrop-blur-none" }}>Sticky
You can use the ModalBody component to make the modal sticky.
Nested
You can also nest modals. Try open it and confirm!
Header
This setup’s super flexible. If you skip adding ModalTitle and just drop a string as its child, it'll auto-render as the title. Like this:
<ModalHeader>
Title
</ModalHeader>Wanna customize more? Throw in props like title and description for a tailored header:
<ModalHeader title='Title' description='Description' />Triggered by menu
You can also trigger the modal by clicking on a menu item.
It might be a good idea to extract the modal into a separate component for better organization.
interface ModalActionProps {
state: string | null
onOpenChange: () => void
actionType: { description: string; action: () => void; confirmText: string; title: string }
disabled: boolean
}
const ModalAction = (props: ModalActionProps) => (
<ModalContent isOpen={props.state !== null} onOpenChange={props.onOpenChange}>
<ModalHeader>
<ModalTitle>{props.actionType?.title}</ModalTitle>
<ModalDescription>{props.actionType?.description}</ModalDescription>
</ModalHeader>
<ModalFooter>
<ModalClose>Cancel</ModalClose>
<Button
intent={props.state === "ban" ? "danger" : "primary"}
className="min-w-24"
isDisabled={props.disabled}
onPress={props.actionType?.action}
>
{props.disabled ? <Loader variant="spin" /> : props.actionType?.confirmText}
</Button>
</ModalFooter>
</ModalContent>
)Then you can use it like this.
<ModalAction
state={state}
onOpenChange={closeModal}
actionType={actionType(state)}
disabled={loading}
/>With that, now we can modify the actionType function to return the initial state.
const actionType = (t: string | null) => {
const initialsState = {
title: '',
description: '',
confirmText: '',
action: () => {}
}
switch (t) {
case 'delete': ...
case 'ban': ...
case 'restore': ...
default:
return initialsState
}
}Component API
Modal
The Modal component controls the modal trigger and content.
ModalTrigger
The ModalTrigger component defines the element that opens a modal.
| Prop | Type | Default |
|---|---|---|
className | string | - |
ModalContent
The ModalContent component renders the modal panel.
| Prop | Type | Default |
|---|---|---|
className | string | - |
closeButton | boolean | true |
overlay | Pick<ModalOverlayProps, "className"> | - |
size | keyof typeof sizes | md |
ModalHeader
The ModalHeader component groups the modal title and description.
| Prop | Type | Default |
|---|---|---|
className | string | - |
description | string | - |
title | string | - |
ModalTitle
The ModalTitle component renders the modal heading.
| Prop | Type | Default |
|---|---|---|
className | string | - |
ModalDescription
The ModalDescription component renders supporting text inside a modal.
| Prop | Type | Default |
|---|---|---|
className | string | - |
ModalBody
The ModalBody component wraps the main modal content.
| Prop | Type | Default |
|---|---|---|
className | string | - |
ModalFooter
The ModalFooter component groups modal actions.
| Prop | Type | Default |
|---|---|---|
className | string | - |
ModalClose
The ModalClose component renders a button that closes the modal.
| Prop | Type | Default |
|---|---|---|
className | string | - |
intent | "primary" | "secondary" | "warning" | "danger" | "success" | "outline" | "plain" | plain |
See the React Aria for the full API reference.
Unlock the full power ofIntent UI Design
Build modern web apps faster with 1000+ resources across components, blocks, patterns, templates, and starter kits.