Craft Agent OSS 主题系统详解:六色语义、OKLCH 配色与 Scenic 模式的完整定制指南
2026/9/16 14:43:52 网站建设 项目流程

Craft Agent OSS 主题系统详解:六色语义、OKLCH 配色与 Scenic 模式的完整定制指南

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

本文基于 Craft Agent 官方主题配置文档(themes.md)展开,系统讲解 Craft Agent 的 6 色彩主题体系、theme.json应用级覆盖、预设主题包、Scenic 玻璃拟态模式以及深色模式的部分覆盖机制。读完本文,你将掌握从“改一个 accent 颜色”到“发布一个完整预设主题包”的全部操作方式,并理解主题在 Electron 渲染进程中的实际解析与热更新链路。

主题体系总览与解析层级

Craft Agent 采用一套6 色彩主题系统,同时支持应用级默认主题与按工作区(workspace)覆盖的主题。主题来源按以下层级生效:

  1. 应用默认(App default):在 Settings → Appearance → Default Theme 中选择,作用于所有未设置覆盖项的工作区;
  2. 工作区覆盖(Workspace override):在 Settings → Appearance → Workspace Themes 中按工作区指定主题,可选择“Use Default”或某个具体主题;
  3. 预设主题包(Preset themes)~/.craft-agent/themes/{name}.json,完整的主题包文件;
  4. 主题覆盖(Theme overrides)~/.craft-agent/theme.json,仅覆盖特定颜色(应用级)。

所有配置项都是可选的——应用内置了合理的默认值。未设置自定义主题的工作区会继承应用默认主题。

渲染进程中的实际解析链

从源码结构看,主题的“预览 > 工作区 > 应用默认”解析链在 ThemeContext.tsx 中实现:effectiveColorTheme = previewColorTheme ?? workspaceColorTheme ?? colorTheme,并据此标注当前生效来源为preview/workspace/app。其中:

  • 工作区覆盖通过window.electronAPI.getWorkspaceColorTheme(activeWorkspaceId)从工作区配置读取;
  • 预设主题优先经 IPC(loadPresetTheme)从用户目录加载,失败时回退到打包内置主题(import.meta.glob('../../../resources/themes/*.json')),仓库内置的 15 个预设主题位于 apps/electron/resources/themes,包括defaultdraculanordcatppuccintokyo-nightgruvboxrose-pinegithubsolarizedone-dark-proghosttyhazenight-owlpierrevitesse
  • 最终的合并逻辑由 theme.ts 中的resolveTheme/mergeThemes完成,颜色键(6 个语义色 + 5 个表面色)逐一以覆盖方为准深合并,dark子对象也做同规则合并。

工作区主题的存储位置

工作区主题偏好保存在工作区配置文件中:

~/.craft-agent/workspaces/{id}/config.json
{ "id": "ws_abc123", "name": "My Project", "defaults": { "colorTheme": "nord" } }

colorTheme省略或未定义时,工作区继承应用默认主题。在 UI 侧,AppearanceSettingsPage.tsx 负责“Default Theme / Workspace Themes”的设置界面,工作区切换时通过setWorkspaceColorTheme写入并跨窗口广播(broadcastWorkspaceThemeChange)。

6 色彩语义系统

颜色用途使用场景
background表面/页面背景浅色/深色表面色
foreground文本与图标主文本色
accent品牌色,Execute 模式高亮、激活状态、紫色 UI 元素
info警告,Ask 模式琥珀色指示、需注意的状态
success已连接状态绿色对勾、成功状态
destructive错误、删除操作红色告警、失败状态

这 6 个键在 theme.ts 中对应ThemeColors接口(backgroundforegroundaccentinfosuccessdestructive),全部可选。语义色进一步映射为 CSS 变量(--background--foreground--accent--info--success--destructive),供全局样式消费。

此外,仓库还有一层“实体颜色”体系(colors/types.ts):标签、状态等实体配置可以直接引用系统色字符串(如"accent""foreground/50",透明度 0–100 通过color-mix(in oklch, ...)渲染),也可以使用{ light, dark }自定义颜色对象——未显式给出dark时由deriveDarkVariant自动派生(hex 颜色向白色混合提亮约 30%)。这说明主题色变量的改动会级联到标签、状态等全部实体着色,定制时建议同时检查这两处观感。

