Skip to content

组件状态与命名

你在 22 组件里把微信的按钮、气泡做成了可复用组件。但组件不是"一个长相"——它会变:被碰、被按、被禁用、在加载。状态是组件的性格,命名是组件的身份证。给每个状态定齐、起规范名,设计系统才"可维护"。

状态混乱、名字乱叫,从哪来

真产品里的混乱是这样发生的:同一个组件,有的页面按下变深绿、有的按下变灰;有的禁用是灰、有的禁用是"还能点但没反应";同学问"那个浅绿按钮是啥状态",你答不上来——因为它没名字。根子在于:没人规定"组件该有哪些状态",也没人规定"状态该怎么命名"。于是每个页面各做各的,设计系统就乱了。专业解法是两件事:先给组件定一套状态集,再给每个状态起统一的规范名。状态和命名,就是设计系统的秩序。

六种状态:组件的"性格清单"

一个标准组件,通常有 6 种状态:默认(平时躺着不动)、悬停(鼠标停在上面)、按下(按下去的瞬间)、禁用(现在不能点)、加载(正在做事等结果)、聚焦(键盘/屏幕阅读器定位到它)。

状态英文什么时候出现微信例子
默认normal平时躺着不动没碰过的绿色按钮
悬停hover鼠标停在上面(桌面端)电脑微信里鼠标悬停的消息
按下pressed手指/鼠标按下去的瞬间按住"发送"那一刻变深
禁用disabled现在不能点发送框为空时的"发送"键(灰的)
加载loading正在做事、等结果刷新朋友圈时按钮转菊花
聚焦focus键盘/屏幕阅读器定位到它搜索框被 Tab 选中时的描边

关键澄清:"状态 = 颜色变化"是误区。状态远不止变色——还有禁用(能不能点)、聚焦(键盘可访问)、加载(在等什么)。颜色只是状态最显眼的表现之一,不是全部。每种状态都应承载一种明确的含义,绝不乱闪。

标准组件 6 态:normal / hover / pressed / disabled / loading / focus

命名规范:命名即规范

状态要能被团队统一调用,就得命名。命名不是"随便起个顺口的",而是规范本身——名字长什么样,决定团队怎么沟通、怎么改。约定是组件 + 变体 + 状态,用连字符串起来。

组件变体状态规范全名
btnprimarypressedbtn-primary-pressed
btnprimarynormalbtn-primary(默认态可省略)
msgbubblenormalmsg-bubble
celllistpressedcell-list-pressed

关键澄清:"命名随便,反正是内部的"是误区。命名即规范——一个 btn-primary-pressed 的名字,既告诉你是哪个组件、哪个样式、哪个状态,又让全团队、全工具、全代码都喊同一个名字。名字一旦乱,设计就散。

命名规范 = 组件 + 变体 + 状态,连字符串;默认态 normal 可省略。

状态名引用语义 Token

上一节(23)的语义 Token 回答"这个状态该用什么颜色"——状态不是凭空变色的,它引用语义 Token。看不看语法都行,先看关系:color-bg 是品牌绿,需要白色界面底色时用 color-surface,两者分得清;组件按下态的名字 btn-primary-pressed,用 color-bg-pressed 这个 Token 的颜色。

css
--color-bg: var(--color-brand-primary);  /* 背景绿 = 品牌绿 */
--color-surface: #FFFFFF;                /* 界面底色 = 白 */
--color-bg-pressed: #049A49;             /* 按下 = 更深绿 */

.btn-primary-pressed { background: var(--color-bg-pressed); } /* 按下背景 */

一句话:状态名是"指纹",Token 是"颜色档案"。把组件的 pressed 态说成"btn-primary-pressedcolor-bg-pressed 的颜色"——改名、改色各管各的。这就是设计系统"可维护"的真正含义:名字定身份,Token 定颜色,各司其职。

状态名管"身份"(谁的哪个状态),Token 管"颜色数据源"(该是什么颜色)。

微信"发送"键:从状态到命名到 Token 捋一遍

发送键六态状态环路

把微信的绿色"发送"键完整走一遍:常态是绿底白字,按下变深绿,发送框为空时灰底点不动、加载时绿底转菊花。把它从状态到命名到 Token 列成一张表,就是"发送"键的完整状态规范——你说"btn-primary-pressed 调深一点",开发改的是它引用的 color-bg-pressed 这个 Token。

状态规范名引用 Token长相
默认btn-primarycolor-bg(品牌绿)+ color-text-inverse(白字)绿底白字
按下btn-primary-pressedcolor-bg-pressed变深一点的绿
禁用btn-primary-disabledcolor-bg-disabled + color-text-disabled灰底灰字、点不动
加载btn-primary-loadingcolor-bg + 转动的菊花图标绿底 + 菊花

微信里最基本的"点一下有反应",背后就是 normal → pressed → normal 的一个状态环路;每种状态都做对了、命名规范了,整张界面才有秩序。

深度

取舍:状态要不要全做? 6 种状态不是每个组件都要做齐。hover 是桌面端专属,手机上手指没有"悬停";focus 是键盘/无障碍必需品,纯手机产品可弱化。按场景取舍:

平台 / 场景必做可选
手机 Appnormal、pressed、disabled、loadinghover(无鼠标)、focus(弱化)
桌面 Webnormal、hover、pressed、disabled、loading、focus
表单输入框focus(描边)、disabled、normalpressed
不可交互的展示组件(如头像)normal其余基本不用

铁律:先做"用户一定会碰到"的状态(normal / pressed / disabled),再按平台补 hover / focus / loading。 别给一个纯展示组件硬凑 6 个状态——那叫过度设计。

命名反模式:四种最坑的起法。

