首页 / Skills / 网页与界面设计 / 设计工程 Design Engineering(Emil Kowalski)
网页与界面设计

设计工程 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.

它做什么

把一位设计工程师对界面打磨的做法写成规则。它按顺序提动画问题:这个到底要不要动画(每天用上百次的键盘操作永远不要)、目的是什么、用哪种缓动、多快。它主张用自定义的强缓动曲线,而不是 CSS 内置的几种,让界面动画保持在约 300 毫秒以内,并说明何时该用弹簧。它还涵盖组件细节(按下反馈、不从 0 缩放、从触发点出现的弹出层、提示框的延迟规则、用过渡而不是关键帧)、clip-path 技巧、拖拽与手势、性能规则(只对 transform 和 opacity 做动画)、减少动态效果和触屏上的悬停处理。评审必须以“修改前 / 修改后 / 原因”的表格输出,并带一份检查清单。

输出

评审表格、优先级清单,以及带有每个数值理由的 CSS 或 JSX 建议。

适合什么场景

想让界面“手感对”的前端开发者和设计师,以及想为动效和组件打磨设立统一评审标准的团队。

说明与风险

低风险:纯指令文件,没有脚本,不联网,不写文件。它给出的是带明确主张的前端建议,数值来自作者自己的表格,请当作有力的默认值,而不是铁律。已用一段粘贴的代码试用一次:返回了规定的表格,指出了命令面板的动画问题并给出优先级。没有运行或渲染任何东西。没有带问题调用时,它只会回复一句简短的问候。作者 Emil Kowalski,MIT 协议。

SKILL.md 原文包内共 2 个文件