支持的颜色格式

任何合法的 CSS 颜色格式都受支持:

  • Hex#8b5cf6#8b5cf6cc(带 alpha)
  • RGBrgb(139, 92, 246)rgba(139, 92, 246, 0.8)
  • HSLhsl(262, 83%, 58%)
  • OKLCHoklch(0.58 0.22 293)(推荐)
  • 命名色purplerebeccapurple

建议:使用 OKLCH 以获得感知均匀、在深浅模式下表现一致的颜色。

源码层面有两点值得注意(见 theme.ts 的themeToCSS实现):

  1. --foreground-rgb--accent-rgb两个派生变量(用于阴影描边和带色调的阴影)仅当颜色是 hex 时才会生成——hexToRgbValues只匹配 6 位/3 位 hex,accent 的 rgb 版本会按 70% 亮度压暗。如果你使用 OKLCH 作为 accent,这部分派生变量不会输出,相关阴影效果会回退到默认表现;
  2. Electron 主进程无法解析 CSS/OKLCH 颜色,theme.ts 提供了BACKGROUND_HEX(light:#faf9fb,dark:#302f33)作为BrowserWindow.backgroundColor的 hex 等价值,避免窗口加载时的白屏闪烁。

应用级主题覆盖文件(theme.json)

创建~/.craft-agent/theme.json可以覆盖特定颜色:

{ "accent": "oklch(0.58 0.22 293)", "dark": { "accent": "oklch(0.65 0.22 293)" } }

所有字段都是可选的,只需指定你想覆盖的颜色。

覆盖文件的校验规则

覆盖文件在读取前会经过 validators.ts 中ThemeOverrideSchema的严格校验(Zod.strict()模式),关键规则包括:

  • 允许的颜色键:6 个语义色 + 5 个表面色(papernavigatorinputpopoverpopoverSolid)+mode(枚举solid/scenic)+backgroundImage+dark子对象;
  • 未知键会被拒绝,空对象(无任何支持字段)也会报错 “Theme override must include at least one supported field”;
  • mode: "scenic"时必须提供backgroundImage,否则报错 “backgroundImage is required when mode is scenic”。

这与文档“Colors look wrong in dark mode / Background image not showing”的排障建议直接对应:先检查文件是否通过了 schema 约束。

实时热更新

主题修改会立即生效,无需重启。watcher.ts 会监视~/.craft-agent/配置目录,检测到theme.json变更后触发主题重载回调;渲染进程侧由 ThemeContext.tsx 把最终变量注入一个<style id="craft-theme-overrides">元素(内容为:root { --background: ...; --accent: ...; }形式的声明)。因此直接编辑theme.json保存后 UI 即可自动更新。

深色模式(dark 子对象)

dark对象提供深色模式下的可选覆盖。当用户系统处于深色模式时:

  1. 顶层基础色作为默认值使用;
  2. dark中定义的颜色覆盖基础色。

这允许部分深色定制——只需覆盖需要不同的颜色即可。

实现上,themeToCSS(theme, isDark)isDark && theme.dark时执行{ ...theme, ...theme.dark }合并,即深色覆盖只针对被显式写出的键生效,其余键仍回退到基础色。默认主题(见下文)即为这种“同一色相、深色模式下提高明度”的典型示范。

预设主题(Preset Themes)

预设主题是完整的主题包,存放于~/.craft-agent/themes/。每个预设是一个包含主题颜色和元数据的 JSON 文件。

预设主题 Schema 示例

{ "name": "Dracula", "description": "A dark theme with vibrant colors", "author": "Zeno Rocha", "license": "MIT", "source": "https://draculatheme.com", "supportedModes": ["dark"], "background": "oklch(0.22 0.02 280)", "foreground": "oklch(0.95 0.01 270)", "accent": "oklch(0.70 0.20 320)", "info": "oklch(0.78 0.14 70)", "success": "oklch(0.72 0.18 145)", "destructive": "oklch(0.65 0.22 28)", "shikiTheme": { "light": "github-light", "dark": "dracula" } }

仓库内置的 dracula.json 即遵循该结构(使用 hex 色值且supportedModes: ["dark"]),可作为可直接参考的模板。

预设元数据字段

字段说明
name主题显示名(预设文件中必填
description简短描述
author主题作者
license许可证类型(MIT 等)
source原始主题的 URL
supportedModes"light""dark"或其组合数组
shikiTheme语法高亮主题(light/dark 变体)

对应类型见 theme.ts 的ThemeFile(在ThemeOverrides基础上扩展元数据字段)与PresetThemeid为去后缀的文件名,如draculapath为完整路径)。PresetThemeSchema(validators.ts)要求:name非空、且至少包含 6 个语义色中的 1 个,否则报 “Theme must have at least one color property”。

supportedModes与深色强制

从 ThemeContext.tsx 的逻辑可以确认文档中的两条规则:

  • 仅支持 dark 的预设supportedModes只含"dark")会强制以深色模式渲染,无视系统模式;
  • 若当前模式不在supportedModes内,document.documentElement会被标记data-theme-mismatch,UI 采用实心背景以避免视觉错乱;同时 Shiki 语法高亮也会回退到该主题支持的模式的shikiTheme

