把基础规范落到具体控件上:每个组件长什么样、有哪些状态、多大。这里是 packages/ui 的设计输入。清单里的控件已经全部实现,各期清单里逐项写了做到哪一步;最后一期是后来补的、最初的清单里没有的控件。
怎么读#
| 文档 | 覆盖的组件 |
|---|---|
| 按钮 | 按钮、图标按钮、按钮组、工具栏 |
| 导航 | 侧轨(含二级)、主行动块、顶栏与全屏菜单、页签、分页、胶囊导航器、进度短横、头像切换、面包屑、页头、步骤条、页内目录、回到顶部 |
| 卡片 | 面板、折叠面板、滚动区、媒体卡(含播放钮)、媒体轮播、图片查看、物品格、列表行 |
| 表单 | 字段、输入框与多行文本、验证码输入、下拉、组合框、标签输入、复选、单选、分段选择、开关、步进器、滑块、日期选择、文件上传 |
| 反馈 | 进度、提示条、轻提示、加载(加载页、开屏页、骨架、行内加载)、空状态、完成横幅 |
| 浮层 | 弹窗、抽屉、下拉菜单、右键菜单、展开条、文字提示、气泡卡片、悬浮卡 |
| 数据展示 | 标签与徽章、数据行带(含小型面积图)、统计块(含滚动数字)、头像、表格(含行展开)、时间线、排期、语义着色词 |
每篇的结构:用途 → 图解 → 规格表 → 状态 → 行为与无障碍 → 宜 / 忌 → 来源。
规格表里的数值分两种:
- 颜色与状态变化多数是实测(官网)或社区(游戏界面);
- 尺寸是把官网的流式
rem换算到 16px 基准后的建议值,实现时可以微调。
通用约定#
尺寸#
三档,全库统一:
| 档 | 控件高度 | 字号 | 水平内边距 | 用在哪 |
|---|---|---|---|---|
sm |
32px | text-sm |
12px | 工具栏、表格内、紧凑面板 |
md |
40px | text-base |
16px | 默认 |
lg |
56px | text-lg |
24px | 首屏的主要行动、移动端的主要按钮 |
官网通用按钮是 4.5rem 高,在 1920 稿上是 54px、在 1440 视口上约 40px,所以 md 取 40、lg 取 56。
触屏上任何可点击元素的点击区域不小于 40 × 40px。
状态#
每个交互组件按需实现:
| 状态 | 表达方式 |
|---|---|
| 默认 | — |
| 悬停 | 换底色。不上浮、不放大、不加阴影。只在有指针的设备上生效 |
| 按下 | 更深一档的底色。不缩小 |
| 聚焦 | 2px focus 色的环,与元素间隔 2px。仅键盘聚焦时出现(:focus-visible) |
| 选中 / 当前 | 填充反转、边条、角括号、选中环,按组件选一种 |
| 禁用 | 降低对比但保持可读;不响应悬停 |
| 加载 | 保持尺寸稳定,不让布局跳动 |
| 错误 | 语义色 + 图标 + 文字说明,三者齐全 |
命名#
- 变体用语义名:
action、control、light、danger。不用颜色名。 - 尺寸用
sm/md/lg。 - 形状是变体的一部分,不单独暴露成属性:不提供
rounded、cut这类让使用者随意组合的开关。 - 色调用
tone:neutral、info、success、warning、danger。
主题#
所有组件只使用 theme.css 里的语义令牌(surface、ink、line、action、control…),因此自动适配亮 / 暗主题与主题色接管。组件内不出现十六进制色值。
几条实现时定下的细则:
- 随主题翻转的颜色一律用语义令牌。 只有"本来就是为某一种底色设计"的填充才直接用
neutral-*、在两个主题下保持不变,清单见 色彩 的"哪些颜色有意不随主题变"。 - 压在反转块上的强调记号用
accent-ink-inverse,不直接用action。surface-inverse在暗色主题下是近白,黄色压在上面看不见。已选的复选与单选、开启的开关、反转图标钮的图标都是这一条。 - 反转块里还要放别的控件时,把它做成反转主题(
data-theme="inverse"),里面照常用surface、ink、accent-ink。面板的标题带、表格的表头带、完成横幅都是。见 色彩。 - 压在页面表面上的强调记号用
accent-ink。 行动色在亮色表面上同样看不见(必填标记)。 - 悬停底用
bg-ink/5,不用surface-sunken。 后者在暗色主题下是纯黑,悬停会变暗而选中变亮,方向相反(页签、列表行)。
链接与路由#
能当链接用的控件(按钮、列表行、媒体卡、物品格、面包屑项、菜单项、展开条的项,以及侧轨项、全屏菜单项、主行动块)有两种写法:
| 写法 | 渲染成什么 |
|---|---|
href="/archive" |
原生的 <a> |
render={<Link to="/archive" />} |
你给的那个元素——路由库的链接组件 |
<Button render={<Link to="/archive" />}>查看档案</Button>- 控件算好的类名、状态属性(
aria-current、data-variant…)和事件会合并到那个元素上:类名拼在一起,事件两边都触发,其余属性以那个元素自己写的为准。 - 传了
render就按链接处理,哪怕没有href——地址在那个元素自己手里。 - 这个写法和浮层的触发元素是同一个(都是 Base UI 的
render),所以库里没有asChild。 - 禁用时有一处差别。
href形态下,禁用的链接被去掉地址,焦点也到不了它。render形态下地址去不掉,所以它仍然能被聚焦;控件给它标上aria-disabled并拦下点击(路由库的链接组件看到点击被拦下就不会跳转)。
无障碍#
- 用原生元素(
button、a、input);浮层这类原生元素做不好的,用无障碍基元 Base UI。 - 纯图标控件必须有可访问名称。
- 状态不只靠颜色表达。
- 装饰元素(竖条、括号、纹理、巨字)对辅助技术隐藏。
- 动效遵守"减少动态效果"。
clip-path切角不能裁掉焦点环,做法见 切角与斜楔。
组件清单与建议顺序#
按"先把语言立住,再铺开"的顺序。每一期做完都应该能搭出一类完整的页面。
第一期:立住语言(已实现)#
能搭出一个官网气质的内容页。源码在 packages/ui/src/components,在仓库根目录 pnpm dev 可以在 Storybook 里并排看亮暗两套。
| 组件 | 规范 | 要点 |
|---|---|---|
| Button | 按钮 | 4px 圆角,图标和文字之间一条细竖线,悬停只换色;照官网云游戏页的顶栏 |
| IconButton | 按钮 | 圆形与方形两种 |
| Tag / TagPair / Badge | 数据展示 | 名值对、类型标签、日期块、通知角标 |
| SectionTitle | 分节标题 | 标准、色带、竖排三种形态,外加一个简化版 |
| Tabs | 导航 | 激活时文字让位给箭头;另有胶囊、楔形两种变体 |
| Panel | 卡片 | 直角、1px 线、无阴影 |
这一期当时没做、后来补上的:按钮组、列表行、媒体卡、物品格、胶囊族的筛选 / 资源 / 倒计时徽章、增益签、日期块的小红角、页签的 wedge 变体。
第二期:表单与反馈#
能搭出设置页、表单页、列表页。在 Storybook 的"示例 / 设置页"和"示例 / 列表页"里可以看到用它们搭出来的页面。
| 组件 | 规范 | 状态 |
|---|---|---|
| Field | 表单 | 已实现 |
| Input / Textarea | 表单 | 已实现(凹陷与描边两种) |
| Checkbox / Radio / Switch | 表单 | 已实现 |
| FilterChip | 数据展示 | 已实现 |
| Progress / ProgressRing / Spinner | 反馈 | 已实现 |
| Alert | 反馈 | 已实现 |
| Select | 表单 | 已实现(和第三期的浮层一起做的) |
| Combobox(组合框) | 表单 | 已实现(含多选与分组) |
| Toast | 反馈 | 已实现(同上) |
| Stepper、双标签开关 | 表单 | 已实现 |
| 菱形表单符号(方案 B) | 表单 | 已实现(全局开关 data-choice="diamond") |
Select 的面板和 Toast 的容器都是浮层,需要定位与焦点管理,和第三期的浮层共用同一套无障碍基元(Base UI)。
第三期:浮层与导航#
能搭出完整的应用外壳。在 Storybook 的"示例 / 调度台"里可以看到:宽屏是侧轨,窄屏换成顶栏和全屏菜单。
| 组件 | 规范 | 状态 |
|---|---|---|
| Dialog | 浮层 | 已实现(含两处可选装饰) |
| Drawer | 浮层 | 已实现 |
| Tooltip | 浮层 | 已实现 |
| DropdownMenu | 浮层 | 已实现(含复选项与一层子菜单) |
| Popover(气泡卡片) | 浮层 | 已实现 |
| FlyoutBar(展开条) | 浮层 | 已实现 |
| Select / Toast | 表单、反馈 | 已实现(Select 含多选) |
| SideRail(侧轨) | 导航 | 已实现(展开与收起两种形态,含分组) |
| TopBar / NavMenu(顶栏与全屏菜单) | 导航 | 已实现 |
| NavAction(主行动块) | 导航 | 已实现 |
| Pagination / Navigator / DashIndicator | 导航 | 已实现 |
| Breadcrumb | 导航 | 已实现 |
第四期:数据与游戏风格#
能搭出工具站、数据面板、游戏风格的界面。
| 组件 | 规范 | 状态 |
|---|---|---|
| Table | 数据展示 | 已实现 |
| DataRow | 数据展示 | 已实现(DataRowList + DataRow) |
| Sparkline(行内的小型面积图) | 数据展示 | 已实现 |
| Stat | 数据展示 | 已实现 |
| RollingNumber(滚动数字) | 数据展示 | 已实现 |
| ResourceChip / Countdown | 数据展示 | 已实现 |
| List / ListRow | 卡片 | 已实现(含深色行带 band) |
| Timeline | 数据展示 | 已实现 |
| ItemSlot | 卡片 | 已实现(含方向键导航的矩阵 ItemGrid) |
| EmptyState / Skeleton | 反馈 | 已实现 |
| Loader(加载页) | 反馈 | 已实现 |
| SplashScreen(开屏页:官网首次载入的那一页) | 反馈 | 已实现 |
| CompletionBanner、列表行的完成态 | 反馈 | 已实现 |
| Term(富文本的语义着色词) | 数据展示 | 已实现 |
第五期:母题组件(已实现)#
把 母题 做成可复用的装饰组件:
| 组件 | 规范 |
|---|---|
| GhostText | 镂空字与微文字 |
| Hatch、HazardStripe、RegistrationStrip | 斜纹与色条 |
| CornerBrackets | 括号与标记 |
| Viewfinder、TickRing、ScrollHint、RecIndicator、Kbd | 测绘叠层 |
| Marquee | 动效 |
| Texture(点阵、工程网格、等高线) | 网格、等高线、点阵 |
| BracketTitle | 括号与标记 |
切角、斜楔、角括号、镂空字、斜纹、警示条纹、三种底纹同时是 utilities.css 里的工具类;切角与斜楔只有工具类,没有组件——"形状是变体的一部分",谁能切角由控件自己决定(目前是楔形页签和物品格的 NEW 签)。
这些放在最后,是因为它们最容易被滥用。先有扎实的基础组件,再提供装饰。
第六期:清单之外补的(已实现)#
前五期做完之后补的。它们在最初的清单里没有——有的是官网上看得到、当时没列进来的(头像切换、媒体轮播、排期、播放钮),有的是搭真实页面时发现缺的。每一个都是先在对应的文档里写了规格、标了来源等级,再做的。表里从播放钮往下的五行是第二批;从行展开往下的五行是第三批——官网上没有它们的原型,是从库里已有的画法延伸出来的,每一行写了借的是哪一处;最后五行是第四批,同样是延伸出来的。
| 组件 | 规范 | 依据 |
|---|---|---|
| ContextMenu(右键菜单) | 浮层 | 推断:下拉菜单换一种触发方式 |
| Combobox 的远程检索与加载态 | 表单 | 推断 |
| Table 的表头吸顶 | 数据展示 | 推断 |
| Accordion(折叠面板) | 卡片 | 推断 |
| Slider(滑块,含范围) | 表单 | 推断 |
| Avatar(头像) | 数据展示 | 实测:官网的圆形头像与选中环 |
| AvatarSwitcher(头像切换) | 导航 | 观察:官网"干员情报"左侧那一列 |
反转块的局部主题 data-theme="inverse" |
色彩 | 实现时定的机制,不是新的画法 |
| SideRailSub(侧轨的二级) | 导航 | 推断 |
| Carousel(媒体轮播) | 卡片 | 观察:官网"玩法介绍" |
| Calendar / DatePicker(月历与日期选择) | 表单 | 推断 |
| Schedule(排期) | 数据展示 | 观察:官网的版本日历 |
PlayButton / PlayMark(播放钮),媒体卡的 video |
卡片 | 实测:官网影像资料区的黄色小方块;摆在哪个角是推断 |
| BackToTop(回到顶部) | 导航 | 推断;悬停变信号黄取自分页条翻页钮的实测 |
| SegmentedControl(分段选择) | 表单 | 推断:输入框的凹陷底 + 选中的填充反转 |
| Steps(步骤条) | 导航 | 观察:宣传物料里"黑色章头 + 黄色重点"的步骤;三态沿用时间线的节点 |
Calendar 的 range、DateRangePicker(日期范围) |
表单 | 推断:两端是选中格的填充反转,中间是墨色的浅带 |
| Table 的行展开、TableExpander | 数据展示 | 推断:排序用的小三角转 90°,明细区是凹陷的底 |
| Toolbar(工具栏) | 按钮 | 推断:方形图标钮和"开关类工具"的墨底黄记号是实测,收成一条带子是延伸 |
| TagInput(标签输入) | 表单 | 推断:输入框的外框 + 组合框多选的直角小块 |
| FileUpload / FileItem(文件上传) | 表单 | 推断:空状态的虚线框、凹陷的底、取景角、直角标签、进度条 |
| Toc(页内目录) | 导航 | 推断:侧轨二级的引线,当前项那一段换成粗条 |
| PageHeader / PageHeaderBack(页头) | 导航 | 推断:返回方块是 back 按钮的深灰斜纹底(实测)收成的图标形态,微文字行同分节标题 |
| ScrollArea(滚动区) | 卡片 | 推断:滚动条是页内目录的引线——细线上一段粗条 |
| OtpInput(验证码输入) | 表单 | 推断:把输入框切成一格一位 |
| HoverCard(悬浮卡) | 浮层 | 推断:气泡卡片的面板,换成悬停触发 |
| ImageViewer(图片查看) | 卡片 | 推断:媒体卡的缩略图 + 弹窗的深色标题带 + 轮播的翻页圆钮 + 取景角 |
不做什么#
- 不做"万能卡片"。 这套语言里的层次靠底色和线,不靠卡片嵌套。
- 不提供发光、玻璃拟态、霓虹描边的变体。
- 不内置官方素材:图标、Logo、立绘、字体都不进库。唯一的例外是单独成一类的 Game 实机风格:它走独立入口,带着官方图片,这一页的约定不适用于它。
- 不做滚动劫持和整页缩放。 那是展示站的手法,由使用方在页面层决定。
- 不把游戏术语写进组件名。 叫
ItemSlot不叫OperatorCard;业务组件由使用方组合。
参照#
社区组件库 ReEnd-Components 已经实现了 75 个以上的组件,它的清单是很好的查漏依据。和它的主要差异:
| ReEnd | 本规范 | |
|---|---|---|
| 默认主题 | 暗色 | 亮色,暗色可切 |
| 主黄 | #FFD429 |
#FFFA00 |
| 气质 | 战术 HUD | 工业编辑 |
| 样式方案 | Tailwind v3 预设 | Tailwind v4 @theme |
| 表单符号 | 菱形 | 方形为默认,菱形可选 |