ホーム / Skills / Web・UIデザイン / デザインエンジニアリング Design Engineering(Emil Kowalski)
Web・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 の仕上げに関するデザインエンジニアの考え方をルールにしたものです。アニメーションの問いを順に立てます。そもそも動かすべきか(1日に何百回も使うキーボード操作では動かさない)、目的は何か、どのイージングか、どれだけ速くするか。CSS 標準のイージングではなく強めの独自カーブを使い、UI は約300ms以内に収め、スプリングを使う場面も説明します。コンポーネントの細部(押下フィードバック、0からの拡大をしない、トリガーを起点に出るポップオーバー、ツールチップの遅延ルール、キーフレームよりトランジション)、clip-path の技、ドラッグとジェスチャー、パフォーマンス(transform と opacity だけをアニメーションさせる)、モーション低減、タッチでのホバー制御も含みます。レビューは必ず「Before / After / Why」の表とチェックリストで返します。

出力

レビュー表、優先度リスト、各数値の理由を添えた CSS または JSX の提案。

こんな場面に

UI の手触りを良くしたいフロントエンド開発者やデザイナー、モーションとコンポーネントの仕上げに共通の基準を持ちたいチーム。

補足とリスク

低リスク:指示のみのファイルで、スクリプトはなく、ネットワークにも接続せず、ファイルも書き込みません。主張の強いフロントエンドの助言で、数値は作者自身の表に基づくため、絶対の法則ではなく強い既定値として扱ってください。貼り付けたコードで一度試用し、決められた表で返し、コマンドパレットのアニメーションを指摘して優先度を付けました。何も実行・描画していません。質問なしで呼ぶと、短い挨拶だけを返します。作者 Emil Kowalski、MIT。

SKILL.md 原文パッケージ内 2 ファイル