语法高亮联动

预设中的shikiTheme决定代码块的语法高亮配色;未指定时使用默认DEFAULT_SHIKI_THEME(light:github-light,dark:github-dark),由getShikiTheme(shikiConfig, isDark)按当前明暗模式选取。

安装预设主题

  1. 下载或创建一个主题 JSON 文件;
  2. 保存到~/.craft-agent/themes/{name}.json(文件名即主题 id);
  3. 在 Settings → Appearance 中选择该主题。

用户目录的预设经 IPC 加载;若 IPC 加载失败(例如 Web 版渲染环境下loadPresetTheme不可用),渲染进程会自动回退到内置同名主题并记录警告。

Scenic 模式(背景图 + 玻璃拟态面板)

Scenic 模式显示整窗背景图片,并配合玻璃拟态(glass-style)面板,营造沉浸式视觉体验。

启用 Scenic 模式

{ "mode": "scenic", "backgroundImage": "mountains.jpg", "background": "oklch(0.15 0.02 270 / 0.8)", "paper": "oklch(0.18 0.02 270 / 0.6)", "navigator": "oklch(0.12 0.02 270 / 0.7)", "popoverSolid": "oklch(0.18 0.02 270)" }

Scenic 模式属性

属性说明
mode设为"scenic"(默认是"solid"
backgroundImage图片文件名(相对主题文件)或 URL

渲染侧的判定条件是resolvedTheme.mode === 'scenic' && backgroundImage 存在(见 ThemeContext 的isScenic计算),二者缺一不可;生效时document.documentElement会获得data-scenic="true"属性,背景图以--background-imageCSS 变量直接设置(注释说明这是为了规避大图 data URL 撑爆样式表大小的问题)。

玻璃面板的表面色

Scenic 模式受益于半透明的表面色:

颜色用途
paperAI 消息、卡片、高亮内容
navigator左侧边栏背景
input输入框背景
popover下拉菜单、模态框、上下文菜单
popoverSolid保证 100% 不透明的 popover 背景

表面色的回退规则见themeToCSS:未设置时依次回退到background--popover-solid则先回退popover再回退background),因此在 Scenic 主题中应显式提供popoverSolid以保证弹出层可读性。

注意:Scenic 主题会自动强制深色模式,以获得与背景图片更好的对比度——这与 ThemeContext.tsx 中effectiveMode = (isScenic || isDarkOnlyTheme) ? 'dark' : resolvedMode的实现一致。

内置默认主题的色值

内置默认主题(DEFAULT_THEME,theme.ts)使用为可访问性优化的 OKLCH 颜色:

Light Mode:

槽位色值说明
Backgroundoklch(0.98 0.003 265)极浅灰,带轻微紫色调
Foregroundoklch(0.185 0.01 270)近黑色,高对比
Accentoklch(0.58 0.22 293)鲜艳的紫色
Infooklch(0.75 0.16 70)暖琥珀色
Successoklch(0.55 0.17 145)清晰的绿色
Destructiveoklch(0.58 0.24 28)警示红

Dark Mode:

