Communitygithub.com

jakubkrehel/better-ui

打磨并优化您项目中的用户界面,涵盖同心圆角、光学对齐、表面深度、上下文图标、点击区域等。

better-ui 是什么?

这是一个用于提升用户界面细节质量的 AI 技能,专注于那些看似微小但共同决定整体质感的视觉和交互要素。它通过具体、可量化的规则,指导开发者实现内外部元素的同心圆角、基于光学而非几何的对齐方式、使用阴影来表示层次而用边框来体现结构、以及可中断的动画、分步进入/退出动画、上下文图标动画等高级交互效果。该技能支持 CSS、Tailwind CSS 和 motion 库等现代前端技术栈,并且为每种效果提供了精确的参数值(如具体的 `cubic-bezier` 曲线、缩放比例、不透明度和模糊值),而不是模糊的范围。此外,它还包含了针对页面加载时跳过动画、主题切换时抑制过渡、以及谨慎使用 `will-change` 等性能优化建议。技能文档的最后部分提供了一个结构化的问题报告模板,用于按严重级别(高/中/低)记录发现的问题,并指导如何进行浏览器验证,最终给出“阻塞”或“批准”的评审结论。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/jakubkrehel/skills/tree/main/skills/better-ui

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

UI 抛光

抛光来自于大量微小细节的叠加。本技能是这些值得关注的细节以及它们所取值的一个参考。

在设计评审时,请放慢界面的速度。在10%的速度下感觉不对劲的地方,在正常速度下就会以微妙的方式出错。

保留项目的组件库、令牌和密度,并根据其运动语言进行调整,除非以下某条规则规定了明确的交互方式。

下面每一条时长、曲线、缩放和模糊值都是具体的数值,而不是一个需要近似处理的范围。cubic-bezier(0.2, 0, 0, 1) 不是 cubic-bezier(0.4, 0, 0.2, 1),0.96 不是 0.95。请使用这里写明的值。

文本换行、字体渲染、表格数字和文本间距属于 better-typography。点击区域、焦点、键盘支持、ARIA 和减少动画属于 better-accessibility。分组、区块间距、断点和空间 RTL 属于 better-layout。

同心圆角

外半径 = 内半径 + 内边距。嵌套元素上不匹配的圆角是让界面感觉不协调的最常见原因。圆角、阴影和轮廓的配方在 surfaces.md 中。

光学对齐优先于几何对齐

当几何居中看起来不对时,进行光学调整。带图标的按钮、播放三角形和非对称图标都需要手动微调。

用阴影表示层次,用边框表示结构

如果边框的唯一目的是创造深度,那么优先使用多层透明 box-shadow 值。保留用于沟通结构或状态的边框:分隔线、分界线以及选中或焦点状态。

可中断的动画

对交互式状态变化使用 CSS 过渡,因为它们可以在动画中间被中断。保留关键帧动画给一次性运行的阶段性序列。

拆分并错开进入动画

对于不频繁的阶段性入场,如果序列用于沟通层次结构,则将内容拆分成语义块,并错开约 100 毫秒。动画化一个容器让你以相同的代价获得更少的效果。高频交互请保持无错开。参见 enter-exit.md。

微妙的退出动画

使用一个小的固定 translateY 而不是完整高度。退出应该比进入更柔和。双向都使用 ease-out。

上下文图标动画

使用 opacity、scale 和 blur 来动画化图标,而不是切换可见性。精确使用这些值:缩放 0.25 到 1,透明度 0 到 1,模糊 4px 到 0px。

如果使用了运动库(package.json 中的 motion 或 framer-motion),则匹配该包的导入路径,如果两者都存在,则匹配附近的导入路径。使用 transition: { type: "spring", duration: 0.3, bounce: 0 }。弹跳永远为 0。

如果没有运动库,则将两个图标都保留在 DOM 中,一个使用绝对定位,并使用 cubic-bezier(0.2, 0, 0, 1) 进行交叉淡入淡出。这提供了进入和退出效果,且没有依赖项。两种配方都在 icon-transitions.md 中。

