An overlay element positioned relative to a trigger.
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
Import from Animate UI instead of react-aria-components: it re-exports all of React Aria, with an animated Popover. Everything else stays the same.
import {
Button,
Dialog,
DialogTrigger,
Heading,
Popover,
} from '@animate-ui/react/primitives/react-aria';
export function SharePopover() {
return (
<DialogTrigger>
<Button>Share</Button>
<Popover placement="bottom" offset={4}>
<Dialog>
<Heading slot="title">Share this document</Heading>
Anyone with the link can view it.
</Dialog>
</Popover>
</DialogTrigger>
);
}Popover is the overlay under React Aria's Select, ComboBox, MenuTrigger, SubmenuTrigger, DatePicker and PreviewTrigger too: importing them from Animate UI animates every one of them.
Animation
React Aria has no Animate UI v1 counterpart: the Popover moves like the closest v1 overlay.
- Under a
DialogTrigger, aPreviewTriggeror a date picker, like the Radix UI and Base UI popovers: it grows from 0.8 and fades in, from the trigger (--trigger-anchor-point, or the side facing the trigger before React Aria measures it), on a spring (stiffness 400, damping 29) that overshoots a little; it shrinks back the same way when it closes, then unmounts. - Under a
MenuTrigger, aSubmenuTrigger, aSelector aComboBox, like the menus: a 220ms fade and scale from 0.9 (soft ease-out), both ways. Submenus move like their menu. Under aSelector aComboBoxwith a single selection, choosing another item holds the popover still before it closes while the chosen item's check (aSelectionIndicator) changes: 250ms while it draws itself, 150ms while it pops or glides. Without a check, it doesn't wait. Under aMenuTriggeror aSubmenuTrigger, choosing an item whose check changes holds it the same way, along with the menus around a submenu. - React Aria only keeps a closing popover mounted if animations are running when it closes, before Motion starts any. Animate UI tracks the same open state React Aria reads (the trigger's, or
isOpen/defaultOpen) and passesisExitingwhile the exit plays, sodata-exitingand theisExitingrender prop stay accurate. - Reopening while it closes picks up from where it is.
shouldSkipAnimation(set byPreviewTriggerwhen swapping previews during its warmup) skips both the entrance and the exit, as React Aria intends.classNameandstylefunctions keep working, and your ownrenderfunction is made animatable rather than replaced.- Open from the start (
defaultOpenon the trigger or the Popover), it plays its entrance on page load, like v1. - Under reduced motion, it only fades (no scale).
API Reference
Popover takes exactly the props of React Aria's Popover, plus:
| Prop | Type | Default |
|---|---|---|
transition? | Transition | { type: 'spring', stiffness: 400, damping: 29 }; menus, selects and comboboxes: { duration: 0.22, ease: [0.215, 0.61, 0.355, 1] } |
exitTransition? | Transition | transition |
DialogTrigger, Dialog, OverlayArrow and the other components take React Aria props only. They are not animated.