animate-ui
Back to list

PrototyperAI/animate-ui

Animate UI

GitHub

Prototyper UI animation conventions for writing, reviewing, or debugging transition code, overlay enter/exit, press feedback, and prefers-reduced-motion.

48 installsMotionInteractionCraft0 demos

Real-world examples not captured yet

This skill shows a gallery of live HTML demos (CDN libraries welcome — GSAP, Three.js, etc.) rendered inline via srcdoc.

Skill markdown
# Prototyper UI — Animation Conventions

All animation decisions for Prototyper UI components. Patterns first, then lookup tables, then rules, then per-component details.

---

## 1. Copy-Paste Patterns

These five patterns cover ~95% of animation work. Copy the exact class strings.

### Pattern A: Positioned Overlay

Used by: Popover, Menu, Tooltip, Select, Combobox, Context Menu, HoverCard, Menubar.

```tsx
className={cn(
  // Enter
  "data-open:animate-in data-open:duration-150",
  "data-open:[animation-timing-function:var(--ease-out-fluid)]",
  "data-open:fade-in-0 data-open:zoom-in-95",
  // Exit
  "data-closed:animate-out data-closed:duration-100",
  "data-closed:[animation-timing-function:var(--ease-in-quart)]",
  "data-closed:fade-out-0 data-closed:zoom-out-95",
  // Direction-aware slide (2 = 0.5rem)
  "data-[side=bottom]:slide-in-from-top-2",
  "data-[side=top]:slide-in-from-bottom-2",
  "data-[side=left]:slide-in-from-right-2",
  "data-[side=right]:slide-in-from-left-2",
  // Origin from trigger position
  "origin-(--transform-origin)",
  // Performance
  "data-entering:will-change-[opacity,transform]",
  "data-exiting:will-change-[opacity,transform]",
  // Accessibility
  "motion-reduce:animate-none motion-reduce:transition-none",
)}
```

### Pattern B: Dialog (Center)

```tsx
// Backdrop
className={cn(
  "data-open:animate-in data-closed:animate-out",
  "data-closed:fade-out-0 data-open:fade-in-0",
  "duration-200",
  "bg-black/10 supports-backdrop-filter:backdrop-blur-xs",
  "motion-reduce:animate-none motion-reduce:transition-none",
)}

// Content — note the slight overshoot scale
className={cn(
  "data-open:animate-in data-closed:animate-out",
  "data-closed:fade-out-0 data-open:fade-in-0",
  "data-closed:zoom-out-[0.98] data-open:zoom-in-[1.02]",
  "duration-200 ease-out-fluid",
  "data-entering:will-change-[opacity,transform]",
  "data-exiting:will-change-[opacity,transform]",
  "motion-reduce:animate-none motion-reduce:transition-none",
)}
```

Dialog uses `zoom-in-[1.02]` (slight overshoot) and `zoom-out-[0.98]` — subtler than overlay's `zoom-in-95`/`zoom-out-95`.

### Pattern C: Sheet (Side-Aware)

```tsx
const sheetVariants = cva(
  // Base: transition + split enter/exit duration
  "transition ease-out-fluid " +
    "data-open:animate-in data-open:duration-300 " +
    "data-closed:animate-out data-closed:duration-200 " +
    "data-entering:will-change-[opacity,transform] " +
    "data-exiting:will-change-[opacity,transform] " +
    "motion-reduce:animate-none motion-reduce:transition-none",
  {
    variants: {
      side: {
        top: "data-open:slide-in-from-top data-closed:slide-out-to-top",
        bottom:
          "data-open:slide-in-from-bottom data-closed:slide-out-to-bottom",
        left: "data-open:slide-in-from-left data-closed:slide-out-to-left",
        right: "data-open:slide-in-from-right data-closed:slide-out-to-right",
      },
    },
  },
);
```

Sheets slide 100% (full edge-to-edge), not `slide-*-2` like positioned overlays.

### Pattern D: Press Feedback

```tsx
"motion-safe:active:scale-[0.97]"; // Standard interactive elements
"motion-safe:active:scale-[0.98]"; // Menu items, tab triggers
"motion-safe:active:scale-[0.95]"; // Small controls
"motion-safe:active:scale-100"; // Explicitly disabled (ghost/link buttons)
```

Always `motion-safe:` prefix — never bare `active:scale-*`. Checkbox uses `motion-safe:group-active:scale-[0.95]` (group variant).

| Scale          | Components                                                                         |
| -------------- | ---------------------------------------------------------------------------------- |
| `scale-[0.97]` | Button (default), Switch (track), Toggle, Toolbar (Button, Link), Select (trigger) |
| `scale-[0.98]` | Menu items (Item, SubTrigger, CheckboxItem, RadioItem), Tabs (trigger)             |
| `scale-[0.95]` | Checkbox (control), RadioGroup (item), NumberField (Increment, Decrement)          |
| `scale-100`    | Button ghost variant, Button link variant                                          |

### Pattern E: State Transition

```tsx
"transition-[color,background-color,border-color,box-shadow,opacity] duration-150 ease-smooth";
"motion-reduce:transition-none";
```

Used by: Button, Checkbox, Combobox (input/chips/chip-remove), Field (FieldGroup), Input, InputGroup, Menu items, NumberField, RadioGroup, Select (trigger), Tabs (trigger), TextField, Textarea, Toggle, Toolbar (button/link/input), NavigationMenu (trigger/link), Accordion (trigger).

---

## 2. Easing Tokens

Defined in `apps/docs/registry/prototyper-tokens.css`:

| Token              | Value                                     | When to use                                              |
| ------------------ | ----------------------------------------- | -------------------------------------------------------- |
| `ease-smooth`      | `cubic-bezier(0.4, 0, 0.2, 1)`            | State transitions, on-screen changes                     |

…

More from PrototyperAI