@wordpress/ui 是一个实验性的 React UI 组件包,基于 WordPress 设计系统构建,提供主题化设计令牌支持。它强调组件间的用户和开发者一致性,与 @wordpress/components 相比,它更注重设计系统实现,且仅通过 npm 分发。
import { Stack } from '@wordpress/ui';
function MyComponent() {
return (
<Stack gap="sm">
<div>Item 1</div>
<div>Item 2</div>
</Stack>
);
}A package that provides React UI components for the WordPress Design System, built on themeable design tokens.
While similar in scope to @wordpress/components, there are a few key differences:
@wordpress/components grew organically as a collection of unrelated UI elements for WordPress screens. In contrast, this package is an implementation of a design system that guarantees user- and developer-facing cohesion between components.@wordpress/components, this package is not bundled as a WordPress script available on the window.wp global and is instead distributed as an npm package that follows semantic versioning for release changes.This is a companion to the @wordpress/theme package that provides:
Install using NPM:
npm install @wordpress/ui
As an implementation of the design system and companion to the @wordpress/theme package, these components depend on CSS custom properties defined by the theme package. What you need to set up depends on whether you’re building for a WordPress context, and how much of the theming features you want to use.
In standard WordPress editor screens (such as the post editor or the site editor), stylesheets, isolation styles, and layout styles are managed centrally by Gutenberg. You don’t need to add any setup yourself — and you should avoid doing so in this shared context to prevent conflicts.
The components ship with built-in fallback values for all CSS custom properties, so they work out of the box without any theme setup. For full theming capabilities, it’s recommended that you install and load the design tokens stylesheet:
npm install @wordpress/theme
import '@wordpress/theme/design-tokens.css';
This stylesheet is universal and does not have a separate RTL version.
Also, to ensure that portaled popovers appear correctly, add these isolation styles to your application’s layout root element:
.root {
isolation: isolate;
}
Finally, in order to support overlay elements such as backdrops to correctly cover the whole browser viewport even when scrolled, add the following style to your global styles:
body {
position: relative;
}
import { Stack } from '@wordpress/ui';
function MyComponent() {
return (
<Stack gap="sm">
<div>Item 1</div>
<div>Item 2</div>
</Stack>
);
}
All components in the design system follow consistent patterns for maximum flexibility and developer experience:
Every component supports the render prop for complete control over the underlying HTML element:
import { Stack } from '@wordpress/ui';
function MyComponent() {
// Render Stack as a <section /> instead of the default <div />
return <Stack render={ <section /> }>{ /* ... */ }</Stack>;
}
All components forward refs to their underlying DOM elements:
import { useRef } from '@wordpress/element';
import { Stack } from '@wordpress/ui';
function MyComponent() {
const stackRef = useRef< HTMLDivElement >( null );
return <Stack ref={ stackRef }>{ /* ... */ }</Stack>;
}
className MergingComponents merge provided className props with their internal styles:
import { Stack } from '@wordpress/ui';
function MyComponent() {
// Your custom CSS className is merged with component styles
return <Stack className="my-custom-class">{ /* ... */ }</Stack>;
}
Interactive components that manage internal state (such as open/closed, selected value, etc.) follow a consistent prop naming convention that supports both controlled and uncontrolled usage.
For a given state x, the convention is:
| Prop | Purpose |
|---|---|
defaultX |
Sets the initial value in uncontrolled mode. The component manages subsequent state changes internally. |
x |
Sets the current value in controlled mode. The consumer is responsible for updating the value in response to changes. |
onXChange |
Callback invoked when the state changes. Receives the new value as its first argument. Works in both controlled and uncontrolled modes. |
For example, a component with an open/closed state would expose:
defaultOpen — initial open state (uncontrolled)open — current open state (controlled)onOpenChange — called when the open state changesAnd a component with a selectable value would expose:
defaultValue — initial value (uncontrolled)value — current value (controlled)onValueChange — called when the value changesIn uncontrolled mode, the component manages its own state. Use defaultX to set the initial value, and optionally onXChange to react to changes:
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>
);
}
In controlled mode, the consumer owns the state and passes it via x. State changes are handled through 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>
);
}
When both x and defaultX are provided, x takes precedence and the component behaves in controlled mode. When neither is provided, the component uses its own internal default (typically documented via a @default JSDoc tag on the defaultX prop).
onChangeThe onXChange callback is distinct from the native DOM onChange event handler. Native onChange fires a React.ChangeEvent tied to a specific DOM element, while onXChange provides the new value directly — making it simpler to use and consistent across all components, including compound and non-form components.
Components that wrap native form elements may still support native event handlers (like onChange, onInput) for interoperability, but onXChange is the recommended approach within this package.
When designing props for a new component:
defaultX, the controlled prop x, and the callback onXChange.defaultOpen prop instead.@default JSDoc tag for the uncontrolled prop when there is a sensible default.This is an individual package that’s part of the Gutenberg project. The project is organized as a monorepo. It’s made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to npm and used by WordPress as well as other software projects.
To find out more about contributing to this package or Gutenberg as a whole, please read the project’s main contributor guide.