mcpField
B
better-ui

better-ui

github.com/23jmo设计与 UI17374 次安装3 周前更新
代码仓库

关于 better-ui

better-ui 是用于交互完善后检查界面表面、图标和动效的视觉润色技能。它提供具体规则和数值,并将无障碍、排版、布局与颜色检查交由相关技能处理。

主要功能

  1. 01嵌套表面的圆角规则
  2. 02阴影、边框和图片描边规范
  3. 03交互过渡与按压缩放参数
  4. 04减少动态效果和悬停条件
  5. 05图标颜色、线宽与方向规则
  6. 06按严重程度组织问题并验证

适用场景

  1. 01润色表面层次与圆角
  2. 02检查交互状态下的动效
  3. 03审查图标一致性和悬停行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/23jmo/jmo-skills --skill better-ui

安装后在 Claude Code 中输入/better-ui确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

animations.md
enter-exit.md
icon-transitions.md
icons.md
LICENSE
performance.md
surfaces.md
agents/
openai.yaml

详细介绍

UI 润色

此技能规定了界面、图标和动效的视觉润色细节,以及每项细节的确切取值。只有在底层交互正常后才适用,润色方面的问题绝不能优先于交互故障。

精确取值,可选润色

以下取值都是精确值,不是供近似参考的范围。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 负责,方向性图标的镜像除外。颜色令牌和对比度测量归 better-colors 负责。

外层圆角等于内层圆角加内边距

当嵌套表面具有可见且均匀的内缩时,外层圆角等于内层圆角加内边距,再加上任何边框宽度。内边距超过 24px,或有意采用不对称内边距时,应将各层视为独立表面,并为每层保留其圆角令牌。具体做法见 surfaces.md。

几何对齐不佳时进行视觉微调

几何居中看起来不协调时,应根据视觉效果进行微调。按钮图标一侧的内边距减少 2px,将播放三角形朝尖端方向移动,并直接修正 SVG 中不对称的字形。具体做法见 surfaces.md。

阴影用于表现层级,边框用于表现结构

如果边框仅用于营造深度效果,应将其替换为多层透明 box-shadow 值。分隔线、分隔符、表格单元格和选中状态应保留边框。表单输入框也应保留边框,因为根据 better-accessibility,其边界需要达到 3:1 的非文本对比度。焦点环同样归 better-accessibility 负责。

强制颜色模式会移除所有 box-shadow。在阴影环下保留 border: 1px solid transparent,这样该模式仍会绘制边缘。具体做法见 surfaces.md。

为图像添加纯黑或纯白描边

为内容图像添加向内偏移 1px 的 1px 描边。浅色模式使用 oklch(0 0 0 / 0.1),深色模式使用 oklch(1 0 0 / 0.1)。切勿使用调色板中的近黑色、带色调的中性色或强调色,因为这些颜色会在图像边缘形成彩色边缘。对于 Logo 和插画等透明艺术图像则跳过。具体做法见 surfaces.md。

交互状态使用过渡,而非关键帧

使用 CSS 过渡或动效库的弹簧效果来驱动交互状态变化;当用户在动效进行中反向操作时,它们会重新确定目标。关键帧会按固定时间线运行,无法反向,因此仅用于只运行一次的序列。参见 animations.md。

按下时缩放至 0.96

按钮按下时,以 ease-out 在 150ms 内缩放至 0.96;禁用状态下则绝不缩放。如果动效会造成干扰,可通过组件现有的变体 API 或 static 属性为按钮提供退出选项。参见 CSS、Tailwind 和 Motion 的做法。

高频交互不添加动画

按键输入、行悬停和标签页切换应即时反馈,或仅对 opacity 或 background-color 添加不超过 150ms 的过渡。将富有表现力的动效留给不频繁出现的时刻,例如视图首次加载、成功状态或空状态。

每种动画状态变化还应通过颜色、图标或标签提供静态提示。动效绝不能是唯一的反馈渠道。

根据减少动态效果偏好控制动态效果

better-accessibility 负责这项要求,所有方案都必须遵守。仅在 prefers-reduced-motion: no-preference 下运行移动、缩放和模糊效果。减少动态效果时,应改用透明度交叉淡入淡出,而不是直接移除元素。CSS、Tailwind 和 Motion 的方案见 animations.md。

低频入场效果间隔 100ms

当分阶段入场的顺序能够体现层级关系时,应将内容拆分为标题、描述和操作等语义区块。各区块的入场效果间隔 100ms,在 300ms 内使用 ease-out,同时应用透明度、4px 模糊和 12px 的 translateY。日常交互绝不使用交错动画。参见 enter-exit.md。

退场效果应比入场更短、更轻

退场时使用透明度、4px 模糊和固定 -12px 的 translateY,时长为 150ms,缓动为 ease-out,绝不使用整个容器的高度。只有在目标位置本身有意义时才完全滑出,例如抽屉关闭。动态效果没有提供信息时,应立即移除元素。参见 enter-exit.md。

首次渲染时跳过状态动画

在包裹状态切换的 AnimatePresence 上设置 initial={false},这样默认状态在挂载时就不会播放动画。对于有意设置的入场效果(例如交错显示的主视觉区),绝不要这样设置。参见 animations.md。

使用精确数值交叉淡入淡出上下文图标

