skills / design

emil-design-eng

what it does

This skill encodes Emil Kowalski's philosophy on UI polish, component design, animation decisions, and the invisible details that make software feel great.

Verified Before and after: 2 models 1 try per case View source Download .zip

Compare the answers

Answers from Claude Sonnet 5.5 and GPT-6.1 Sol · try 1 of 1

Same request, same model, once with the skill and once without. Read both and judge for yourself.

“Users say our Cmd+K command palette feels sluggish, even though it renders in under 10ms. Here's how it opens. What's going on?”

Source material given with the request

// CommandPalette.tsx (opened with Cmd+K, our power users open it dozens of times an hour) <AnimatePresence> {open && ( <motion.div initial={{ opacity: 0, scale: 0.8, y: -20 }} animate={{ opacity: 1, scale: 1, y: 0 }} exit={{ opacity: 0, scale: 0.8, y: -20 }} transition={{ type: "spring", stiffness: 120, damping: 8 }} className="palette" > <input autoFocus placeholder="Type a command" /> ... </motion.div> )} </AnimatePresence>
with the skill
**The render is fast; the interaction feels slow because of the animation.** Users press Cmd+K expecting an immediately usable tool, but the palette starts invisible, undersized, and displaced, then bounces into place. For a keyboard-driven interface used dozens of times an hour, **remove the opening and closing animation entirely**. Tuning the spring would improve the symptom, not fix the mismatch. | Before | After | Why | | --- | --- | --- | | `initial={{ opacity: 0, scale: 0.8, y: -20 }}` | Render at full opacity, size, and position | Users shouldn’t have to visually track the palette before typing. | | Spring with `stiffness: 120, damping: 8` | No transition | This underdamped spring overshoots and takes time to settle, adding perceived latency well beyond the render time. | | Animated `exit` within `AnimatePresence` | Immediate unmount | Closing should respond immediately too, especially when users dismiss and reopen rapidly. | ```tsx {open && ( <div className="palette"> <input autoFocus placeholder="Type a command" /> ... </div> )} ``` Remove `AnimatePresence` if it only wraps this palette, and check that `.palette` or its backdrop doesn’t add CSS entry/exit animations.
Show the rest (3 more lines)
Also verify that focus reaches the input immediately and returns to the previous element on dismissal. Keep your dialog semantics, focus trap, and Escape handling intact. **The target is press → palette → type, with no visible waiting stage.** Springs are useful for gestures and interruptible movement—not a frequently used keyboard command.
without
Your render is fast; **the animation makes the palette feel slow.** Users perceive “ready” when the UI looks stable and usable—not when React finishes rendering. This animation gets in the way: - **It starts noticeably displaced:** `scale: 0.8` and `y: -20` make the palette grow and move into position instead of appearing where users expect to type. - **The spring is bouncy:** With `stiffness: 120` and `damping: 8`, it’s underdamped and can overshoot and oscillate. There’s no short, predictable completion time. - **It repeats constantly:** An entrance flourish that feels pleasant once becomes friction when power users invoke it dozens of times an hour. `autoFocus` may make the input technically ready before the animation settles, but typing into a moving, initially transparent input doesn’t *feel* immediate. ### Make opening nearly instantaneous For a keyboard-first utility, remove the motion or use a tiny, short fade: ```tsx const reduceMotion = useReducedMotion(); <AnimatePresence> {open && ( <motion.div
Show the rest (17 more lines)
key="command-palette" initial={reduceMotion ? false : { opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: reduceMotion ? 0 : 0.08 }} className="palette" > <input autoFocus placeholder="Type a command" /> ... </motion.div> )} </AnimatePresence> ``` An instant open is also a good choice—animation isn’t required here. Keep focus and typing immediate, and avoid animating the input’s position or scale. **Measure Cmd+K → visible, focused input**, not just render time. Also verify that keystrokes entered immediately after Cmd+K are captured. That’s the responsiveness users actually experience.

Answers are shown exactly as the model wrote them, from the first try, and nothing is picked by hand.

The models

2 models

Claude Sonnet 5.5

made by Anthropic

claude-sonnet-5-5 · revision not reported by the provider

1 try per case · tested 3 Nov 2026

GPT-6.1 Sol

made by OpenAI

gpt-6.1-sol · revision not reported by the provider

1 try per case · tested 3 Nov 2026

The tasks

written by Carte Blanche
dropdown-css-review

“Review the CSS for our account dropdown. It opens from a button in the top-right of the header.”

janky-bottom-sheet

“Our mobile bottom sheet stutters when it opens and while you drag it, especially on cheap Android phones. Why?”

rapid-toast-css

“Write the CSS for a toast that slides up from the bottom of the screen when it appears and fades out when dismissed. Several toasts can be added within a second, and they stack.”

sluggish-command-palette

“Users say our Cmd+K command palette feels sluggish, even though it renders in under 10ms. Here's how it opens. What's going on?”

sticky-hover-dead-press

“On phones our buttons sometimes stay enlarged after you tap them. They also feel kind of dead when you press them. Can you fix the CSS?”

Install

Download the .zip and unzip it. Put its files, in a folder named emil-design-eng, here:

Claude Code~/.claude/skills/Every project. For one project only, use .claude/skills/ inside it.
Codex~/.agents/skills/Every project. For one repository only, use .agents/skills/ inside it.
Cursor~/.cursor/skills/Cursor also reads the Claude Code and Codex folders above.

Then start a new session and ask for what the skill does. Other agents that read SKILL.md have their own skills folder; check their docs.

Coming after launch: get skills from inside your agent, no download needed.