Communitygithub.com

surfaces

定义 Web UI 中每个元素的材质、层级、状态和图标,确保一致的表面设计系统。

surfaces 是什么?

该 AI 技能为 Web UI 组件提供一套“表面”设计规范,涵盖填充、边缘、阴影、圆角、交互状态及图标处理。它通过一个简短的配方列表来决策,确保两个屏幕不会出现不同的卡片风格。技能详细说明了决策顺序:首先判断是否需要表面;其次选择层级(页面、抬升、浮动、覆盖);然后用阴影环表示高度,用边框表示结构,不同时使用;圆角采用同心嵌套规则;交互状态(悬停、按下、选中、禁用、焦点可见)作为表面变化设计;图标使用单一集合、`currentColor`、描边与文本匹配;材质仅允许在滚动内容上方的浮动镀铬中使用;最后处理滚动边缘的分隔线、淡化和过滚动。此技能适用于任何现代 Web 框架(React、Vue、Angular 等),通过 CSS 变量和 Token 实现,并特别考虑了强制色彩模式等无障碍场景。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nkurunziza-saddy/hmm-interfaces/tree/HEAD/surfaces

在你喜欢的 AI 中提问

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

文档

表面

本技能决定每个元素由什么构成:其填充、边缘、阴影、圆角、状态和图标。它从一份简短的配方列表中挑选,因此两个屏幕上绝不会出现两种不同的卡片。

在做任何决策之前,请应用 product-ui §1(品味日志和优先级)和 §5(哪个技能拥有什么)。

按此顺序决策

  1. 是否需要表面? 先移除再添加。带周围空白的标题不需要卡片。永远不要在卡片内嵌套卡片。原因:每个容器都会增加一个眼睛必须阅读的边缘。
  2. 哪个层级? 页面、抬升、浮动或覆盖。每个元素一个层级,根据其功能而不是你想让它多突出而选择。elevation.md
  3. 边缘由什么绘制? 高度获得阴影环。结构获得边框。绝不在一个边缘上同时使用两者。elevation.md
  4. 哪个圆角? 获取元素角色的标记,然后使嵌套的圆角同心。elevation.md
  5. 哪些状态? 将悬停、按下、选中、禁用和焦点可见设计为表面的变化,然后再完善默认状态。states-and-icons.md
  6. 哪种图标处理? 单一集合、currentColor、描边与文本匹配。states-and-icons.md
  7. 是否允许材质? 仅限滚动内容上方的浮动镀铬。materials-and-edges.md
  8. 滚动边缘。 分隔线、淡化、过滚动。materials-and-edges.md

四个层级

层级用于浅色模式深色模式
页面底面底面填充,无阴影最深填充,无阴影
抬升卡片、控件、选中项白色,环 + 1px 投影 + 3px 紧密投影亮一个色阶,白色环,紧密黑色投影
浮动菜单、弹出层、工具提示、提示框白色,环 + 1px 投影 + 4px 紧密投影亮两个色阶,白色环,紧密黑色投影
覆盖对话框、抽屉、命令面板(带遮罩)白色,环 + 1px 投影 + 6px 紧密投影亮三个色阶,白色环,紧密黑色投影

精确标记在 elevation.md 中。其背后的规则:

  • 环加紧密投影。 模糊 ≤ 8px,偏移 ≤ 6px,投影具有负扩散。原因:大而柔和的模糊读起来像发光,弄脏页面,看起来像生成的。
  • 深色模式通过变亮来抬升。 阴影在深色上几乎看不见,因此亮度承载高度,低 Alpha 的白色环承载边缘。
  • 阴影是半透明的且单一颜色。 不透明的灰色会留下光晕。深色投影保持黑色。
  • 同级共享一个层级。 一行中的卡片有一个阴影、一个圆角、一个内边距。
  • 悬停改变填充,而不是阴影。

无需参考的规则

  • 边框显示结构,阴影显示高度。 分隔线、输入框、表格单元格和选中状态保留边框。一个卡片其边框仅为了抬升而存在时,应使用环代替。
  • 在阴影环下方保留 border: 1px solid transparent。 原因:强制色彩模式会移除阴影,而边框仍会绘制一个边缘。
  • 图像获得 1px 内嵌轮廓:outline: 1px solid 黑色 10%(深色下白色 10%),outline-offset: -1px。绝不要使用色调颜色,后者会显示为条纹。跳过徽标和透明艺术品。
  • 同心圆角。 外层 = 内层 + 内边距(+ 边框),最多 24px 内边距。超过此值,它们就是独立的表面。
  • 焦点是一个环,绝不要无。 :focus-visible 显示一个 2px 的强调色轮廓,偏移 2px;字段采用齐平的方式,作为 2px 的强调色边缘,没有间隙。没有替代品的 outline: none 是个 bug。该环不占用布局空间。
  • 禁用控件不接受悬停、按下或缩放。
  • 图标:每个表面一个集合,currentColor,默认轮廓,激活时填充。描边与相邻文本字重匹配,400 字重时 1.5px 到 600 字重时 2px。
  • 仅浮动镀铬中使用背景模糊。 绝不要在内容、卡片或表格上使用。
  • 可滚动覆盖层(对话框、抽屉、菜单)获得 overscroll-behavior: contain。

