UI/UX Design Best Practices
Guidelines for building interfaces where every interaction detail compounds into something that feels right. Covers animation decisions, Tailwind v4 motion utilities, component interaction patterns, and accessibility requirements.
When to Apply
Load this skill when:
- Writing or reviewing components with hover, active, focus, or enter/exit animations
- Implementing transitions, transforms, or keyframe animations (CSS or Tailwind)
- Reviewing Tailwind utility usage for motion-related classes
- Designing interactive elements: buttons, dropdowns, modals, drawers, tooltips, popovers
- Checking accessibility for motion sensitivity (
prefers-reduced-motion)
- Implementing gesture or drag interactions
- Debugging janky or sluggish animations
Reference Documentation
Animation
rules/animation-decision-framework.md - core philosophy, should-animate decision tree, easing selection, duration cheatsheet, perceived performance
rules/animation-springs.md - spring config (Framer Motion / Motion), mouse interactions, interruptibility advantage
rules/animation-component-patterns.md - buttons, scale(0) rule, origin-aware popovers, tooltip instant-on-subsequent, blur crossfades
rules/animation-transitions-transforms.md - CSS transitions vs keyframes, @starting-style, translateY percentages, scale children, GPU acceleration
rules/animation-clip-path.md - inset() shape, hold-to-delete/confirm pattern, tab color transitions, scroll reveals, comparison sliders
rules/animation-gestures.md - momentum dismissal, boundary damping, pointer capture, multi-touch protection, friction stops
rules/animation-performance.md - only animate transform/opacity, CSS variable inheritance, Framer Motion hardware acceleration, WAAPI
rules/animation-accessibility-stagger.md - prefers-reduced-motion, touch hover gating, stagger delays, asymmetric enter/exit timing
rules/animation-review-checklist.md - component design principles, slow-motion debugging, review checklist table
Tailwind v4
rules/tailwind-v4-changes.md - v3→v4 migration table, arbitrary value syntax, CSS variable shorthand
rules/tailwind-transitions.md - transition-property, transition-duration, transition-timing-function, transition-delay
rules/tailwind-transforms.md - scale, translate, rotate, transform-origin, GPU transform-gpu
rules/tailwind-animations.md - animate-* builtins, custom @theme keyframes
rules/tailwind-effects.md - opacity, blur, backdrop-blur
rules/tailwind-interactivity.md - will-change, pointer-events, cursor, user-select
rules/tailwind-variants.md - motion-reduce: / motion-safe:, touch hover gating, starting:, stacking variants
rules/tailwind-patterns.md - ready-to-use patterns (button, dropdown, modal, toast, tooltip, stagger, frosted glass) + anti-patterns table
Quick Reference
The One Rule
Only animate transform and opacity. These skip layout and paint, running on the GPU. Animating height, padding, margin, or width triggers all three rendering steps and causes jank.
Animation Decision by Frequency
| Frequency |
Decision |
| 100+ times/day (keyboard shortcuts, command palette) |
No animation - ever |
| Tens of times/day (hover effects, list navigation) |
Remove or drastically reduce |
| Occasional (modals, drawers, toasts) |
Standard animation |
| Rare or first-time (onboarding, celebrations) |
Can add delight |
Duration Cheatsheet
| Element |
Duration |
| Button press feedback |
100–160ms |
| Tooltips, small popovers |
125–200ms |
| Dropdowns, selects |
150–250ms |
| Modals, drawers |
200–500ms |
| Marketing / explanatory |
Can be longer |
Rule: UI animations under 300ms. A 180ms dropdown feels more responsive than a 400ms one.
Easing Cheatsheet
| Situation |
Easing |
Tailwind |
| Element entering / exiting |
ease-out |
ease-out |
| Element moving on screen |
ease-in-out |
ease-in-out |
| Hover / color change |
ease |
ease-linear or default |
| Constant motion (spinner, marquee) |
linear |
ease-linear |
Never use ease-in for UI interactions. It starts slow - the exact moment the user is watching most closely - making the interface feel sluggish.
Custom Easing Values (register in @theme)
@theme {
--ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
}
<!-- Use in Tailwind via CSS variable shorthand -->
<div class="ease-(--ease-out-strong)">...</div>
Tailwind Quick Patterns
<!-- Button press feedback -->
<button class="transition-transform duration-160 ease-out active:scale-[0.97]">
<!-- Dropdown / popover entry (scale from origin) -->
<div class="transition-[transform,opacity] duration-200 ease-out
data-[state=closed]:scale-95 data-[state=closed]:opacity-0
origin-top-left">
<!-- Toast / modal entry -->
<div class="transition-[transform,opacity] duration-300 ease-out
starting:opacity-0 starting:translate-y-4">
<!-- Respect reduced motion -->
<div class="transition-transform motion-reduce:transition-none">
Review Format
When reviewing UI code, output a markdown table:
| Before |
After |
Why |
transition: all 300ms |
transition: transform 200ms ease-out |
Specify exact properties; avoid all |
transform: scale(0) |
transform: scale(0.95); opacity: 0 |
Nothing appears from nothing |
ease-in on dropdown |
ease-out with custom curve |
ease-in feels sluggish |
No :active state on button |
active:scale-[0.97] |
Buttons must feel responsive to press |
transform-origin: center on popover |
origin-[var(--radix-popover-content-transform-origin)] |
Scale from trigger, not center |
| Animation on keyboard action |
Remove animation entirely |
Repeated 100x/day - animation adds delay |
| Duration > 300ms on UI element |
Reduce to 150–250ms |
Slow transitions feel broken |
Hover without @media (hover: hover) guard |
Add @media (hover: hover) and (pointer: fine) |
Touch devices trigger hover on tap |
| Keyframes on rapidly-triggered element |
CSS transitions for interruptibility |
Keyframes restart from zero on interruption |
Framer Motion x/y props under load |
transform: "translateX()" string |
Short-hand props are not hardware-accelerated |
| Same enter/exit speed |
Exit faster than enter |
Slow deliberate entry, snappy exit |
| All elements appear at once |
Stagger 30–80ms between items |
Cascading feels more natural |
Full Reference
For detailed explanations, code examples, and Tailwind mappings, read the files listed in Reference Documentation above. Load only the specific rule files relevant to the current task to minimize token usage.
1---2name: ui-ux-design-best-practices3description: UI/UX polish, component design, animation decisions, and Tailwind v4 patterns for making interfaces feel right. Use when reviewing, writing, or refactoring UI code involving animations, transitions, CSS transforms, gestures, Tailwind utility classes, or interactive component behavior. Triggers on tasks involving motion design, interactive states (hover/active/focus), component feel, or any use of Tailwind transition/transform/animation utilities.4---56# UI/UX Design Best Practices78Guidelines for building interfaces where every interaction detail compounds into something that feels right. Covers animation decisions, Tailwind v4 motion utilities, component interaction patterns, and accessibility requirements.910## When to Apply1112Load this skill when:13- Writing or reviewing components with hover, active, focus, or enter/exit animations14- Implementing transitions, transforms, or keyframe animations (CSS or Tailwind)15- Reviewing Tailwind utility usage for motion-related classes16- Designing interactive elements: buttons, dropdowns, modals, drawers, tooltips, popovers17- Checking accessibility for motion sensitivity (`prefers-reduced-motion`)18- Implementing gesture or drag interactions19- Debugging janky or sluggish animations2021## Reference Documentation2223### Animation2425- `rules/animation-decision-framework.md` - core philosophy, should-animate decision tree, easing selection, duration cheatsheet, perceived performance26- `rules/animation-springs.md` - spring config (Framer Motion / Motion), mouse interactions, interruptibility advantage27- `rules/animation-component-patterns.md` - buttons, scale(0) rule, origin-aware popovers, tooltip instant-on-subsequent, blur crossfades28- `rules/animation-transitions-transforms.md` - CSS transitions vs keyframes, `@starting-style`, translateY percentages, scale children, GPU acceleration29- `rules/animation-clip-path.md` - `inset()` shape, hold-to-delete/confirm pattern, tab color transitions, scroll reveals, comparison sliders30- `rules/animation-gestures.md` - momentum dismissal, boundary damping, pointer capture, multi-touch protection, friction stops31- `rules/animation-performance.md` - only animate transform/opacity, CSS variable inheritance, Framer Motion hardware acceleration, WAAPI32- `rules/animation-accessibility-stagger.md` - `prefers-reduced-motion`, touch hover gating, stagger delays, asymmetric enter/exit timing33- `rules/animation-review-checklist.md` - component design principles, slow-motion debugging, review checklist table3435### Tailwind v43637- `rules/tailwind-v4-changes.md` - v3→v4 migration table, arbitrary value syntax, CSS variable shorthand38- `rules/tailwind-transitions.md` - `transition-property`, `transition-duration`, `transition-timing-function`, `transition-delay`39- `rules/tailwind-transforms.md` - `scale`, `translate`, `rotate`, `transform-origin`, GPU `transform-gpu`40- `rules/tailwind-animations.md` - `animate-*` builtins, custom `@theme` keyframes41- `rules/tailwind-effects.md` - `opacity`, `blur`, `backdrop-blur`42- `rules/tailwind-interactivity.md` - `will-change`, `pointer-events`, `cursor`, `user-select`43- `rules/tailwind-variants.md` - `motion-reduce:` / `motion-safe:`, touch hover gating, `starting:`, stacking variants44- `rules/tailwind-patterns.md` - ready-to-use patterns (button, dropdown, modal, toast, tooltip, stagger, frosted glass) + anti-patterns table4546## Quick Reference4748### The One Rule4950**Only animate `transform` and `opacity`.** These skip layout and paint, running on the GPU. Animating `height`, `padding`, `margin`, or `width` triggers all three rendering steps and causes jank.5152### Animation Decision by Frequency5354| Frequency | Decision |55|---|---|56| 100+ times/day (keyboard shortcuts, command palette) | No animation - ever |57| Tens of times/day (hover effects, list navigation) | Remove or drastically reduce |58| Occasional (modals, drawers, toasts) | Standard animation |59| Rare or first-time (onboarding, celebrations) | Can add delight |6061### Duration Cheatsheet6263| Element | Duration |64|---|---|65| Button press feedback | 100–160ms |66| Tooltips, small popovers | 125–200ms |67| Dropdowns, selects | 150–250ms |68| Modals, drawers | 200–500ms |69| Marketing / explanatory | Can be longer |7071**Rule:** UI animations under 300ms. A 180ms dropdown feels more responsive than a 400ms one.7273### Easing Cheatsheet7475| Situation | Easing | Tailwind |76|---|---|---|77| Element entering / exiting | ease-out | `ease-out` |78| Element moving on screen | ease-in-out | `ease-in-out` |79| Hover / color change | ease | `ease-linear` or default |80| Constant motion (spinner, marquee) | linear | `ease-linear` |8182**Never use `ease-in` for UI interactions.** It starts slow - the exact moment the user is watching most closely - making the interface feel sluggish.8384### Custom Easing Values (register in `@theme`)8586```css87@theme {88 --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);89 --ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);90 --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);91}92```9394```html95<!-- Use in Tailwind via CSS variable shorthand -->96<div class="ease-(--ease-out-strong)">...</div>97```9899### Tailwind Quick Patterns100101```html102<!-- Button press feedback -->103<button class="transition-transform duration-160 ease-out active:scale-[0.97]">104105<!-- Dropdown / popover entry (scale from origin) -->106<div class="transition-[transform,opacity] duration-200 ease-out107 data-[state=closed]:scale-95 data-[state=closed]:opacity-0108 origin-top-left">109110<!-- Toast / modal entry -->111<div class="transition-[transform,opacity] duration-300 ease-out112 starting:opacity-0 starting:translate-y-4">113114<!-- Respect reduced motion -->115<div class="transition-transform motion-reduce:transition-none">116```117118## Review Format119120When reviewing UI code, output a markdown table:121122| Before | After | Why |123|---|---|---|124| `transition: all 300ms` | `transition: transform 200ms ease-out` | Specify exact properties; avoid `all` |125| `transform: scale(0)` | `transform: scale(0.95); opacity: 0` | Nothing appears from nothing |126| `ease-in` on dropdown | `ease-out` with custom curve | `ease-in` feels sluggish |127| No `:active` state on button | `active:scale-[0.97]` | Buttons must feel responsive to press |128| `transform-origin: center` on popover | `origin-[var(--radix-popover-content-transform-origin)]` | Scale from trigger, not center |129| Animation on keyboard action | Remove animation entirely | Repeated 100x/day - animation adds delay |130| Duration > 300ms on UI element | Reduce to 150–250ms | Slow transitions feel broken |131| Hover without `@media (hover: hover)` guard | Add `@media (hover: hover) and (pointer: fine)` | Touch devices trigger hover on tap |132| Keyframes on rapidly-triggered element | CSS transitions for interruptibility | Keyframes restart from zero on interruption |133| Framer Motion `x`/`y` props under load | `transform: "translateX()"` string | Short-hand props are not hardware-accelerated |134| Same enter/exit speed | Exit faster than enter | Slow deliberate entry, snappy exit |135| All elements appear at once | Stagger 30–80ms between items | Cascading feels more natural |136137## Full Reference138139For detailed explanations, code examples, and Tailwind mappings, read the files listed in **Reference Documentation** above. Load only the specific rule files relevant to the current task to minimize token usage.