图标在低频状态变化时切换,例如播放变为暂停,或复制变为已复制,应使用交叉淡入淡出效果。缩放从 0.25 变为 1,透明度从 0 变为 1,模糊从 4px 变为 0px。使用动态效果库时,采用 { type: "spring", duration: 0.3, bounce: 0 },且 bounce 始终为 0。不使用动态效果库时,将两个图标都保留在 DOM 中,并使用 cubic-bezier(0.2, 0, 0, 1) 在 300ms 内完成交叉淡入淡出。

标签页图标切换,以及悬停时行内显示的操作,都属于高频交互不使用动画。两种方案见 icon-transitions.md。

切换主题时禁用过渡效果

主题切换时禁用所有过渡效果,强制刷新样式,并在下一帧后恢复过渡效果。否则,所有颜色过渡会同时触发,使切换过程显得拖沓。参见方案。

只过渡发生变化的属性

像 transition-property: scale, opacity 这样明确指定属性,绝不要使用 all。参见 performance.md。

在 will-change 中指定动画属性

只有在确认首帧卡顿后才添加 will-change,并明确指定动画属性:scale 对应 scale,transform 对应 transform。仅限变换属性、opacity 和 filter,绝不要使用 all。参见 performance.md。

仅对支持悬停的指针应用悬停效果

将仅用于悬停的样式放在 @media (hover: hover) 内。触屏设备上,轻触后 :hover 会保持激活,呈现类似选中状态的效果。Tailwind 4 的 hover: 变体已在该查询条件下编译,而 Tailwind 3 没有。若控件会自行绘制按压状态,则设置 -webkit-tap-highlight-color: transparent,避免默认的灰色闪烁叠加其上。

限制覆盖层内的滚动

为可滚动的对话框、抽屉、菜单和侧边面板设置 overscroll-behavior: contain,以避免滚动超出其边界后,页面背景跟着滚动。

让图标描边粗细与文本字重匹配

图标的实际描边粗细应与旁边文本的字重相匹配,从字重 400 时的 1.5px 到字重 700 时的 2.5px。同一个界面中只使用一个图标库。表格、尺寸和网格规则见 icons.md。

一个 SVG,按状态重新着色

图标使用 currentColor,并通过 CSS 颜色和不透明度呈现悬停、选中和禁用状态,不使用单独的资源。默认变体为描边,填充表示激活状态。在 dir="rtl" 下,仅镜像含义随阅读方向变化的图标。请参阅 icons.md。

完成前检查

检测项修复方法
带内边距的父元素和子元素使用相同的 rounded-* 或 border-radius将内边距加到外层圆角上
box-shadow: 0 0 0 1px 用作边框环,但旁边没有 borderborder: 1px solid transparent
img 上的 outline-slate-*、outline-zinc-* 或十六进制轮廓颜色outline-black/10 和 dark:outline-white/10
transition-all 或 transition: all指定发生变化的属性
在 :hover、.open 或其他切换类上设置 animation:对相同属性使用过渡
active:scale-95、scale-90 或低于 0.96 的 whileTap0.96
:active 缩放没有排除 :disabledenabled:active: 或 :not(:disabled):active
bounce: 设置为非 0 值bounce: 0
基础规则中的 opacity: 0 仅通过 animation 显示在 from 关键帧中设置隐藏状态,并使用 animation-fill-mode: both
translate、scale、filter 或 motion.* 动画没有 prefers-reduced-motion、motion-safe: 或 MotionConfig 防护添加防护,并在减少动态效果时交叉淡入淡出不透明度
颜色过渡加上主题切换,但没有 disableTransitionOnChange 或覆盖规则使用主题切换抑制方案
will-change: all,或在从未播放动画的元素上设置 will-change指定动画属性或删除该声明
图标 SVG 中的 fill="#..." 或 stroke="#..."currentColor
@media (hover: hover) 之外的纯 CSS :hover 或 Tailwind 3 hover:用媒体查询包裹
对话框、抽屉或菜单上的 overflow: auto 或 overflow-y-auto 没有 overscroll-behavioroverscroll-behavior: contain

报告

严重程度。 HIGH 表示会破坏交互,例如无法反向播放的关键帧切换,或在触屏设备上卡住的悬停状态。better-interface 的两个升级触发条件都属于此类,一经发现即为 HIGH。一个是忽略 prefers-reduced-motion 的动态效果,另一个是仅通过动态效果呈现的状态变化。MEDIUM 表示表面样式、图标或动态效果存在明显不一致。LOW 表示个别细节需要打磨。

验证。 没有浏览器时,请根据代码读取组件定义的所有状态,例如悬停、按下、选中、加载和空状态,并检查其持续时间和缓动方式。使用浏览器时,请逐一查看各状态,并在浏览器的 Animations 面板中以 10% 速度重放动态效果。将所有无法执行的检查报告为 Not verified。

格式。 按违规原则分组,按严重程度排序;每个根本原因占一行,并列出其出现的所有位置:

严重程度位置修复前修复后原因

位置 格式为 path/to/file:line。原因需指出违反的原则及对用户的影响。

若仍存在任何 HIGH,结尾写上 Block;否则写上 Approve,并在表格中保留其余待处理事项。不得对未检查的覆盖范围写 Approve。若没有需要报告的问题,请写明“没有可采取行动的 UI 润色问题”,并报告验证情况。

评论

支持 Markdown