图像轮廓

为图像添加一个低不透明度的 1px 轮廓,以获得一致的深度感。浅色模式下使用纯黑色(oklch(0 0 0 / 0.1)),深色模式下使用纯白色(oklch(1 0 0 / 0.1))。绝不能使用像石板灰或锌色这样的近似黑色,也绝不能使用带色调的中性色。带色调的轮廓会拾取底层表面的颜色,看起来像图像边缘的污垢。

按下时缩放

点击时使用 scale(0.96) 能赋予按钮触觉反馈。始终为 0.96;任何低于 0.95 的值都会显得夸张。添加一个 static 属性,以便在动画会分散注意力的地方将其关闭。参见 CSS、Tailwind 和 Motion 的配方。

页面加载时跳过动画

在 AnimatePresence 上使用 initial={false} 来阻止进入动画在首次渲染时执行。检查是否保留了有意的页面入场动画。

主题切换时抑制过渡

主题切换会同时更改几乎所有元素的颜色、背景、边框和阴影。这些属性上的每条过渡都会同时触发,导致切换过程变得模糊而非干脆利落。注入 *,*::before,*::after{transition:none !important},强制重排,然后在下一帧将其移除。参见 配方。

仅过渡发生变化的属性

始终指定确切的属性名称:transition-property: scale, opacity。Tailwind 的 transition-transform 涵盖了 transform, translate, scale, rotate。

谨慎使用 will-change

仅用于 transform、opacity 和 filter,这些属性 GPU 可以进行合成。绝不要使用 will-change: all。在看到首帧卡顿时才添加,而不是提前。参见 performance.md。

匹配图标描边与文本字重

图标旁边的文本携带了文本的光学重量:在常规(400)文本旁边使用 1.5px 描边,在半粗(600)文本旁边使用 2px。每个图标集使用一种描边重量,每个表面使用一个图标库。大小调整和 RTL 翻转在 icons.md 中。

单个 SVG,按状态重新着色

图标使用 currentColor,并通过 CSS 颜色和不透明度从悬停、选中和禁用状态获取颜色,绝不使用独立的资源。轮廓是默认变体;填充表示活动状态。

运动克制

为高频交互提供即时反馈,或者在透明度和颜色上使用时长不超过 150 毫秒的过渡。自定义动画每次触发都会产生注意力成本。

每个动画化的状态变化还需要一个静态提示:颜色、图标或标签。动画绝不是唯一的反馈通道。

完成前检查

错误修复
图标看起来不居中使用内边距进行光学微调,或修复 SVG
突兀的阶段性入场或退出错开不频繁的入场;保持退出微妙
主题切换导致整个页面交叉淡入淡出在切换时禁用过渡,强制重排,在下一帧恢复
在元素上使用 transition: all指定确切属性
首帧动画卡顿添加 will-change: transform(谨慎使用)
纤细图标旁是粗体文本使描边宽度匹配文本字重

报告

严重级别。 HIGH 会破坏交互、使动画无法使用,或者仅在动画运行时状态变化才可见。MEDIUM 是表面、图标或运动中可见的不一致。LOW 是孤立的抛光问题。

验证。 在没有浏览器的情况下:检查组件定义的每个状态,即悬停、焦点、活跃、加载和空状态,以及从代码中读取的运动持续时间和缓动曲线。在浏览器中:遍历每个状态,并在浏览器的动画面板中以 10% 的速度重放动画。将每个无法运行的检查报告为 Not verified。

格式。 将发现的问题按其违反的原则进行分组,按严重级别排序,每行对应一个根本原因,列出其出现的每个位置:

严重级别位置之前之后原因

位置 是 path/to/file:line。原因 说明所违反的原则和用户影响。

当有任何 HIGH 级别的问题存在时,以 Block 结束,否则以 Approve 结束,将表格中的其余问题留待处理。绝不要 Approve 你没有检查过的内容。如果没有需要报告的问题,则说明“未发现可操作的 UI 抛光问题”并报告验证情况。

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

相关技能