Prototyper UI animation conventions for writing, reviewing, or debugging transition code, overlay enter/exit, press feedback, and prefers-reduced-motion.
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
- Build PrimitiveBuild foundational UI primitives from scratch with strong ARIA, keyboard, focus, and state handling.
- Create ComponentCreate new Prototyper UI components from scratch, including Base UI primitives, registry entries, examples, and MDX documentation.
- Prototyper UIPrototyper UI component library (Tailwind CSS v4 + Base UI) for installing components, customizing themes, and using component documentation.