- 前端
- CMS
【免费下载链接】wp-calypso
The JavaScript and API powered WordPress.com
@automattic/components是 wp-calypso 项目(WordPress.com 的 JavaScript 与 API 前端)内置的 React 组件库,而Button是该组件库中用于承载"点击触发动作"语义的核心控件。本文以 packages/components/src/button/README.md 为骨架,结合其 TypeScript 实现、SCSS 样式、单元测试 与 Storybook 用例,完整讲解该组件的全部 Props、按钮类型、图标按钮用法与设计准则,并说明其"已弃用(deprecated)"状态及向@wordpress/components迁移的正确姿势。
组件概览:触发动作的通用按钮,当前已标记弃用
Buttons 表达的是"用户点击或轻触后将发生什么动作"。它们用于触发任何类型的操作,也包括导航。该组件从@automattic/components包导出(见 packages/components/src/index.ts),并对外暴露Button组件与其ButtonProps类型。
需要特别注意的是:这个按钮组件已经因为"过于激进且通用的 CSS"(aggressive and generic CSS)被弃用——当它被导入时,其全局性样式会破坏许多其他按钮。因此官方建议改用@wordpress/components包中的Button组件。组件源码的 JSDoc 注释(index.tsx)也明确标注了@deprecated,Storybook 目录则归类为Deprecated/Button(见 index.stories.tsx)。
不过,由于历史原因该组件在仓库中仍有大量使用点(例如 client/my-sites/activity/filterbar/index.jsx 等文件仍在import { Button, Gridicon } from '@automattic/components'),理解它的用法、实现原理与弃用原因,对阅读旧代码、做增量改造仍然非常必要。
快速上手:基本用法
从@automattic/components导入Button与Gridicon(后者用于图标按钮),即可使用:
import { Button, Gridicon } from '@automattic/components'; export default function RockOnButton() { return ( <Button compact primary> You rock! </Button> ); }上面的示例同时叠加了compact(紧凑尺寸)与primary(主操作视觉强调)两个修饰属性,这也是该组件最常见的组合用法。
Props 全解:7 个官方 Props 与源码中的隐藏第 8 个
原文档给出了完整的 Props 表格,这也是使用本组件的核心参考:
| Name | Type | Default | Description |
|---|---|---|---|
plain | bool | false | Renders a button with no user-agent styles |
compact | bool | false | Decreases the size of the button |
primary | bool | false | Provides extra visual weight and identifies the primary action in a set of buttons |
borderless | bool | false | Renders a button without borders |
scary | bool | false | Indicates a dangerous or potentially negative action |
busy | bool | false | Indicates activity while a background action is being performed |
href | string | null | If provided, rendersainstead ofbutton |
从源码的OwnProps接口(index.tsx)可以看到,实际实现还额外支持一个transparent布尔属性(README 表格未列出),用于渲染"背景透明、随 CSS 变量着色的描边按钮"。此外组件还透传className。
Props 如何映射为样式类
所有布尔修饰属性最终通过clsx拼装成 CSS 类名(index.tsx):
plain为真时,输出类名button-plain(不附带任何修饰类);- 否则输出基础类
button,并按属性追加is-compact、is-primary、is-scary、is-busy、is-borderless、is-transparent。
测试 test/index.js 专门验证了这一映射:<Button scary primary borderless compact />会同时带上is-compact、is-primary、is-scary、is-borderless四个类;而不带任何修饰时仅保留button类。
按钮类型与设计语义
原文档将按钮划分为七种类型,每种都有明确的设计语义:
- Primary(主按钮):用于在任何体验中突出最重要的操作。注意,一个区块或一屏内不要超过一个主按钮,以免给用户造成压迫感。
- Secondary(次按钮):界面中使用最频繁的类型。只有当某个按钮需要更强或更弱的视觉权重时,才换用其他样式。
- Button with icon(带图标的按钮):当文字不足以表达时,用图标辅助传达按钮功能。
- Scary(危险按钮):用于会删除客户数据、或事后难以恢复的操作。破坏性按钮应在动作完成前先触发确认对话框。要谨慎使用这类按钮,因为它们可能给用户带来压力。
- Borderless(无边框按钮):用于较不重要或较少使用的操作,因为它们的视觉存在感更低。
- Busy(忙碌按钮):当按钮已被按下、且关联动作正在执行时使用。
- Plain(纯样式按钮):当需要"button-as-div"时使用——重置按钮的所有样式,随后由使用方自行增强。例如当你需要某元素行为上像个按钮、但外观上不像按钮时,这是很好的选择。
源码中的样式语义佐证
这些设计语义在 style.scss 中都有对应实现:
- 基础样式(
.button):1px 实线边框、2px 圆角、padding: 8px 14px、line-height: 22px,颜色通过 CSS 变量取色(--color-surface、--color-neutral-70、--color-neutral-10等),并针对.rtl容器切换阿拉伯语字体族(见 style.scss)。 - 主按钮(
.button.is-primary):使用--color-accent强调色作背景,hover/focus 时加深为--color-accent-60(style.scss)。 - 危险按钮(
.button.is-scary):文字颜色切换为错误色--color-error;与primary叠加时(.button.is-primary.is-scary)背景直接使用错误色(style.scss)。 - 忙碌按钮(
.button.is-busy):设置pointer-events: none禁用交互,并通过button__busy-animation关键帧动画(3000ms 无限线性循环、background-position从 240px 平移到 0)产生流动条纹效果(style.scss 与 style.scss)。主按钮、危险按钮的 busy 状态分别使用各自色系的条纹渐变。 - 无边框按钮(
.button.is-borderless):去掉边框与背景、左右内边距归零,hover/focus 仅加深文字颜色(style.scss)。 - 纯样式按钮(
.button-plain):appearance: none、透明背景、继承文本颜色与字号、无内边距(style.scss)。 - 透明按钮(
.button.is-transparent):背景透明,边框与文字颜色取--transparent-button-text-color(默认回退到currentcolor),hover 时切换为--transparent-button-text-color-hover(默认--color-accent),并以 flex 居中内容(style.scss)。
另外,基础.button还内置了[disabled]/:disabled/.disabled三种禁用态样式(文字变灰、光标default),以及.accessible-focus容器下的焦点环样式(box-shadow: 0 0 0 2px var(--color-primary-light)),无障碍设计同样有所覆盖(style.scss)。
图标按钮:与 Gridicon 组合使用
当文字不足以传达含义时,可以在按钮内插入 Gridicon 图标。约定是图标显示在文字左侧(唯一的例外是external图标放在文字右侧)。文字需要包裹在span或其他元素中以便控制间距。也可以做纯图标按钮(无文字),但应谨慎使用,因为可能降低可读性:
import { Button, Gridicon } from '@automattic/components'; export default function RockOnButton() { return ( <Button> <Gridicon icon="trash" /> <span>Button with icon</span> </Button> ); }样式层面对 Gridicon 做了专门对齐:默认width/height: 18px、top: 4px,非末位图标带margin-right: 4px(style.scss);borderless场景下图标放大到 24px;compact场景还会对gridicons-plus-small、gridicons-arrow-left/right等特殊图标做微调(如箭头图标因 SVG 边界盒偏低需上移 1px,见 style.scss 与 style.scss)。
组件库的文档示例 docs/example.jsx 完整展示了各类图标按钮组合:普通/危险/主按钮/主危险按钮分别搭配heart、plugins、globe、pencil、camera、time、user-circle、cart等图标,以及 borderless 场景下的cross(Remove)、trash(Trash)、link-break(Disconnect)等典型管理操作。
源码级实现剖析
渲染逻辑:button与a的自动切换
UnforwardedButton 是核心渲染函数,其关键行为如下:
- 通过
isAnchor判断:只要传入了href,就渲染<a>,否则渲染<button>。 - 渲染
<button>时,cleanButtonProps会把type默认设为"button"(避免表单内按钮意外触发表单提交),并剥离href、target、rel等不该出现在按钮上的属性(index.tsx)。 - 渲染
<a>时,cleanAnchorProps剥离type等按钮专属属性;并且当设置了target(如_blank)时,会自动将rel中已有的noopener/noreferrer去重后追加noopener noreferrer,以阻止外部链接的 referrer 泄漏(index.tsx 与 index.tsx)。 - 组件通过
forwardRef暴露,ref 同时支持HTMLButtonElement | HTMLAnchorElement。
上述行为在 test/index.js 中被系统化验证:
href存在时渲染为链接,且type属性会被忽略(第 52-63 行);- 指定
target="_blank"时自动补全rel="noopener noreferrer"(第 65-83 行); - 未传
href时渲染为<button>,默认带type="button",并且不会把target/rel误加到按钮上(第 86-115 行); disabled属性透传,按钮被禁用(第 35-39 行);- 子元素(如 Gridicon)正常渲染并被包含在按钮内(第 41-49 行)。
样式系统:CSS 变量驱动的主题化
整个按钮样式完全基于 CSS 自定义属性(--color-surface、--color-neutral-*、--color-accent、--color-error等)取色,因此能随主题(如暗色模式)自动变化,这也是它当年在 Calypso 各处被广泛复用的原因。样式文件末尾还保留了已弃用的.button.is-link样式(透明、无边框、color: var(--color-link)、font-size: inherit,见 style.scss),供旧代码平滑过渡。
Storybook 用例一览
index.stories.tsx 提供了 9 个可直接预览的故事:Default、Compact、Busy、Scary、Borderless、Disabled、Link(带href与target="_blank")、Plain、Transparent(在黑色背景上演示--transparent-button-text-color与 hover 颜色的自定义,见第 91-108 行)。这些故事是快速对比各修饰属性视觉差异的最佳入口。
使用规范与设计准则
原文档给出的通用准则(General guidelines)值得原样保留并作为 UI 文案规范:
- 使用清晰、准确的标签(Use clear and accurate labels)。
- 使用句子式大小写(sentence-style capitalization)。
- 以强烈、简洁、可行动的动词开头(Lead with strong, concise, and actionable verbs)。
- 当用户确认某个动作时,使用具体标签,如Save或Trash,而不是OK和Cancel。
- 对最重要的操作进行优先级排序。过多的行动号召会造成混乱,让用户不确定下一步该做什么。
迁移建议:为什么以及如何改用 @wordpress/components
弃用的根本原因写在 README 第一段:该按钮引入的是"激进且通用(aggressive and generic)"的 CSS,一旦被导入就可能污染并破坏页面上的其他按钮(例如其全局选择器会意外命中其他元素)。因此在wp-calypso 后续版本中,新代码不应再使用@automattic/components的Button,而应改用@wordpress/components包中同名的Button组件(其文档位于 WordPress Gutenberg 组件文档站,此处不再列出外部链接)。
迁移时的大致思路:
- 将
import { Button, Gridicon } from '@automattic/components'中的Button替换为import { Button } from '@wordpress/components'(Gridicon仍可保留,用于图标按钮)。 - 属性映射:
primary→variant="primary"、compact→ 视需求用isSmall/isCompact等价物,scary→isDestructive,busy→isBusy,borderless→variant="tertiary"或variant="link",href在@wordpress/components的 Button 中同样支持渲染为链接。 - 视觉验收:由于两者样式体系不同(Gutenberg 组件基于自己的 design tokens),迁移后需要在对应页面做一次视觉回归。
关联组件
原文档末尾列出了三个关联组件,它们与按钮配合使用可以覆盖更复杂的交互场景(当前仓库中对应的实现位于client/components下):
- ButtonGroup(按钮组):需要把多个按钮分组排列时使用,参考 client/components/button-group。
- SplitButton(分裂按钮):需要为按钮附加一个次级 popover 菜单时使用,参考 client/components/split-button。
- SpinnerButton(带加载指示的按钮):需要在按钮上展示加载转圈时使用,参考 client/components/spinner-button。
综上所述,@automattic/components的Button虽已被官方标记弃用,但它作为 wp-calypso 历史 UI 体系的一部分,其 Props 语义、样式分层与实现思路(button/link 双形态、CSS 变量取色、修饰类映射)至今仍有学习与迁移参考价值。阅读旧代码遇到@automattic/components的 Button 时,可按本文的 Props 表快速理解其视觉意图,并按迁移指南逐步替换为新组件。
- 前端
- CMS
【免费下载链接】wp-calypso
The JavaScript and API powered WordPress.com
相关推荐
wp-calypso CardHeading 组件完全指南:用法、Props 与源码实现剖析
wp calypso CardHeading 组件完全指南:用法、Props 与源码实现剖析 导读 CardHeading 是 wp calypso(WordP
前端CMS@automattic/components v5.0.0 升级指南:wp-calypso 组件库的破坏性变更、迁移映射与源码解读
@automattic/components v5.0.0 升级指南:wp calypso 组件库的破坏性变更、迁移映射与源码解读 @automattic/co
前端CMSwp-calypso Spotlight 组件实战指南:用法、Props 与 JITM 集成源码解析
wp calypso Spotlight 组件实战指南:用法、Props 与 JITM 集成源码解析 Spotlight 是 wp calypso(WordPr
前端CMS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考