Animation

Understand Lumi UI's animation system.

Lumi UI provides a streamlined animation system that uses CSS Transitions instead of traditional CSS animations, creating a more responsive, native-like experience while keeping your code clean and maintainable.

Core Philosophy

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

ClassUsage
animate-popupUsed for Popovers, Dropdowns, Selects etc...
animate-dialogUsed for Modals and Dialogs.
animate-backdropUsed for Overlays.

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.

Add CSS variables to your @theme block
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-out: cubic-bezier(0.19, 1, 0.22, 1);
--duration: 200ms;
--duration-fast: 150ms;
Add animation utilities to your main CSS file
@utility animate-popup {
  transform-origin: var(--transform-origin);
  transition-property: opacity, scale, translate, display, overlay; 
  transition-duration: var(--duration);
  transition-timing-function: var(--ease-out);
 
  &[data-starting-style],
  &[data-ending-style] {
    opacity: 0;
    scale: 0.95;
  }
 
  &[data-ending-style] {
    transition-timing-function: var(--ease-out);
    transition-duration: var(--duration-fast);
  }
 
  @media (prefers-reduced-motion: reduce) {
    transition-duration: 0ms !important;
    animation-duration: 0ms !important;
  }
}
 
@utility animate-dialog {
  transform-origin: top;
 
  transition-property: opacity, scale, translate, display, overlay;
  transition-duration: var(--duration-fast);
 
  &[data-starting-style],
  &[data-ending-style] {
    opacity: 0;
    scale: 0.9;
  }
 
  @media (prefers-reduced-motion: reduce) {
    transition-duration: 0ms !important;
    animation-duration: 0ms !important;
  }
  
}
 
@utility animate-backdrop {
  transition-property: opacity, display, overlay;
  transition-duration: var(--duration-fast);
  transition-timing-function: linear; 
 
  &[data-starting-style],
  &[data-ending-style] {
    opacity: 0;
  }
 
  @media (prefers-reduced-motion: reduce) {
    transition-duration: 0ms !important;
  }
}
 

Customization

Global Customization

Control animations across your entire app by modifying CSS variables:

@theme {
  /* How long the open animation takes */
  --duration: 200ms;
  
  /* How long the close animation takes (usually faster feels snappier) */
  --duration-end: 100ms;
 
  /* The "bounciness" of the opening (Ease Out) */
  --ease-out: cubic-bezier(0.19, 1, 0.22, 1);
  
  /* The "speed" of the closing (Ease In) */
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
}

Read more about customizations in Tailwind CSS.

Component-Specific Overrides

For unique animation needs, override the utility class.

Accessibility

  • Respects prefers-reduced-motion media query
  • Animations are disabled when users prefer reduced motion
  • Smooth transitions for users who enable animations

Opting out

Remove the utility class and use standard Tailwind classes for complete control:

<DialogPopup
  className="transition-transform duration-[700ms] ease-[cubic-bezier(0.45,1.005,0,1.005)] data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 data-[ending-style]:duration-[350ms] data-[ending-style]:ease-[cubic-bezier(0.375,0.015,0.545,0.455)] motion-reduce:transition-none"
/>

Component Compatibility

Uses animate-popup:


Uses animate-dialog & animate-backdrop: Dialog | AlertDialog