Animation
Understand Lumi UI's animation system.
Lumi UI uses Base UI's native transition model with CSS Transitions and state attributes. We do not depend on tw-animate presets like animate-in / animate-out as the default pattern.
Core Philosophy
Consistent across components
By centralizing animation logic into shared utility classes, your entire application maintains a unified motion language. This ensures that every popover, modal, and dropdown feels physically identical.
Native Feel with CSS Transitions
Unlike most libraries that use CSS Animations (which must complete once started), Lumi UI uses CSS Transitions that track element state. This means animations can smoothly reverse direction mid-way, preventing the "snapping" effect when users interact quickly.
Clean, Minimal Code
Replace verbose animation classes with single utility classes:
Traditional approach:
<PopoverPrimitive.Popup
className="data-[state=open]:animate-in data-[state=closed]:animate-out
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0
data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ..." />Lumi UI approach:
<BasePopover.Popup className="animate-popup ..." />Available Animation Classes
See Component Compatibility below for details.
Installation & Setup
If you installed init command via CLI, you can skip this section. If you are installing manually, add the following to your CSS.
@utility animate-popup {
@apply origin-[var(--transform-origin)] transition-[opacity,scale,transform] ease-spring duration-150;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
scale: 0.95;
}
}
@utility animate-fade-up {
@apply transition-all duration-300 ease-smooth;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
translate: 0 100%;
}
}
@utility animate-fade-down {
@apply transition-all duration-300 ease-smooth;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
translate: 0 -100%;
}
}
@utility animate-slide-left {
@apply transition-all duration-300 ease-smooth;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
translate: 100% 0;
}
}
@utility animate-slide-right {
@apply transition-all duration-300 ease-smooth;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
translate: -100% 0;
}
}
@utility animate-fade-zoom {
@apply transition-all duration-200 ease-smooth;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
scale: 0.94;
}
}
@utility animate-fade {
@apply transition-all duration-200;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
}
}Component-Specific Overrides
For unique animation needs, override the utility class.
Opting out
Remove utility classes (animate-popup, animate-fade-up, animate-fade-down, animate-slide-left, animate-slide-right, animate-fade-zoom, animate-fade) and use standard Tailwind classes for complete control:
<PopoverContent
className="data-ending-style:scale-90 data-ending-style:opacity-0
data-starting-style:scale-90 data-starting-style:opacity-0
origin-[var(--transform-origin)] transition-[transform,scale,opacity]"
/><DialogContent
className="transition-all duration-200 data-ending-style:scale-90
data-ending-style:opacity-0 data-starting-style:scale-90
data-starting-style:opacity-0"
/><DialogBackdrop className="transition-all duration-200
data-ending-style:opacity-0 data-starting-style:opacity-0" />Component Compatibility
animate-popup
Used for surfaces that follow an anchor or require a "springy" entrance:
- Form: Combobox, Select
- Overlay: Context Menu, Dropdown Menu, Popover, Preview Card, Tooltip
- Status: Toast
- Misc: Menubar
animate-fade & animate-fade-zoom
Used for center-aligned overlays or static backdrops:
- Dialogs:
animate-fade-zoom: Alert Dialog, Command Menu, Dialog (center,scrollable)animate-fade: All backdrops, Dialog (element-outside,responsive,stacked)
- Navigation: Navigation Menu
Directional Animations
Used for edge-aligned Sheet and Dialog variants:
animate-fade-up: Sheet (bottom), Dialog (bottom)animate-fade-down: Sheet (top), Dialog (top)animate-slide-left: Sheet (right)animate-slide-right: Sheet (left)