---
name: "interface_feel_craft"
description: "Teaches interface-feel craft: timing, motion, perceived performance, and micro-interactions. Triggers when someone asks to make a UI feel fast, polished, or responsive, or wants timing/easing/animation values for web or app interfaces."
---

# Interface Feel Craft

## Purpose

Interfaces are judged by how they feel, not by how fast they are. A 200ms response can feel instant with the right feedback, and a 100ms response can feel broken with none. This skill teaches the timing principles, motion rules, perceived-performance techniques, and micro-interaction structure that make interfaces feel good.

## Workflow

### 1. Establish the feedback layer first

Every user action must get acknowledgment inside ~100ms. This is the hard floor of human perception: responses within 100ms feel instantaneous. Below that, do not animate; just respond. The layers:

- **0-100ms: immediate feedback.** Press ripple, field highlight, hover state. No animation needed, just visual confirmation the input landed.
- **100-500ms: value anticipation.** Skeleton screens, optimistic updates, predictive content. The user sees something meaningful while the real work finishes.
- **Beyond 500ms: explicit progress.** Spinner, progress bar, or a message. Past 1 second, the user needs the system to say what it is doing.
- **Under 400ms total (Doherty Threshold):** keep interactive responses under 400ms or the user's mental model of the task breaks.

If an action cannot complete inside 100ms, ship the feedback layer anyway. A spinner shown late feels slower than one shown instantly.

### 2. Set durations by size of change

Use a duration scale. Bigger change, longer animation. Reference Material Design 3 tokens: short1 50ms, short2 100ms, medium1 200ms, medium2 300ms, long1 400ms, long2 500ms.

- **Micro feedback** (button press, toggle, checkbox): 100-200ms. Faster than this reads as instant, which is fine for the feedback layer, but too fast to carry meaning.
- **Component transitions** (dropdown open, tooltip, card expand): 200-300ms. Visible but never sluggish.
- **Panels and modals**: 300-500ms. Entrances run longer than exits at the same tier; entrances orient the user, exits just need to get out of the way.
- **Hard ceiling:** no routine UI animation exceeds 500-700ms. Complex multi-element sequences can go to 1000ms with staggering, but rarely.

### 3. Pick the easing by direction of travel

Easing is what makes motion feel physical instead of mechanical. Choose by where the element is going:

- **Entering:** decelerate, fast start that settles to rest. Material standard-decelerate `cubic-bezier(0, 0, 0, 1)`.
- **Exiting:** accelerate, slow start that picks up speed out. Material standard-accelerate `cubic-bezier(0.3, 0, 1, 1)`.
- **Moving across the screen:** ease-in-out, slow at both ends. Material standard `cubic-bezier(0.2, 0, 0, 1)` also works for most transitions.
- **Never linear** for one-shot UI motion; it reads as robotic. Linear is only for loops and spinners.
- **Avoid the CSS default `ease`**; it is a compromise curve that feels neither intentional nor natural.

### 4. Animate only compositor-safe properties

For 60fps motion, animate `transform` (translate, scale, rotate) and `opacity` only. Animating width, height, top, left, margin, or padding forces layout and paint every frame and will stutter under real page weight. A panel reveal should be `transform: scaleY()` with `transform-origin: top`, never a height transition.

### 5. Build micro-interactions as trigger, rules, feedback

Dan Saffer's structure for any small interaction:

- **Trigger:** what starts it (user-initiated like a tap, or system-initiated like an auto-save).
- **Rules:** what happens and in what order, including what cannot happen.
- **Feedback:** how the user knows the rules executed.
- **Loops and modes:** whether it repeats, and any special states it can be in.

Worked example, a button that submits a form:

```css
.btn {
  transition: transform 150ms cubic-bezier(0.2, 0, 0, 1),
              background-color 150ms cubic-bezier(0.2, 0, 0, 1);
}
.btn:active { transform: scale(0.97); }              /* press: instant confirmation */
.btn.loading { pointer-events: none; }               /* rule: no double submit */
.btn .spinner { display: none; }
.btn.loading .spinner { display: inline-block; }     /* feedback: working state */
.btn.loading .label { visibility: hidden; }          /* keep button dimensions: no layout shift */
```

On click: label hides, spinner shows, dimensions stay fixed (rule), button becomes non-interactive (mode). On success: 300ms color transition to the success state plus an icon swap. On failure: an error state with a message, and the button returns to idle with the label back.

### 6. Choreograph sequences

When several elements move together, stagger them 50-200ms apart, leading element first. Sequential beats simultaneous: a modal that fades its backdrop in while the panel slides up 80ms later feels layered and intentional; both at once feels flat. Keep the whole sequence under 1000ms.

### 7. Respect reduced motion

`prefers-reduced-motion` is an accessibility need, not a preference. Parallax, zoom, and large spatial movement can cause nausea and dizziness. The strategy: replace motion with an instant cut. Keep functional state changes (color, opacity) but drop translate/scale movement.

```css
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
```

## Output Contract

When applying this skill to a design or component, produce:

1. The duration chosen for each motion, with the tier (micro / component / panel) and a one-line reason.
2. The easing curve and direction reasoning (entering, exiting, moving).
3. The feedback-layer plan: what the user sees inside 100ms, what they see by 500ms.
4. The reduced-motion fallback.
5. Runnable code (CSS or equivalent) for the micro-interactions, using only transform and opacity.

## Operating Rules

- Every motion must communicate something: a state change, a spatial relationship, attention direction, or causality. If you cannot name what an animation communicates, remove it.
- Feedback latency is the metric that matters most. Measure time-to-first-acknowledgment, not time-to-complete.
- Entrances are longer than exits. Exiting elements should leave quickly.
- Mobile motion runs about 30% shorter than desktop equivalents for a snappier feel.
- User-driven motion (dragging, scrolling) maps directly to input and stays linear; easing is for system-driven transitions.
- Test motion on the real page, not a blank canvas. Jank only shows up under real weight.
- Never ship a motion design without the reduced-motion fallback.
- No invented numbers: all timing claims in this skill come from the sources in `references/sources.md`.

See [references/sources.md](references/sources.md) for citations and the research base.
