NocoBase 插件客户端样式与主题开发指南:createStyles、Theme Token 与主题编辑器实战

发布时间:2026/9/17 3:27:46
NocoBase 插件客户端样式与主题开发指南:createStyles、Theme Token 与主题编辑器实战 NocoBase 插件客户端样式与主题开发指南createStyles、Theme Token 与主题编辑器实战【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseNocoBase 的前端基于 Ant Designantd构建其客户端插件在编写组件样式时官方推荐统一使用 antd-style 方案通过 theme token 引用颜色、间距、圆角等设计变量从而让自定义组件自动适配主题切换包括暗色模式。本指南以 styles-themes.md 为核心完整讲解createStyles、createStylish、createGlobalStyle三种写法并结合nocobase/client源码说明 NocoBase 对 token 体系的扩展CustomToken以及主题编辑器插件的调试方式读完即可在自己的插件中写出可随主题自动适配的组件样式。为什么 NocoBase 选择 antd-styleNocoBase 客户端组件样式开发统一基于 antd-style 库它与 antd 的 theme token 体系深度集成。antd 的 theme tokenSeed Token / Alias Token定义了一套语义化的设计变量如主色、背景色、圆角、间距等组件通过 token 而非硬编码颜色取值即可在明暗主题切换时自动跟随。从源码看antd-style 在 NocoBase 客户端运行时中被注册为全局依赖在 globalDeps.ts 中通过defineGlobalDep(requirejs, antd-style, antdStyle)将整个 antd-style 模块暴露给插件运行时因此插件代码中可以直接import { createStyles } from antd-style无需额外引入重复的样式库实例。同时nocobase/client在 style/index.ts 中对createStyles做了二次导出并定义了一个扩展后的工具类型import { CreateStylesUtils, createStyles } from antd-style; import type { CustomToken } from nocobase/client-v2; export * from ./useToken; export { createStyles }; export interface CustomCreateStylesUtils extends CreateStylesUtils { token: CustomToken; }这意味着 NocoBase 中createStyles回调拿到的token不仅是 antd 的标准 Alias Token还叠加了 NocoBase 自定义的CustomToken详见下文NocoBase 的 CustomToken 扩展一节你可以放心在样式里引用这些额外变量。编写样式createStyles推荐createStyles是最常用的样式写法它把样式定义与组件逻辑放在一起支持CSS object和CSS 字符串模板两种方式并且生成的styles对象会被缓存组件 re-render 不会带来重复计算开销import { createStyles } from antd-style; const useStyles createStyles(({ token, css }) ({ // CSS object 写法 container: { backgroundColor: token.colorBgLayout, borderRadius: token.borderRadiusLG, maxWidth: 400, width: 100%, height: 180, display: flex, alignItems: center, justifyContent: center, flexDirection: column, marginLeft: auto, marginRight: auto, }, // CSS 字符串模板写法 card: css color: ${token.colorTextTertiary}; box-shadow: ${token.boxShadow}; :hover { color: ${token.colorTextSecondary}; box-shadow: ${token.boxShadowSecondary}; } padding: ${token.padding}px; border-radius: ${token.borderRadius}px; background: ${token.colorBgContainer}; transition: all 100ms ${token.motionEaseInBack}; margin-bottom: 8px; cursor: pointer; , })); export default () { // styles 对象会被缓存不用担心 re-render 问题 const { styles, cx, theme } useStyles(); return ( div className{cx(a-simple-create-style-demo-classname, styles.container)} div className{styles.card}createStyles Demo/div div当前主题模式{theme.appearance}/div /div ); };要点说明回调参数{ token, css }中token可直接引用 antd 语义变量css用于书写嵌套、伪类等更复杂的 CSS 字符串模板。返回的 hook 提供styles生成的类名映射、cx类名合并工具可传入自定义类名与 styles 类名、theme当前主题对象包含appearance等字段可用于展示当前是明色还是暗色模式。在 NocoBase 中此处的token类型为CustomCreateStylesUtils[token]即 NocoBase 扩展后的CustomToken可同时引用自定义主题变量见后文。createStylishcreateStylish用于创建可复用的样式片段适合在多个组件之间共享样式。与createStyles不同它返回的不是类名映射而是一组可以直接在css模板中展开复用的样式块import { createStyles, createStylish, css } from antd-style; const useStylish createStylish(({ token, css }) { const containerBgHover css cursor: pointer; transition: 150ms background-color ease-in-out; :hover { background: ${token.colorFillQuaternary}; } ; const defaultButtonBase css color: ${token.colorTextSecondary}; background: ${token.colorFillQuaternary}; border-color: transparent; ; return { defaultButton: css ${defaultButtonBase}; :hover { color: ${token.colorText}; background: ${token.colorFillSecondary}; border-color: transparent; } :focus { ${defaultButtonBase}; border-color: ${token.colorPrimary}; } , containerBgHover, containerBgL2: css ${containerBgHover}; border-radius: 4px; background: ${token.colorFillQuaternary}; :hover { background: ${token.colorFillTertiary}; } , }; }); const useStyles createStyles({ container: { backgroundColor: #f5f5f5, maxWidth: 400, width: 100%, height: 180, display: flex, alignItems: center, justifyContent: center, }, btn: css padding: 24px; , }); export default () { const { styles, cx } useStyles(); const stylish useStylish(); return ( div className{styles.container} div className{cx(styles.btn, stylish.defaultButton)} stylish Button /div /div ); };使用场景建议当多个组件存在相同的悬停背景、按钮底色、卡片容器等样式片段时抽成createStylish避免重复。可以通过${someStylishBlock}的方式在另一个样式块中嵌套复用如上例containerBgL2复用了containerBgHoverdefaultButton在 hover/focus 状态复用了defaultButtonBase。最终在组件中通过cx(styles.xxx, stylish.yyy)组合到元素上互不冲突。createGlobalStylecreateGlobalStyle用于注入全局样式。通常用得比较少大部分场景createStyles就够了只有需要影响页面级元素如全局 class、伪元素、滚动条等时才使用import { createGlobalStyle } from antd-style; const Global createGlobalStyle .some-class { color: hotpink; } ; export default () { return ( div Global / div classNamesome-class猛男最喜欢的颜色/div /div ); };注意全局样式的副作用是全局性的插件内请谨慎使用避免污染其他插件的 UI。使用 theme tokenAntd 的 theme token 可以在createStyles和createGlobalStyle中直接使用。通过 token 引用颜色、间距、圆角等变量组件就能自动适配主题切换包括暗色模式而不是写死某个具体颜色值。在 createStyles 中使用import { SmileOutlined } from ant-design/icons; import { Button, Space } from antd; import { createStyles } from antd-style; const useStyles createStyles(({ token, css }) { const commonCard css border-radius: ${token.borderRadiusLG}px; padding: ${token.paddingLG}px; ; return { container: css background-color: ${token.colorBgLayout}; padding: 24px; , primaryCard: css ${commonCard}; background: ${token.colorPrimary}; color: ${token.colorTextLightSolid}; , defaultCard: css ${commonCard}; background: ${token.colorBgContainer}; color: ${token.colorText}; , }; }); const App () { const { styles } useStyles(); return ( div className{styles.container} Space direction{vertical} style{{ width: 100% }} size{16} Space Button title{功能按钮的说明} icon{SmileOutlined /} / 操作按钮 /Space div className{styles.defaultCard}普通卡片/div div className{styles.primaryCard}主要卡片/div /Space /div ); }; export default App;这里演示了常见的 token 用法布局背景用token.colorBgLayout容器背景用token.colorBgContainer主色强调用token.colorPrimary主色上的文字用token.colorTextLightSolid保证对比度。圆角、内边距等尺寸类 token 通常以 px 为单位在模板字符串中需要手动拼接单位如${token.borderRadiusLG}px、${token.paddingLG}px。在 createGlobalStyle 中使用在全局样式中 token 通过p.theme.xxx方式从模板函数参数读取import { createGlobalStyle, ThemeProvider } from antd-style; const Global createGlobalStyle .ant-custom-button { color: ${(p) p.theme.colorPrimary}; background: ${(p) p.theme.colorPrimaryBg}; height: ${(p) p.theme.controlHeight}px; border-radius: ${(p) p.theme.borderRadius}px; padding: 0 ${(p) p.theme.paddingContentHorizontal}px; :hover { background: ${(p) p.theme.colorPrimaryBgHover}; color: ${(p) p.theme.colorPrimaryTextActive}; } :active { background: ${(p) p.theme.colorPrimaryBorder}; color: ${(p) p.theme.colorPrimaryText}; } border: none; cursor: pointer; } ; export default () { return ( ThemeProvider Global / button classNameant-custom-buttonantd 中不存在的按钮/button /ThemeProvider ); };注意这里必须用ThemeProvider包裹全局样式内部的函数式插值才能拿到p.theme。antd 提供了完整的 Seed Token / Alias Token 列表如主色、成功/警告/错误色、字体、间距、圆角、阴影、动效等可按需查阅官方主题定制文档。NocoBase 的 CustomToken 扩展除了 antd 标准 tokenNocoBase 在客户端主题层扩展了自定义 token 体系。nocobase/client-v2的 type.ts 定义了CustomTokenimport type { ThemeConfig as _ThemeConfig } from antd; import { AliasToken } from antd/es/theme/internal; export interface CustomToken extends AliasToken { colorPrimaryHeader: string; colorBgHeader: string; colorBgHeaderMenuHover: string; colorBgHeaderMenuActive: string; colorTextHeaderMenu: string; colorTextHeaderMenuHover: string; colorTextHeaderMenuActive: string; colorBgSider: string; colorTextSiderMenu: string; colorTextSiderMenuHover: string; colorTextSiderMenuActive: string; colorBgSiderMenuHover: string; colorBgSiderMenuActive: string; colorSettings: string; colorBgSettingsHover: string; colorTemplateBgSettingsHover: string; colorBorderSettingsHover: string; paddingPageHorizontal: number; paddingPageVertical: number; paddingPopupHorizontal: number; paddingPopupVertical: number; marginBlock: number; borderRadiusBlock: number; siderWidth: number; globalStyle?: string; }可以看到NocoBase 针对自己的后台布局新增了头部Header、侧边栏Sider、设置面板Settings等区域的专属 token以及页面/弹层内边距、区块圆角、侧栏宽度等布局变量。这些变量的默认值定义在 defaultTheme.ts 中例如colorPrimaryHeader: #001529、colorBgHeader: #001529、colorSettings: #F18B62等。这意味着在你的插件样式中除了使用token.colorPrimary这类 antd 标准 token还可以直接引用token.colorBgSider、token.siderWidth、token.borderRadiusBlock等 NocoBase 布局变量让你的组件与整个后台界面保持视觉一致。nocobase/client提供的useTokenhook见 useToken.ts在 antdtheme.useToken基础上将返回类型断言为CustomToken配合 style/index.ts 导出的CustomCreateStylesUtils可以在 TypeScript 下获得完整的自定义 token 提示。调试主题NocoBase 提供了主题编辑器插件可以在界面上直接调整主题变量并实时预览效果。它覆盖了 antd 标准 token 与 NocoBase 自定义 token头部、侧边栏配色等调整结果会即时反映到所有基于 token 编写的组件样式上——这正是坚持使用 token 而非硬编码颜色的价值所在一处调整全局生效。主题编辑器的配置会持久化到后端前端通过主题系统加载并应用到ThemeProvider最终通过 antd 的 token 机制下发到每个组件。因此插件开发者只需保证自己的样式全部基于 token 编写即可自动获得主题编辑器带来的自定义能力与暗色模式支持无需针对主题做额外适配。相关链接Component 组件开发概述 — 回到组件开发概览了解组件注册与渲染的完整流程客户端样式与主题 API 入口 —createStyles重导出与CustomCreateStylesUtils定义NocoBase 自定义 Token 类型定义 —CustomToken/ThemeConfig完整字段NocoBase 默认主题值 — 各自定义 token 的默认取值antd-style 全局依赖注册 — 插件运行时如何直接使用antd-style模块【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考