槽位色值说明
Backgroundoklch(0.145 0.015 270)带紫色调的深暗色
Foregroundoklch(0.95 0.01 270)近白色
Accentoklch(0.65 0.22 293)提亮版本,保证深色下可见性
Infooklch(0.78 0.14 70)提亮版本
Successoklch(0.60 0.17 145)提亮版本
Destructiveoklch(0.65 0.22 28)提亮版本

即深色模式并非简单反色,而是保持色相、提高明度(lightness),这正是文档推荐 OKLCH 的原因。

实战示例

最简:只改 accent 颜色

{ "accent": "#3b82f6" }

自定义品牌色

{ "accent": "oklch(0.55 0.25 250)", "info": "oklch(0.70 0.15 200)", "dark": { "accent": "oklch(0.65 0.25 250)", "info": "oklch(0.75 0.12 200)" } }

高对比度主题

{ "background": "#ffffff", "foreground": "#000000", "dark": { "background": "#000000", "foreground": "#ffffff" } }

注意前两个示例都使用 hex 前景/主色,因此--foreground-rgb/--accent-rgb派生变量可以正常输出;第三个示例的全黑/全白搭配同样能触发 rgb 派生变量。

创建主题的流程与建议

  1. 覆盖单个颜色:创建~/.craft-agent/theme.json;做完整主题包:创建~/.craft-agent/themes/{name}.json
  2. 只添加你要定制的颜色(预设需至少 1 个语义色,覆盖文件至少 1 个受支持字段);
  3. 可选地添加dark子对象覆盖深色模式。

技巧:

  • 从只改accent开始,快速个性化;
  • 使用 OKLCH 获得可预测的颜色行为;
  • 在浅色和深色两种模式下都测试;
  • 保持对比度可访问(foreground 对 background)。

故障排查

主题不生效(Theme not applying):

  • 确认 JSON 语法合法(validateThemeContent/validateThemeOverrideContent会先做 JSON 解析再跑 schema);
  • 检查文件位置是否正确(覆盖是~/.craft-agent/theme.json,预设是~/.craft-agent/themes/,预设文件名即主题 id);
  • 确保颜色值是合法的 CSS 颜色;
  • 预设文件检查name是否存在且至少有一个语义色,未知键在覆盖文件中会直接导致校验失败。

深色模式下颜色不对(Colors look wrong in dark mode):

  • 添加显式dark覆盖;
  • OKLCH 颜色在深色模式下通常需要更高的 lightness 值;
  • 检查预设的supportedModes是否排除了当前模式(dark-only 主题会强制深色渲染,data-theme-mismatch时 UI 改用实心背景)。

背景图不显示(Background image not showing):

  • 确认mode设为"scenic"
  • 检查图片路径是相对主题文件的路径,或为合法 URL(schema 层面也要求 scenic 模式必须提供backgroundImage);
  • 确认图片文件存在且可读。

OKLCH 颜色参考

OKLCH 格式:oklch(lightness chroma hue)

  • Lightness(明度):0–1(0 = 黑,1 = 白)
  • Chroma(彩度):0–0.4(0 = 灰,越大越饱和)
  • Hue(色相):0–360(色轮角度)

常用色相参考:

颜色色相值
Red~25
Orange~70
Yellow~100
Green~145
Cyan~195
Blue~250
Purple~293
Pink~330

对照内置默认主题可以发现其取色规律:accent 用 293(紫)、info 用 70(橙琥珀)、success 用 145(绿)、destructive 用 28(红),与上表一一对应——自建主题时按同一色相坐标取值,再在dark子对象里把 lightness 提高 0.05–0.10,即可得到风格一致的深色变体。

小结

Craft Agent 的主题体系可以概括为三条正交的能力线:颜色层(6 语义色 + 5 表面色,OKLCH 优先,dark部分覆盖)、选择层(应用默认 → 工作区覆盖 → 预设包 → theme.json 覆盖,UI 侧另有悬停预览优先级)、模式层(solid / scenic,scenic 强制深色并联动 Shiki 高亮与data-scenicCSS 钩子)。相关实现集中在 theme.ts(类型、默认值与 CSS 变量生成)、validators.ts(覆盖文件与预设文件的严格 schema 校验)、watcher.ts(theme.json 热更新)与 ThemeContext.tsx(渲染端解析、DOM 注入与跨窗口同步),读者可沿这些文件进一步深入。

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询