提供用于 WordPress 设计系统的 React UI 组件的包,构建于可主题化的设计令牌之上。
虽然范围与 @wordpress/components 类似,但有几个关键区别:
@wordpress/components作为一组用于 WordPress 界面的不相关 UI 元素自然发展而来。相比之下,此包是设计系统的实现,保证组件之间面向用户和开发者的一致性。- 与
@wordpress/components不同,此包不会打包为可通过window.wp全局对象使用的 WordPress 脚本,而是作为 npm 包分发,并遵循 语义化版本控制 来发布变更。
@wordpress/theme、@wordpress/ui 和 @wordpress/icons 构成了设计系统的基础层。更高层级的组合包(包括 @wordpress/dataviews 和 @wordpress/admin-ui)基于这些基础构建常见解决方案。如果你正在查看 Gutenberg 检出副本,请参阅版本匹配的 设计系统介绍;如果在 monorepo 之外阅读此包,请参阅 Gutenberg trunk 上的最新版本。
此包包含许多常见 UI 组件,但等效组件仍可能位于 @wordpress/components 中。有关当前逐组件的指南,包括现有 @wordpress/components 组件何时仍是推荐选择,如果你正在查看 Gutenberg 检出副本,请参阅版本匹配的 use-recommended-components 规则文档;如果在 monorepo 之外阅读此包,请参阅 Gutenberg trunk 上的最新版本。
这是 @wordpress/theme 包的配套包,提供:
- 设计令牌:用于颜色、间距、排版等的全面设计令牌系统
- 主题系统:灵活的主题提供器,用于跨应用保持一致的主题
安装
使用 NPM 安装:
npm install @wordpress/ui
设置
作为设计系统的实现和 @wordpress/theme 包的配套包,这些组件依赖于主题包定义的 CSS 自定义属性。需要设置的内容取决于你是否面向 WordPress 环境构建,以及希望使用多少主题功能。
在标准 WordPress 编辑器界面中
在标准 WordPress 编辑器界面(例如文章编辑器或站点编辑器)中,样式表、隔离样式和布局样式由 Gutenberg 集中管理。你无需自行添加任何设置——并且应避免在此共享环境中这样做,以防止冲突。
其他地方
这些组件自带所有 CSS 自定义属性的内置回退值,因此无需任何主题设置即可开箱即用。如需完整主题功能,建议安装并加载设计令牌样式表:
npm install @wordpress/theme
import '@wordpress/theme/design-tokens.css';
此样式表是通用的,没有单独的 RTL 版本。
为了确保通过 portal 渲染的弹出层正确显示,请将这些隔离样式添加到你的应用的布局根元素:
.root {
isolation: isolate;
}
为了支持背景遮罩等浮层元素,使其即使在滚动时也能正确覆盖整个浏览器视口,请将以下样式添加到全局样式中:
body {
position: relative;
}
此包中的组件在定义样式时使用 CSS 级联层,这可能与某些使用裸元素选择器应用样式的应用程序发生冲突(例如 input { border-color: #aaa; })。如果可能,应避免这类裸元素选择器样式,尽可能优先使用 CSS 类。
如果你需要相对于自己的 CSS 级联层自定义级联层顺序,组件样式被限定在 wp-ui 层下,你可以在定义自己的层顺序时使用该层:
@layer wp-ui, example-app;
与 @wordpress/components 混合使用
如果你的应用将 @wordpress/ui 与 @wordpress/components 浮层搭配使用,并直接打包这两个包(即不依赖 WordPress 脚本加载器公开的 window.wp.components 全局对象),请从一个长期存在的根组件中调用一次 useEnableWpCompatOverlaySlot():
import { useEnableWpCompatOverlaySlot } from '@wordpress/ui';
function App() {
useEnableWpCompatOverlaySlot();
return <YourApp />;
}
这会使应用加入共享的 body 级浮层容器,从而使 @wordpress/ui 浮层可靠地堆叠在 @wordpress/components 浮层之上。此加入操作是单向且幂等的。在标准 WordPress 编辑器界面中不需要这样做,因为插槽会基于 window.wp.components 自动启用。
用法
组件名称
组件名称描述组件是什么,并使用修饰符说明其外观或用途。IconButton 是显示图标的按钮。ButtonLink 是样式为按钮的链接。Dialog.CloseIconButton、Drawer.CloseIconButton 和 Notice.CloseIconButton 提供用于关闭或消除操作的图标按钮。
复合组件将相关部分归入同一个名称下。例如,ButtonLink.Icon 在 ButtonLink 内渲染图标,而 Menu.LinkItem 是菜单内的链接项。有关贡献者指南,请参阅 组件命名。
基本组件用法
import { Stack } from '@wordpress/ui';
function MyComponent() {
return (
<Stack gap="sm">
<div>Item 1</div>
<div>Item 2</div>
</Stack>
);
}
核心设计原则
设计系统中的所有组件都遵循一致的模式,以实现最大灵活性和开发者体验:
自定义渲染
每个组件都支持 render 属性,以完全控制底层 HTML 元素:
import { Stack } from '@wordpress/ui';
function MyComponent() {
// 将 Stack 渲染为 <section /> 而不是默认的 <div />
return <Stack render={ <section /> }>{ /* ... */ }</Stack>;
}
Ref 转发
所有组件都会将 ref 转发到底层 DOM 元素:
import { useRef } from '@wordpress/element';
import { Stack } from '@wordpress/ui';
function MyComponent() {
const stackRef = useRef< HTMLDivElement >( null );
return <Stack ref={ stackRef }>{ /* ... */ }</Stack>;
}
自动合并 className
组件会将提供的 className 属性与其内部样式合并:
import { Stack } from '@wordpress/ui';
function MyComponent() {
// 你的自定义 CSS className 会与组件样式合并
return <Stack className="my-custom-class">{ /* ... */ }</Stack>;
}
受控与非受控模式
管理内部状态(例如打开/关闭、选定值等)的交互式组件遵循一致的属性命名约定,支持受控和非受控两种用法。
属性命名模式
对于给定状态 x,约定如下:
| 属性 | 用途 |
|---|---|
defaultX | 在非受控模式下设置初始值。组件会在内部管理后续状态变更。 |
x | 在受控模式下设置当前值。使用方负责响应变更更新值。 |
onXChange | 状态变更时调用的回调。接收新值作为第一个参数。在受控和非受控模式下均可使用。 |
例如,具有打开/关闭状态的组件将公开:
defaultOpen— 初始打开状态(非受控)open— 当前打开状态(受控)onOpenChange— 打开状态变更时调用
而具有可选值的组件将公开:
defaultValue— 初始值(非受控)value— 当前值(受控)onValueChange— 值变更时调用
非受控用法
在非受控模式下,组件自行管理自身状态。使用 defaultX 设置初始值,并可选使用 onXChange 响应变化:
import { Tabs } from '@wordpress/ui';
function MyTabs() {
return (
<Tabs.Root
defaultValue="tab1"
onValueChange={ ( value ) => console.log( value ) }
>
<Tabs.List>
<Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
<Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="tab1">Content 1</Tabs.Panel>
<Tabs.Panel value="tab2">Content 2</Tabs.Panel>
</Tabs.Root>
);
}
受控用法
在受控模式下,使用方拥有状态,并通过 x 传入。状态变化通过 onXChange 处理:
import { useState } from '@wordpress/element';
import { CollapsibleCard } from '@wordpress/ui';
function MyCard() {
const [ isOpen, setIsOpen ] = useState( false );
return (
<CollapsibleCard.Root open={ isOpen } onOpenChange={ setIsOpen }>
<CollapsibleCard.Header>Details</CollapsibleCard.Header>
<CollapsibleCard.Content>
Collapsible content here.
</CollapsibleCard.Content>
</CollapsibleCard.Root>
);
}
当同时提供 x 和 defaultX 时,x 优先,组件表现为受控模式。当二者均未提供时,组件使用自身内部默认值(通常通过 defaultX prop 上的 @default JSDoc 标签说明)。
与原生 onChange 的区别
onXChange 回调不同于原生 DOM onChange 事件处理器。原生 onChange 会触发绑定到特定 DOM 元素的 React.ChangeEvent,而 onXChange 直接提供新的值——这更易于使用,并且在所有组件(包括复合组件和非表单组件)中保持一致。
包装原生表单元素的组件可能仍会支持原生事件处理器(如 onChange、onInput)以实现互操作,但在此包中推荐使用 onXChange。
有关在新组件中实现此模式的指南,请参阅 受控和非受控属性。
为这个包做贡献
这是一个属于 Gutenberg 项目的独立包。该项目以 monorepo 形式组织。它由多个自包含的软件包组成,每个包都有特定用途。此 monorepo 中的包会发布到 npm,并被 WordPress 以及其他软件项目使用。
要了解更多关于为这个包或整个 Gutenberg 做贡献的信息,请阅读项目的主要 贡献者指南。