홈 / Skills / 웹 및 UI 디자인 / 디자인 엔지니어링 Design Engineering (Emil Kowalski)
웹 및 UI 디자인

디자인 엔지니어링 Design Engineering (Emil Kowalski)

Emil KowalskiMITSkill 언어: 영어
라이선스 확인됨스크립트 없음낮은 위험
실행 예시실제 실행 · claude-sonnet-5-5 · 2026년 10월
Please review this UI code for polish and animation problems. ```css .btn { transition: all 300ms; } .menu { transform: scale(0); transform-origin: center; transition: transform 500ms ease-in; } .menu.open { transform: scale(1); } .card:hover { transform: scale(1.05); } .row { opacity: 0; animation: slideIn 600ms ease-in-out forwards; } ``` ```jsx <motion.div animate={{ x: open ? 0 : -300 }} /> // Cmd+K opens the command palette with a 400ms fade and slide ``` The .menu is a dropdown anchored to a profile button; the row animation plays on a list of 40 items all at once.
Skill: emil-design-eng

Here's the review.

Before After Why
.btn { transition: all 300ms; } transition: transform 160ms ease-out; plus .btn:active { transform: scale(0.97); } all animates properties you didn't intend to animate and can trigger layout and paint. 300ms is too slow for button feedback (aim for 100-160ms). The button also has no press state.
.menu { transform: scale(0) } transform: scale(0.95); opacity: 0; and .menu.open { transform: scale(1); opacity: 1; } Nothing in the real world appears from nothing. scale(0) makes the menu pop out of a point.
transform-origin: center on the profile dropdown transform-origin: top right (or the trigger's side), or var(--transform-origin) if you use Base UI or Radix A popover should grow from its trigger. Only modals stay centered.
transition: transform 500ms ease-in transition: transform 180ms cubic-bezier(0.23, 1, 0.32, 1), opacity 180ms ease-out; ease-in starts slow, which is exactly when the user is watching. 500ms is far too long for a dropdown (150-250ms). Make the close faster than the open, around 120ms.
.card:hover { transform: scale(1.05); } Wrap it in @media (hover: hover) and (pointer: fine), drop to about scale(1.02), and add transition: transform 200ms ease-out on .card Touch devices fire hover on tap, so the card sticks scaled. There is also no transition, so the hover snaps. 1.05 is heavy for a card, and it resizes the content and can cause neighbors to look cramped.
.row { animation: slideIn 600ms ease-in-out forwards; } on 40 items at once animation: slideIn 250ms cubic-bezier(0.23, 1, 0.32, 1) both; with animation-delay: calc(var(--i) * 30ms), and cap the stagger (for example min(var(--i), 8)) Entering elements need ease-out, not ease-in-out. 600ms is too long. All 40 rows moving in unison reads as one block, so stagger them by 30-80ms. Don't let the stagger run for seconds (40 × 30ms is 1.2s), so cap it. Never block interaction while it plays.
.row { opacity: 0; ... } as the base style Put the hidden state in the keyframe's from and use animation-fill-mode: both If the animation fails or is disabled, rows stay invisible forever. Also consider @starting-style or transitions if rows get added dynamically, since keyframes restart from zero when interrupted.
<motion.div animate={{ x: open ? 0 : -300 }} /> animate={{ transform: open ? "translateX(0)" : "translateX(-100%)" }} with an explicit transition, such as a spring (duration: 0.3, bounce: 0) The x shorthand runs on the main thread and drops frames under load. A hardcoded -300 breaks if the panel width changes, so percentages are safer. Springs also keep velocity if the user toggles mid-motion.
Cmd+K palette with a 400ms fade and slide No animation. Render it instantly. A keyboard shortcut used hundreds of times a day should feel instant. Raycast does this. If you want some softness, use at most a 100ms opacity-only fade, and none on close.
No reduced-motion handling anywhere @media (prefers-reduced-motion: reduce) keeps opacity fades and removes the slide, scale and translate motion. In Motion, use useReducedMotion(). Reduced motion means gentler, not zero. Keep the fades that aid comprehension and remove the movement.

Priorities

  1. Remove the Cmd+K animation. It has the biggest impact on how the app feels.
  2. Fix the dropdown (scale(0), ease-in, 500ms, center origin), since it hits every issue at once.
  3. Stagger and shorten the list animation.
  4. Clean up transition: all, the hover gating, and the Motion x prop.

Suggested CSS for the dropdown and rows

:root { --ease-out: cubic-bezier(0.23, 1, 0.32, 1); }

.menu {
  opacity: 0;
  transform: scale(0.95);
  transform-origin: top right; /* match the profile button's position */
  transition: transform 120ms var(--ease-out), opacity 120ms ease-out;
}
.menu.open {
  opacity: 1;
  transform: scale(1);
  transition-duration: 180ms;
}

.row {
  animation: slideIn 250ms var(--ease-out) both;
  animation-delay: calc(min(var(--i), 8) * 40ms);
}
@keyframes slideIn {
  from { opacity: 0; transform: translateY(8px); }
}

The menu's closed state needs pointer-events: none or visibility: hidden so it isn't clickable while invisible.

Test run: a pasted CSS and JSX snippet with common animation mistakes. The model used the required Before, After, Why table, flagged the Cmd+K palette animation and gave a priority list. Nothing was run or rendered; the suggested values come from the Skill's own tables.

하는 일

UI를 다듬는 디자인 엔지니어의 철학을 규칙으로 옮겼습니다. 애니메이션에 대한 질문을 순서대로 던집니다. 애초에 움직여야 하는가(하루에 수백 번 쓰는 키보드 동작에는 절대 안 됨), 목적은 무엇인가, 어떤 이징인가, 얼마나 빠른가. CSS 기본 이징 대신 강한 맞춤 곡선을 쓰고, UI는 약 300ms 이내로 유지하며, 스프링을 써야 할 때를 설명합니다. 컴포넌트 세부(눌림 피드백, 0에서 시작하는 확대 금지, 트리거에서 나오는 팝오버, 툴팁 지연 규칙, 키프레임 대신 트랜지션), clip-path 기법, 드래그와 제스처, 성능 규칙(transform과 opacity만 애니메이션), 모션 줄이기, 터치 기기의 호버 처리도 포함합니다. 검토는 반드시 'Before / After / Why' 표와 체크리스트로 돌려줍니다.

결과물

검토 표, 우선순위 목록, 각 값의 이유가 붙은 CSS 또는 JSX 제안.

이런 때 좋습니다

인터페이스의 손맛을 살리고 싶은 프런트엔드 개발자와 디자이너, 모션과 컴포넌트 다듬기에 일관된 검토 기준을 두려는 팀.

참고 사항 및 위험

낮은 위험:지침만 있는 파일로 스크립트가 없고, 네트워크에 접속하지 않으며, 파일을 쓰지 않습니다. 주관이 뚜렷한 프런트엔드 조언이며 수치는 작성자 본인의 표에서 나온 것이므로 절대 법칙이 아니라 강한 기본값으로 보세요. 붙여 넣은 코드로 한 번 시험했고, 정해진 표로 답하며 명령 팔레트의 애니메이션 문제를 짚고 우선순위를 줬습니다. 실행이나 렌더링은 하지 않았습니다. 질문 없이 호출하면 짧은 인사만 합니다. 작성자 Emil Kowalski, MIT.

SKILL.md 원본패키지에 파일 2개