跳到主要内容

全局配置(DesignProvider)

DesignProvider@plaud/design 的一站式入口。在应用根部挂载一次,即可配置组件库所需的全部能力:

  • 主题:light / dark,支持受控 / 持久化,并可跟随系统偏好
  • 方向ltr / rtl,支持 RTL 布局
  • 图标注入:必填的 icons 注册表(design 不内置任何图标实现)
  • Overlay 宿主:自动挂载 <OverlayHost />,命令式弹层(Dialog.open() 等)开箱即用

它的定位等同于 antd 的 ConfigProvider:一处集中配置整个设计系统。

何时使用

Provider能力适用场景
DesignProvider主题 + 方向 + Overlay 宿主 + 图标注入业务应用入口,一站式
IconRegistryProvider仅图标注入,不管理主题 / Overlay主题由外部托管的场景(如本文档站的 Docusaurus)

绝大多数应用都应使用 DesignProvider。仅当已有其他系统托管主题与 DOM 属性时,才改用轻量的 IconRegistryProvider——参见图标配置

基础用法

在应用根部包裹一次。icons 为必填项,需提供一份覆盖全部图标 key 的注册表(契约见图标配置):

import { DesignProvider } from '@plaud/design'

import { icons } from './icons'

export const App = () => (
<DesignProvider icons={icons}>
<YourApp />
</DesignProvider>
)

这一次挂载即会把主题 token 应用到 document.documentElement、注入图标,并让命令式弹层在其下任意位置可用。

主题

DesignProvider 管理 light / dark 主题,并通过切换 <html> 上的 .dark class 与 data-theme 属性把主题反映到文档。实际颜色值来自 @plaud/design-tokens(CSS 变量),provider 只负责“拨开关”。

非受控(默认)

默认情况下主题是非受控的。用 defaultTheme 指定初始值;此后 provider 会持久化用户选择,并在没有存储值时跟随系统偏好:

<DesignProvider icons={icons} defaultTheme="light">
<YourApp />
</DesignProvider>

初始主题的解析顺序:

  1. localStorage 中存储的偏好(当 persistTheme 开启时)
  2. defaultTheme
  3. 之后跟随系统偏好(prefers-color-scheme)——只要用户没有显式选择过主题

受控

传入 theme 即可完全接管。受控模式下 provider 始终渲染该值,忽略 localStorage,也不再跟随系统偏好——状态由你掌控:

const [theme, setTheme] = useState<'light' | 'dark'>('light')

return (
<DesignProvider icons={icons} theme={theme}>
<ThemeToggle onToggle={() => setTheme((t) => (t === 'light' ? 'dark' : 'light'))} />
<YourApp />
</DesignProvider>
)

读取与切换主题 —— useTheme

在 provider 内部,useTheme() 暴露当前主题与切换方法。在 DesignProvider 外部使用会抛错。

import { useTheme } from '@plaud/design'

const ThemeToggle = () => {
const { theme, setTheme, toggleTheme } = useTheme()

return (
<button type="button" onClick={toggleTheme}>
当前主题:{theme}(点击切换)
</button>
)
}
  • toggleTheme():在 light / dark 之间切换
  • setTheme('dark'):设置指定主题
  • 非受控模式下二者都会持久化到 localStorage(当 persistTheme 开启时);受控模式下 theme 仍由父组件掌控,请改用自己的状态驱动。

方向(RTL)

设置 dir 切换文档方向。provider 会把它写到 <html>dir 属性上,useTheme() 也暴露 dir / setDir 供运行时切换:

<DesignProvider icons={icons} dir="rtl">
<YourApp />
</DesignProvider>

持久化

主题持久化默认开启,localStorage 的 key 为 plaud-design-theme

// 完全关闭持久化(不读写 localStorage)
<DesignProvider icons={icons} persistTheme={false}>
<YourApp />
</DesignProvider>

// 或保留持久化,但使用自定义 key
<DesignProvider icons={icons} storageKey="my-app-theme">
<YourApp />
</DesignProvider>
备注

默认的 storageKey 刻意保留为 plaud-design-theme,生产应用不建议改动——一旦修改,已上线用户在升级后会丢失主题偏好。

Overlay 宿主

DesignProvider 会在根部自动挂载 <OverlayHost />,因此 Dialog.open() / Drawer.open() 等命令式弹层无需任何额外配置即可渲染。

如果你刻意不使用 DesignProvider(例如只用 IconRegistryProvider),需要自行挂载宿主,命令式弹层才有渲染出口:

import { IconRegistryProvider, OverlayHost } from '@plaud/design'

const Root = ({ children }) => (
<IconRegistryProvider icons={icons}>
{children}
<OverlayHost />
</IconRegistryProvider>
)

详见可组合弹层

图标注入

icons 为必填项——@plaud/design 不内置任何图标实现,组件用到的每个图标都从这里注入的注册表读取。缺失注册表或某个 key 会在渲染时抛错。契约、完整 key 列表与参考实现见图标配置

:::info 为什么本文档站用的是 IconRegistryProvider 本 Docusaurus 站点的主题由 Docusaurus 自身托管,所以站点在 src/theme/Root.tsx 中通过轻量的 IconRegistryProvider 注入图标,而不是让 DesignProvider 去管理文档主题。你的业务应用应使用 DesignProvider。 :::

API

DesignProvider Props

Prop类型默认值说明
iconsIconRegistry必填。 覆盖全部 key 的图标注册表,见图标配置
childrenReact.ReactNode必填。 应用子树
theme'light' | 'dark'-受控主题。设置后忽略 localStorage 与系统偏好
defaultTheme'light' | 'dark''light'非受控模式下、且无存储偏好时的初始主题
dir'ltr' | 'rtl''ltr'文档方向,写入 <html dir>
persistThemebooleantrue是否将主题偏好持久化到 localStorage
storageKeystring'plaud-design-theme'持久化使用的 localStorage key

useTheme() 返回值(ThemeContextValue)

字段类型说明
theme'light' | 'dark'当前主题
setTheme(theme: ThemeName) => void设置指定主题
toggleTheme() => void在 light / dark 之间切换
dir'ltr' | 'rtl'当前文档方向
setDir(dir: Direction) => void设置文档方向