Extends the Dialog component to display content that complements the main content of the screen.
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.
shadcn/ui's Sheet is built on Base UI's Dialog: there is no separate primitive. Its popup carries data-side, and Animate UI's Dialog then slides it in from that edge instead of tipping it in.
Usage
Import the Dialog from Animate UI instead of Base UI, and give the Popup the edge it comes from with data-side. Everything else stays the same, types included (Dialog.Popup.Props…).
import { Dialog as SheetPrimitive } from '@animate-ui/react/primitives/base-ui/dialog';
export function EditProfile() {
return (
<SheetPrimitive.Root>
<SheetPrimitive.Trigger>Open</SheetPrimitive.Trigger>
<SheetPrimitive.Portal>
<SheetPrimitive.Backdrop className="fixed inset-0" />
<SheetPrimitive.Popup
data-side="right"
className="fixed inset-y-0 right-0 w-3/4 sm:max-w-sm"
>
<SheetPrimitive.Title>Edit profile</SheetPrimitive.Title>
<SheetPrimitive.Description>
Make changes to your profile here.
</SheetPrimitive.Description>
<SheetPrimitive.Close>Close</SheetPrimitive.Close>
</SheetPrimitive.Popup>
</SheetPrimitive.Portal>
</SheetPrimitive.Root>
);
}Side
The side prop of shadcn/ui's SheetContent wrapper sets the edge of the screen where the sheet appears. Values are top, right, bottom, or left. The wrapper passes it to the Popup as data-side.
No Close Button
Use showCloseButton={false} on shadcn/ui's SheetContent wrapper to hide the close button. The prop belongs to the wrapper, not to the primitive.
Animation
Animate UI v1's Sheet, sliding in on a soft ease-out, with a smoother backdrop and a quicker exit.
- Backdrop fades in from nothing to what its classes set: its background color deepens while its backdrop filter grows, so the page behind blurs progressively from 0 (fading its opacity would cross-fade the sharp page with an already blurred one). Over 400ms on a soft ease-out (
cubic-bezier(0.215, 0.61, 0.355, 1)), and it clears the same way, outlasting the sheet. - Popup slides in from its
data-sideedge by its own size (translateX(100%)from the right,-100%from the left,translateY(-100%)from the top,100%from the bottom) and fades in, in 0.4s on the same soft ease-out: it answers at once and slows down all the way in. Unlike a drawer it never goes past its rest: held against the screen's edge, it would open a gap there. - Dismissed (Escape, a click outside, the close button or a
Close), it leaves at once, quicker than it came, speeding off its edge (0.2s, a steady push from half its average speed to one and a half) and fading out, then unmounts. The backdrop clears behind it. - On the backdrop,
exitTransitiondefaults totransition: changetransitionand both directions follow, as in v1. The sheet's own exit is the quicker one above unless you setexitTransition. - Base UI decides a closed popup is done before Motion's exit has started. The Portal keeps Base UI's portal mounted and the popup visible until the exit is over; clicks go through to the page as soon as it closes.
- Reopening while it closes picks up from where it is: it slides back in from there.
- A sheet doesn't follow the finger: for a panel you swipe away, use the Drawer.
- Under reduced motion, the sheet fades in place without sliding; the backdrop still fades.
AnimateUIProvider temposcales every duration.
API Reference
The Sheet takes exactly the props of Base UI's Dialog: see the Dialog's API Reference. Animate UI adds the animation props below.
Backdrop
Base UI props, plus:
| Prop | Type | Default |
|---|---|---|
transition? | Transition | { duration: 0.4, ease: [0.215, 0.61, 0.355, 1] } |
exitTransition? | Transition | transition |
Popup
Base UI props, plus:
| Prop | Type | Default |
|---|---|---|
data-side? | 'top' | 'right' | 'bottom' | 'left' | - |
transition? | Transition | { duration: 0.4, ease: [0.215, 0.61, 0.355, 1] } |
exitTransition? | Transition | { duration: 0.2, ease: [0.33, 0.17, 0.67, 0.5] } |