Cherry Studio UI 组件库 @cherrystudio/ui 集成指南:设计系统、双模式主题接入与源码级原理解析

发布时间:2026/9/20 23:37:33
Cherry Studio UI 组件库 @cherrystudio/ui 集成指南:设计系统、双模式主题接入与源码级原理解析 Cherry Studio UI 组件库 cherrystudio/ui 集成指南设计系统、双模式主题接入与源码级原理解析【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio导读cherrystudio/ui是 Cherry Studio 面向 React 应用发布的 UI 组件库承载了 Cherry Studio 的原始色板primitive palettes、产品语义product semantics与 Shadcn 兼容主题映射。本指南以 packages/ui/README.md 为主体结合 packages/ui/src 下的真实源码与 packages/ui/package.json 的导出配置系统讲解从安装、两种主题接入模式到 CSS 变量分层契约、图标生成管线与组件 API 的完整实践并深入剖析其底层实现原理帮助你在一小时内完成独立应用与 Cherry Studio 设计系统的对接。一、组件库定位与核心特性cherrystudio/ui是 Cherry Studio 官方维护的 React 组件库其设计目标不是再造一套孤立的 UI 框架而是把 Cherry Studio 在设计上沉淀下来的价值以可复用的形式开放出来。README 中列出的特性可以概括为六点特性说明Design System提供 Cherry Studio 原始色板、产品语义变量以及 Shadcn 兼容的主题映射Dark Mode内置浅色:root与深色.dark双主题支持Tailwind v4基于最新 Tailwind CSS v4 构建使用theme inline适配器Flexible Imports提供两种样式集成模式适配不同的采纳路径TypeScript完整的类型定义与编辑器支持Low Collision通过 CSS 变量隔离降低命名冲突默认不接管应用运行时状态从源码结构看packages/ui/src组件库被划分为components/含primitives/基础组件与composites/复合组件、hooks/、lib/、styles/令牌与主题入口、utils/五大部分这与 README 中的目录结构完全对应。值得注意的是包版本目前为1.0.0-alpha.1见 packages/ui/package.json属于预发布阶段接口仍可能演进接入时建议锁定精确版本。二、快速开始安装与入口2.1 安装npm install cherrystudio/ui # peer dependencies npm install motion react react-dom tailwindcss组件库以react、react-dom、tailwindcss、motion为核心对等依赖peerDependencies。此外从 packages/ui/package.json 可以看到其 peerDependencies 还包含react-hook-form、hookform/resolvers标记为可选、hookform/resolvers等只有当你使用 Form 相关复合组件时才需要安装。2.2 推荐导入方式本仓库推荐通过包的导出入口export entry points消费避免直接深入包内部路径入口内容cherrystudio/ui主入口组件、Hooks 等聚合导出cherrystudio/ui/components仅组件cherrystudio/ui/icons图标运行时导出与目录cherrystudio/ui/utils公共工具函数cherrystudio/ui/styles/tokens.css基础令牌foundation valuescherrystudio/ui/styles/theme.css完整主题契约 Tailwind 适配器这些入口在 packages/ui/package.json 的exports字段中逐一声明并同时提供importESM与requireCJS两种解析以及react-native字段方便不同构建体系消费。三、两种主题集成模式核心章节cherrystudio/ui提供两种截然不同的集成路径全量主题契约Mode 1与选择性基础消费Mode 2。选择哪种取决于你希望接管多少 Tailwind 主题语义。3.1 Mode 1全量主题契约 ✨如果你的应用希望整套外观都长成 Cherry Studio只需在应用 CSS 中导入一份文件/* app.css */ import cherrystudio/ui/styles/theme.css;特性✅ 可以直接使用标准 Tailwind 工具类bg-primary、bg-red-500、p-4、rounded-lg✅ 颜色解析为 Cherry Studio 设计值✅ 使用 Tailwind 标准数字间距刻度p-4等✅ 包含 Shadcn 派生的圆角rounded-4xl起外加rounded-full更小的 Cherry 别名如rounded-4xs仍保留用于兼容⚠️ 会覆盖导入应用包中的默认 Tailwind 主题契约示例Button classNamebg-primary text-red-500 p-4 rounded-lg {/* bg-primary - 当前主操作语义色 */} {/* text-red-500 - Cherry Studio 的 red-500 */} {/* p-4 - Tailwind 数字间距 */} {/* rounded-lg - 语义圆角令牌 */} /Button div classNamerounded-4xs极小圆角 (0.03125rem)/div div classNamerounded-xs小圆角 (0.125rem)/div div classNamerounded-md中圆角 (0.5rem)/div div classNamerounded-xl大圆角 (0.875rem)/div div classNamerounded-full全圆角 (9999px)/div源码验证packages/ui/src/styles/theme.css 就是 Mode 1 的全部秘密。文件头部明确标注了它由pnpm theme:build自动生成、禁止手改其主体是一个巨大的theme inline块把--cs-*基础值逐层映射为--color-*如--color-red-500: var(--cs-red-500)、Shadcn 语义如--color-primary: var(--primary)与 Cherry Studio 产品语义如--color-success: var(--success)。inline关键字是必需的因为主题变量引用了其他 CSS 变量需要内联解析。圆角方面theme.css 采用 Shadcn 标准的倍数派生体系--radius-sm: calc(var(--radius) * 0.6); --radius-md: calc(var(--radius) * 0.8); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) * 1.4); --radius-2xl: calc(var(--radius) * 1.8); --radius-3xl: calc(var(--radius) * 2.2); --radius-4xl: calc(var(--radius) * 2.6); --radius-full: var(--cs-radius-round);这套倍数与 Shadcn 官方 radius 适配器一致因此只要覆盖--radius一个输入所有标准圆角会等比缩放。3.2 Mode 2选择性基础消费 如果你的应用已经拥有自己的语义契约只想借用 Cherry Studio 的部分基础值则采用此模式——只导入原始令牌与既有基础提供者由你决定设计系统暴露哪些值/* app.css */ import tailwindcss; import cherrystudio/ui/styles/tokens.css; /* 只重新导出你需要的部分 */ theme inline { --color-primary: var(--cs-brand-500); /* 采纳 Cherry Studio 的基础值 */ --color-red-500: oklch(...); /* 保留你自己的红色刻度 */ --radius-lg: 1rem; /* 保留你自己的圆角 */ }特性✅ 不覆盖完整 Tailwind 主题✅ 可访问 Cherry Studio 基础值var(--cs-brand-500)、var(--cs-red-500)✅ 自行决定采纳什么、保留什么✅ 适用于已拥有语义契约、只需特定基础值的场景⚠️ 不暴露完整的 Shadcn 或 Cherry Studio 产品契约定义适配器后的组件消费方式{/* 由消费者拥有的适配器把其 primary 工具类映射到所选基础值 */} button classNamebg-primary text-primary-foreground使用已采纳的主色/button {/* 你的原始 Tailwind 主题不受影响 */} div classNamebg-red-500 Use the default Tailwind red /div {/* 组件消费消费者拥有的工具类契约而非裸的 --cs-* 提供者 */} div classNamerounded-lg bg-primary text-primary-foreground /关键纪律在 Mode 2 下组件样式应当消费消费者自己的工具类契约而不是直接引用--cs-*提供者变量——--cs-*是内部实现细节。3.3 内部组合层说明src/styles/contract.css是内部组合层供生成的theme.css入口使用用于保持基础提供者 → 运行时输入 → Shadcn → 产品语义的导入顺序见 packages/ui/src/styles/contract.css。它不是公开包导出也不应作为消费者入口/* contract.css 的真实导入顺序单向依赖 */ import ./tokens.css; /* 基础令牌 */ import ./theme-input.css; /* 受控运行时输入 */ import ./shadcn.css; /* 官方 Shadcn 语义 */ import ./product.css; /* Cherry Studio 产品语义 */而 packages/ui/src/styles/tokens.css 只包含基础提供者注释明确要求不得导入官方 Shadcn 契约或产品语义从结构上保证了分层不被破坏。四、CSS 变量规则一份可执行的命名空间契约4.1 分层架构总览规范性的 v2 架构、Shadcn 契约与迁移边界定义在 Design Token System 中完整的公共/历史变量清单请查阅 Variable Catalog。整个变量体系呈现为一条单向的数据流foundation values (--cs-brand-*, existing providers) │ ▼ controlled runtime inputs (--cs-theme-primary, --cs-theme-primary-foreground) │ ▼ public semantic contract (Shadcn: --background, --primary, ...) (Cherry: --success, --chat-user, ...) │ ▼ Tailwind theme inline adapter (--color-background, --color-success, ...) │ ▼ semantic utilities (bg-background, bg-success, ...)4.2 命名空间规则务必遵守为了避免混淆取值来源、主题映射与运行时覆盖README 给出了七条硬性规则--background、--primary、--muted-foreground等shadcn.css中的变量是官方 Shadcn 契约获准的 Cherry Studio 产品语义同样不加前缀例如--success、--background-subtle历史迁移名称仅限工具使用不得重新创建为运行时产品变量共享的--cs-*变量是内部值提供者选择性基础消费者只能在自己定义的适配器中引用基础提供者普通组件样式不得引用--cs-theme-*是保留给宿主写入的输入子集--color-*、--radius-*、--font-*是Tailwind 适配器输出不是另一层语义输入。只有适配器所有者可以在theme中声明--color-*组件 CSS、页面 CSS 与渲染进程 TS/TSX 编写的样式既不能声明也不能消费--color-*--cs-theme-*是受控的宿主写入输入不是组件面语义角色或 Tailwind 工具类组件、页面与 Electron 外壳变量停留在各自样式表中不会因为它们是 CSS 自定义属性就进入共享契约。4.3 默认消费规则常规应用包默认依赖cherrystudio/ui/styles/theme.css组件应优先使用语义工具类bg-background、text-muted-foreground、bg-success自定义 CSS 可使用匹配的官方或产品变量只有确实需要基础层访问权的设计系统邻近包才依赖cherrystudio/ui/styles/tokens.css运行时主题逻辑只能通过注册过的--cs-theme-*输入写入共享主题值不得直接写官方语义或派生的--color-*变量仅渲染进程使用的运行时值在--app-*下保持宿主本地。4.4 源码视角分层如何落地theme-input.css 定义了受控运行时输入注释明确宿主应用可以写入这些值它们是输入而非公共组件语义当前仅有两个变量:root { --cs-theme-primary: var(--cs-primary); --cs-theme-primary-foreground: var(--cs-primary-foreground); }shadcn.css 是官方契约层所有官方变量保持无前缀以兼容生态如--background: var(--cs-background)、--primary: var(--cs-theme-primary)并自带浅色/深色两套chart-*序列tokens/colors/providers.css 是语义值提供者完整实现了浅色:root与深色.dark两套--cs-*值例如浅色--cs-background: var(--cs-white)、深色--cs-background: oklch(0.209 0 0 / 0.55)且注释强调深色下层级越高表面越亮因此 Popover 浮在 Card 之上。这套分层的价值在于组件只消费稳定的无前缀语义--cs-*是随时可替换的实现细节--color-*是只读的生成输出——三者解耦后主题演进例如未来切换到 DTCG 格式不会破坏任何组件 API。五、Shadcn CLI 所有权谁写 theme.cssREADME 明确规定了 Shadcn CLI 的职责边界使用 Shadcn CLI 仅用于脚手架/更新组件源码与依赖元数据。Cherry Studio 编写的主题层与生成器拥有共享 CSS 契约的所有权即使components.json把 CLI 指向生成的src/styles/theme.css入口。实践规则不要保留对src/styles/theme.css的直接 CLI 编辑pnpm theme:build是它唯一的写入者审查shadcn add提出的任何 CSS并按所有权归位官方语义进shadcn.cssCherry Studio 产品语义进product.css与theme-contract.ts组件局部样式随组件存放通过主题生成器添加 Tailwind 映射而不是手改生成输出接受一个改变主题需求的组件后依次运行pnpm theme:build与pnpm theme:check。结合源码看theme.css 头部有醒目的 ⚠️ DO NOT EDIT DIRECTLY! 注释并指明其生成源src/styles/tokens/*、theme-input.css、shadcn.css、product.css或生成器契约与这一所有权约定完全一致。六、基础组件使用6.1 基本用法import { Button, Input } from cherrystudio/ui function App() { return ( div Button variantdefault sizedefaultClick me/Button Input typetext placeholderType here onChange{(event) console.log(event.currentTarget.value)} / /div ) }6.2 模块化导入组件库支持按模块拆分导入便于 tree-shaking 与按需加载// 只引入组件 import { Button } from cherrystudio/ui/components // 只引入工具函数 import { DIALOG_CLOSE_DURATION_MS, DIALOG_UNMOUNT_DELAY_MS, toUndefinedIfNull } from cherrystudio/ui/utils七、开发与验证命令在 packages/ui 目录或通过pnpm --filter cherrystudio/ui执行# 安装依赖 pnpm install # 开发模式tsc -w 增量编译 pnpm dev # 构建先 pnpm theme:build再 tsdown 打包并拷贝样式产物到 dist/styles pnpm build # 类型检查 pnpm type:check # 校验变量图、生成适配器、注册表与渲染进程自有 CSS 边界 pnpm theme:check # 运行测试 pnpm test其中theme:check是这套体系的守门员。按 Design Token System 第 8 节它会验证所有必需 Shadcn 变量存在、每个公共产品变量属于稳定白名单、官方与产品变量名不重叠、各层依赖单向无环、生成的 CSS 与提交产物一致、渲染进程主题入口不得重新引入遗留别名等十余项治理规则。从 packages/ui/package.json 可以看到构建流水线的实际拼装build: pnpm theme:build tsdown mkdir -p dist/styles cp -R src/styles/. dist/styles/即先生成主题 CSS再打包 JS最后把样式产物复制进发布目录保证cherrystudio/ui/styles/*.css入口可用。八、图标生成管线所有图标生成都应通过包命令进行以便生成文件更新后自动执行 ESLint 修复与仓库格式化# 生成通用图标、Providers、Models缺省三组全量 pnpm icons:generate # 仅通用图标非 Provider/Model Logo 的一般 UI 图标 pnpm icons:generate --typeicons # Provider 图标Avatar、barrel、catalog、per-icon loaders pnpm icons:generate --typeproviders # Model 图标Avatar、barrel、per-icon loaders pnpm icons:generate --typemodels类型SVG 源生成产物iconsicons/general/*.svg通用 React 图标组件及其 barrelprovidersicons/providers/{light,dark}/*.svgProvider 浅/深色组件、元数据、Avatars、barrels、catalogs、loadersmodelsicons/models/{light,dark}/*.svgModel 浅/深色组件、元数据、Avatars、barrels、loaders导入语义从cherrystudio/ui/icons导入基于 key 的查找 API。静态 Provider 组件刻意走独立的cherrystudio/ui/icons/providers入口这样常规查找路径不会求值整个 Provider barrel对应 package.json 中独立的./icons/providers导出。Provider 组件已不再从cherrystudio/ui/icons复导出静态消费者必须显式使用 provider 入口。增量与精确再生成生成管线使用哈希缓存未变化的 SVG 会被跳过。需要更窄或干净的重新生成时使用可选参数# 仅重新生成一个 provider 及其 Avatar/catalog/loader 条目 pnpm icons:generate --typeproviders --onlyopencode # 重新生成多个 models pnpm icons:generate --typemodels --onlyclaude,gemini # 忽略哈希缓存强制重新生成所有 provider pnpm icons:generate --typeproviders --force参数语义汇总省略--type时按icons→providers→models顺序全量生成--typeicons|providers|models限定单个源与输出组--onlyname[,name]将 Provider/Model 组件与 Avatar 生成限定到指定名称--force绕过 SVG 哈希缓存。Provider 与 Model 生成分两阶段先跑 SVG 组件阶段再跑 Avatar 查找产物阶段。posticons:generate生命周期脚本会在两阶段结束后先用 ESLint 修复生成的图标文件再运行一次仓库格式化器。scripts/下的内部脚本仍保留用于管线开发但常规使用应统一走pnpm icons:generate见 packages/ui/package.json 中的icons:generate与posticons:generate脚本定义。九、包表面Package Surface与目录结构9.1 运行时面与开发面packages/ui工作区同时包含运行时代码与仅开发资产运行时面src/、dist/构建产物、package.json中声明的导出入口——只有这部分是可供消费的包 API开发资产stories/与.storybook/Storybook 故事、scripts/图标与主题生成、icons/生成管线用原始资产、docs/迁移与参考文档。9.2 目录结构docs/ # 迁移计划与参考文档 src/ ├── components/ │ ├── primitives/ # 基础组件 │ ├── composites/ # 复合组件 │ ├── icons/ # 图标运行时导出与目录 │ └── index.ts ├── hooks/ # React Hooks ├── lib/ # 内部工具 ├── styles/ # 令牌与主题入口文件 ├── utils/ # 工具函数 └── index.ts # 主运行时入口 scripts/ # 主题与图标生成工具 stories/ # Storybook stories 与沙箱用法 icons/ # 供代码生成的原始图标资产9.3 结构标记Structural Markers与 UI 语义契约packages/ui为组件内部样式与独立构建保留了 Shadcn 兼容的data-slot属性。当 Cherry Studio 应用消费包源码时应用的 UI 契约生成器把这些标记视为结构语义并生成对应的公共data-uipart:*令牌保留原始属性。既有使用data-slot的渲染进程代码、应用测试与自定义主题继续工作新选择器可使用生成的语义层。应用级令牌语法、稳定性分级、维护锚点与选择器规则由 UI Semantic Contract即 docs/references/components/ui-semantic-contract.md定义显式角色与受维护的part:*令牌是公共选择器推断角色仅是尽力而为的发现坐标。十、命名约定packages/ui/下所有文件与目录名遵循kebab-case符合 Shadcn CLI 约定与项目级规则 §4.5见 命名约定文档覆盖primitives/、composites/、icons/、hooks/、stories/等全部目录。文件内导出的标识符则保持惯例组件用PascalCase工具函数与 Hooks 用camelCase。示例button.tsx导出Buttondata-table.tsx导出DataTableerror-boundary/index.tsx导出ErrorBoundaryuse-dnd-reorder.ts导出useDndReorder对照 packages/ui/src 的实际目录primitives/button.tsx、composites/data-table/index.tsx、hooks/use-dnd-reorder.ts等命名约定在源码中已严格执行。十一、组件 API 详解11.1 Button带多种变体与尺寸的按钮组件内部基于class-variance-authority的cva构建见 button.tsx。PropsProp取值说明variantdefault|destructive|outline|secondary|emphasis|ghost|link视觉变体sizedefault|sm|lg|icon|icon-sm|icon-lg|icon-navbar尺寸loadingboolean加载态控制源码中data-[busytrue]会施加cursor-progress与opacity-40loadingIcon/loadingIconClassNameReactNode/string自定义加载图标及其类名asChildboolean通过 RadixSlot渲染为子元素如把按钮语义附加到 Link 上其余—所有标准 React button props源码细节size的默认值为min-h-7.5 gap-1.5 px-2.5 text-[13px]icon-navbar是 30px 盒体 18px 图标8px 圆角的导航栏/工具栏图标按钮加载 Spinner 尺寸会根据按钮尺寸自适应icon-sm13px、sm14px、icon-navbar18px、lg/icon-lg18px、其余 16px。11.2 InputShadcn 兼容的原生输入组件。Props接受标准 React input props包括原生type、value与基于事件的onChange使用aria-invalid触发无效态样式按钮源码中同样出现aria-invalid:ring-destructive/20之类的配套处理使用className进行受支持的布局组合。十二、Hooks 与工具函数12.1 HooksuseDndReorder当渲染列表是源列表的过滤子集时仍能保持拖拽重排序的正确性对应源码 use-dnd-reorder.tsuseDndState从当前 dnd-kit 上下文读取激活与悬停的标识符。两者均基于dnd-kit系列依赖实现见 package.json 中的dnd-kit/core、dnd-kit/modifiers、dnd-kit/sortable、dnd-kit/utilities。12.2 工具函数这些函数通过cherrystudio/ui/utils导出属于公共 API源码注释明确区分了公共utils/与内部lib/见 utils/index.tstoUndefinedIfNull(value)在 API 边界把null转为undefined其余值原样返回toNullIfUndefined(value)把undefined转为null保证缺失值表示一致DIALOG_CLOSE_DURATION_MSDialog CSS 关闭动画时长200 msDIALOG_UNMOUNT_DELAY_MS命令式 Dialog 宿主卸载前的延迟200 ms。十三、许可协议cherrystudio/ui以MIT协议开源发布见 packages/ui/package.json 的license字段可在遵循 MIT 条款的前提下自由使用、修改与分发。结语cherrystudio/ui的价值在于它把 Cherry Studio 的设计资产变成了一套分层清晰、可增量采纳、有治理工具背书的公共契约tokens.css提供基础值theme.css提供完整语义与 Tailwind 适配theme-input.css划出宿主运行时输入边界theme:check守护整个变量图的单向性与稳定性。无论你是想整套复用 Cherry Studio 视觉还是只想借几个基础色值都可以在这两种模式中找到明确的落点而阅读 Design Token System 与 Variable Catalog能帮助你理解这套体系的设计意图与演进边界。【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询