#反模式例子问题
1无规范、随手起greenBtnPressedbtn1那个按钮没说清"哪个组件 + 哪个状态",团队张冠李戴
2把颜色写进名字btn-lightgreen-pressed一换色名字就作废;颜色该交给 Token,不进名字
3状态混在组件名里pressedBtndisabledMsg状态应是后缀btn-primary-pressed),不是前缀,否则排序检索全乱
4同一状态多种叫法有人叫 active、有人叫 pressed、有人叫 down同一件事三种叫法,等于没规范

反模式共同点:让"名字"失去了语义和唯一性。命名规范的意义,就是保证全团队对同一个状态喊同一个名字。

边界:状态与命名管什么、不管什么。

  • 状态管"看起来、能不能点",不管"布局":状态是组件自身的样式变化,不改变组件的位置、大小、层级——那还是 Auto-Layout(13)和组件事。
  • 命名管"怎么称呼",不管"怎么画"btn-primary-pressed 只定义身份;它长什么样,由引用的 Token(颜色)和组件样式决定。
  • 状态要延续到代码,不只图纸:设计稿里定义了 pressed 的样式,开发代码里也要有对应的 :active / :hover 状态——否则"设计做了、代码没做",按下没反应。

误区

#误解正解
1状态 = 颜色变化状态还有禁用(能不能点)、聚焦(键盘可访问)、加载(在等什么);颜色只是最显眼的表现之一
2命名随便,反正是内部的命名即规范btn-primary-pressed 让全团队、全工具、全代码喊同一个名字
36 种状态每个组件都要做齐hover 是桌面专属、focus 是无障碍必需品,按平台取舍;纯展示组件做 normal 即可
4颜色写进名字里没毛病一换色名字就作废;颜色应交给 Token,状态名只管身份
5状态是图纸的事,开发不用管设计稿定义了 pressed/hover,代码里也要有对应状态,否则按下没反应

练习

即时题

Q1:组件状态一共有哪几种?哪一种是"键盘/无障碍"需要的?

答案normal(默认)、hover(悬停)、pressed(按下)、disabled(禁用)、loading(加载)、focus(聚焦)。focus 是键盘定位/屏幕阅读器需要的。

Q2:为什么说"状态 = 颜色变化"是误区?

答案状态不止变色,还有禁用(能不能点)、聚焦(键盘可访问)、加载(在等结果)。颜色只是状态最显眼的表现之一,不是状态本身。

Q3btn-primary-pressed 这个名字,每个部分分别代表什么?

答案btn=组件(按钮),primary=变体(主样式),pressed=状态(按下)。命名 = 组件 + 变体 + 状态,用连字符串起。

Q4(衔接题):组件状态名和 Token(23)是什么关系?

答案状态名是"身份"(谁的哪个状态),Token 是"颜色数据源"。`btn-primary-pressed` 引用 `color-bg-pressed` 这个语义 Token,改色只改 Token。

Q5(一反模式):把状态名起成 greenBtnPressed,错在哪?

答案①无规范、随手起,大小写混用;②把颜色(green)写进名字,一换色就作废;③状态放中间,检索和排序乱。应写成 `btn-primary-pressed`。

模块题 微信新增一个"点赞"按钮。请:①列出它至少需要的 3 个状态;②分别给每个状态起规范名;③说明每个状态引用了哪个语义 Token(用 23 的语言)。

参考思路 - 状态:normal(默认)、pressed(按下)、disabled(禁用,如已点过或未登录)。手机上可省 hover。 - 命名:`btn-like-normal`(或省略为 `btn-like`)、`btn-like-pressed`、`btn-like-disabled`。 - Token:normal 用 `color-bg` + `color-text-inverse`;pressed 用 `color-bg-pressed`;disabled 用 `color-bg-disabled` + `color-text-disabled`。 - 关键点:**名字定身份、Token 定颜色**,状态集 + 命名规范 + Token 三件事各司其职,按钮才"可维护"。

迷你案例(微信实战) 给微信的"发送"键做完一套"状态 + 命名 + Token"规范:

  1. 在你的微信设计文件里,找到那个绿色"发送"键组件。
  2. 给它定义状态:先做 normal / pressed / disabled 三个(手机上 hover 可省)。
  3. 给每个状态起规范名:btn-primarybtn-primary-pressedbtn-primary-disabled
  4. 为每个状态定颜色,并引用语义 Token(用 23 的语言):normal → color-bg(品牌绿);pressed → color-bg-pressed(深一点);disabled → color-bg-disabled(灰)。
  5. 验证:把"发送框"清空,让"发送"键进入 disabled 态,看它是不是变灰、点不动。
  6. 最后在心里回答:如果老板说"按下态再深一点",你要改的是名字还是 Token?——是 color-bg-pressed 这个 Token,btn-primary-pressed 的名字不用动。

做完你就懂了:组件不是"一个长相",而是一套有状态、有名字、有 Token 数据源的规范。 状态和命名,就是设计系统"可维护"的秩序——它让团队从"那个绿了吧唧的按钮"升级成"btn-primary-pressed"。

素材

  • 👉 打开交互演示:组件状态 — 同一按钮切换 normal/hover/pressed/disabled/loading/focus,对照规范名与引用的语义 Token。
  • Material Design 状态:Google 定义的标准组件状态表(hover/focus/pressed/disabled/loading),看专业系统怎么定状态集。
  • iOS HIG 状态:苹果对控件状态(enabled/disabled/selected)的规范,对照理解"状态集"怎么取舍。
  • Design Tokens(23)衔接:本节把 23 的语义 Token 接到组件状态上——状态名引用 Token,颜色交给 Token 管。
  • 后续衔接:24 组件状态与命名 → 组件库治理(把状态做全、名字统一)→ 设计系统整体规范交付。