对比

错误的写法正确的写法原因
卡片上的 border: 1px solid #e5e5e5box-shadow: var(--elev-raised); border: 1px solid transparent仅用于深度的边框变成环;强制色彩仍会绘制边缘
box-shadow: 0 10px 40px rgba(0,0,0,.2)0 0 0 1px a.08, 0 1px 2px a.12, 0 4px 8px -4px a.16紧密清晰胜过宽大柔和
深色卡片使用 0 8px 24px #000更亮的填充加 0 0 0 1px oklch(1 0 0 / .08)阴影在深色上消失;亮度显示高度
卡片圆角 8,内部图片圆角 8,内边距 8内部 8,外部 16同心角保持均匀间隙
<img> 融入白色卡片outline: 1px solid oklch(0 0 0 / .1); outline-offset: -1px边缘可读,无需边框
button:focus { outline: none }button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px }键盘用户保留焦点
1.5px 图标描边紧邻 600 字重标签2px 描边描边粗细匹配字重粗细
每个工具栏位置填充图标默认轮廓,激活按钮填充填充是状态信号
卡片上的 backdrop-filter: blur(20px)不透明表面模糊属于浮动在滚动内容上的镀铬

完成前检查

模式修复
box-shadow 模糊 > 8px 或 Alpha > .2 在浅色 UI 上使用层级标记
border 加上 box-shadow 做同样的工作仅使用环加透明边框
阴影环缺少 border: 1px solid transparent添加它
父元素和其内边距子元素相同的 border-radius父元素使用 inner + padding
没有 :focus-visible 替代品的 outline: none 或 outline: 0添加环
使用 :focus(不是 :focus-visible)样式化环切换到 :focus-visible
状态中 border-width 变化颜色、填充或等宽的透明边框
图标中硬编码的 fill="#…" 或 stroke="#…"使用 currentColor
一个屏幕上导入两个图标库只用一个
固定栏、侧边栏或浮动菜单外部的 backdrop-filter移除它
覆盖层列表没有 overscroll-behavior: contain添加它
滚动器边缘的硬切,或被 overflow: hidden 裁剪的阴影淡化边缘;为滚动器增加内边距

通过在 2 倍缩放下渲染浅色和深色模式并裁剪每个层级的边缘来进行验证。悬停、按下、Tab 聚焦、选择和禁用每个控件,并比较操作前后的盒子尺寸。切换强制色彩模式(Chrome 开发者工具,渲染仿真)并确认每个卡片仍有一个边缘。

Individual skills in this repo

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

nkurunziza-saddy/break

Stress-tests a piece of UI with worst-case data and every reachable state, then reports what broke with a numbered fix for each. Use it when the user types /break, or asks to "break this", "stress-test", "try the worst case", "what happens with long names", "check the empty and error states" or "find the edge cases" on a component or screen.

nkurunziza-saddy/layout

Structure and space in product UI on the web. It sets the spacing scale, grouping, alignment, density (compact or comfortable), hit areas, app shells (sidebar, toolbar, content, inspector), max widths, container-query responsiveness, dropdown and popover sizing, room for long and translated text, layout stability (no shift on load) and sticky elements that must not cover focus.

nkurunziza-saddy/motion

Builds motion for product UI on the web. It decides whether something should move at all, then why, which tool (CSS transition, WAAPI, Motion, spring), which properties, curve, duration, interruption, exit and reduced-motion path, and it writes the code. Also covers stagger and choreography, gestures (drag, flick, sheets), motion tokens and animation performance.

nkurunziza-saddy/pick-library

Picks the right library for a frontend task from a curated, status-checked list, instead of hand-rolling it or installing an abandoned package. Use it when the user asks "what should I use for…", "is there a library for…", or names a package, and when you are about to build a toast, command menu, drawer, date picker, table, virtual list, drag and drop, chart, OTP input, animated number, theme switch, form validation…

相关技能