A modal dialog that interrupts the user with important content and expects a response.
Installation
Install the packages
Add the shadcn/ui component
Animate it
The CLI finds your shadcn/ui components through components.json, swaps their primitive imports for Animate UI's and removes the CSS animation classes Motion replaces.
Usage
React Aria builds an alert dialog from a Dialog with role="alertdialog" inside a Modal. Import from Animate UI instead of react-aria-components: it re-exports all of React Aria, with animated Modal and ModalOverlay.
import {
Button,
Dialog,
DialogTrigger,
Heading,
Modal,
ModalOverlay,
} from '@animate-ui/react/primitives/react-aria';
export function DeleteProject() {
return (
<DialogTrigger>
<Button>Delete project</Button>
<ModalOverlay>
<Modal>
<Dialog role="alertdialog">
<Heading slot="title">Delete this project?</Heading>
<p>This action cannot be undone.</p>
<Button slot="close">Cancel</Button>
<Button slot="close">Delete</Button>
</Dialog>
</Modal>
</ModalOverlay>
</DialogTrigger>
);
}Animation
React Aria has no Animate UI v1 counterpart: the motion is v1's Alert Dialog (Radix UI and Base UI shipped the same one), with a quicker exit.
- ModalOverlay fades in over 400ms on a soft ease-out, along with the modal's fade, and out the same way. React Aria renders the Modal inside it, so it fades its own background color and backdrop filter (from transparent to the values its classes set) rather than its opacity, which would fade the modal with it.
- Modal tips forward into place, around its center: it starts from
perspective(500px) rotateX(-20deg) scale(0.8), transparent and blurred (4px), and comes upright and sharp on a spring (stiffness 150, damping 25), fading in ahead of it with the overlay (400ms on a soft ease-out): it's there first, then it settles. Dismissed, it goes back the way it came, at once, quicker and speeding away (0.2s, a steady push from half its average speed to one and a half), out of sight just before the overlay has cleared, then unmounts. frompicks the edge the modal tips from, as in v1:topby default (rotateX(-20deg)),bottom(rotateX(20deg)),left(rotateY(20deg)) orright(rotateY(-20deg)).- On the overlay,
exitTransitiondefaults totransition: changetransitionand both directions follow, as in v1. The dialog's own exit is the quicker one above unless you setexitTransition. - Animate UI passes
isExitingwhile the exit plays, so React Aria keeps the modal mounted,data-exitingstays accurate, and focus returns to the trigger. - Without
isDismissable, an outside click doesn't close it; Escape does, unlessisKeyboardDismissDisabled. - Reopening while it closes picks up from where it is.
- Under reduced motion, the modal fades and un-blurs without tilting or scaling.
AnimateUIProvider temposcales every duration and spring.
API Reference
Modal and ModalOverlay take exactly the props of React Aria's Modal, plus:
| Prop | Type | Default |
|---|---|---|
from? | 'top' | 'bottom' | 'left' | 'right' | 'top' |
transition? | Transition | Modal: { type: 'spring', stiffness: 150, damping: 25, opacity: { duration: 0.4, ease: [0.215, 0.61, 0.355, 1] } }; ModalOverlay: { duration: 0.4, ease: [0.215, 0.61, 0.355, 1] } |
exitTransition? | Transition | Modal: { duration: 0.2, ease: [0.33, 0.17, 0.67, 0.5] }; ModalOverlay: transition |
DialogTrigger, Dialog, Heading and the other components take React Aria props only. They are not animated.