Files
boos e0a5f57793 feat(desktop): embed BoosAPI Desktop client as a subproject
Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
2026-06-22 11:32:57 +08:00

4.9 KiB
Raw Permalink Blame History

Theming System

markstream-vue 的主题机制文档:Light/Dark 模式实现、CSS 变量架构、主题切换方式。


1. 主题架构概览

markstream-vue 采用 混合主题方案:

Props (isDark) → CSS Class (.is-dark / .dark) → CSS Variables Override → 组件渲染

三层机制互为补充:

层级 机制 说明
1. Props isDark: boolean 由宿主应用传入,最高优先级
2. CSS Class .dark / .is-dark 添加到根容器或组件上
3. Media Query prefers-color-scheme: dark 系统偏好兜底

2. 全局主题变量

2.1 挂载方式

/* Light(默认) */
.markstream-vue {
  --border: 214.3 31.8% 91.4%;
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --secondary: 210 40% 96%;
  --muted: 210 40% 96%;
  --muted-foreground: 215.4 16.3% 46.9%;
}

/* Dark — 两种触发方式 */
.dark .markstream-vue,    /* 父级添加 .dark 类 */
.markstream-vue.dark {    /* 自身添加 .dark 类 */
  --border: 217.2 32.6% 17.5%;
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  --secondary: 217.2 32.6% 17.5%;
  --muted: 217.2 32.6% 17.5%;
  --muted-foreground: 215 20.2% 65.1%;
}

2.2 使用方式

在组件中通过 hsl() 引用:

color: hsl(var(--foreground));
background-color: hsl(var(--secondary));
border: 1px solid hsl(var(--border) / 0.9);

Tailwind 配置中也引用这些变量(带回退值):

const fallback = {
  foreground: 'hsl(var(--foreground), 217.2 22.08% 19.5%)',
}

3. 组件级暗色模式

3.1 Props 传递链

NodeRenderer (isDark prop)
  └─ 所有子组件 (isDark prop)
       └─ :class="{ 'is-dark': props.isDark }"

3.2 CSS 类切换模式

各组件使用 .is-dark 类覆盖 CSS 变量:

<div class="code-block-container" :class="{ 'is-dark': props.isDark }">

<style scoped>
.code-block-container {
  --markstream-code-fallback-bg: #ffffff;
}
.code-block-container.is-dark {
  --markstream-code-fallback-bg: #111827;
}
</style>

3.3 各组件暗色实现方式

组件 暗色触发 方式
全局变量 .dark .markstream-vue CSS 变量覆盖
CodeBlockNode .is-dark class ~30+ CSS 变量覆盖
AdmonitionNode .is-dark class CSS 变量覆盖 + 透明度调整
MermaidBlockNode :class 条件 Tailwind dark 类名切换
Tooltip .is-dark class bg-gray-900 text-white
MathBlockNode .is-dark class spinner 颜色反转
ImageNode - 无暗色适配
HighlightNode - 无暗色适配(固定 #ffff00)
BlockquoteNode - 仅通过全局 --blockquote-border-color
TableNode - 仅通过 --table-border
ListItemNode - 仅通过 --list-item-marker 等
FootnoteNode - 固定 #eaecef 边框色,无暗色适配

4. Monaco Editor 主题

代码块支持独立的编辑器主题系统:

interface Props {
  darkTheme?: CodeBlockMonacoTheme // 暗色编辑器主题
  lightTheme?: CodeBlockMonacoTheme // 亮色编辑器主题
}

// 运行时根据 isDark 切换
const activeTheme = props.isDark ? props.darkTheme : props.lightTheme

支持:

  • 字符串形式:内置主题名
  • 对象形式:CodeBlockMonacoThemeObject 自定义主题

VSCode 变量自动映射:

  • --vscode-editor-background
  • --vscode-editor-foreground
  • --vscode-editor-selectionBackground

5. 媒体查询兜底

部分组件使用系统偏好作为兜底:

@media (prefers-color-scheme: dark) {
  .math-loading-spinner {
    border-color: rgba(255, 255, 255, 0.1);
    border-top-color: rgba(255, 255, 255, 0.6);
  }
}

JavaScript 检测:

window.matchMedia('(prefers-color-scheme: dark)').matches

6. Tailwind 作用域隔离

所有 Tailwind 工具类限定在 .markstream-vue 内生效,避免全局污染:

// tailwind.config.js
important: '.markstream-vue'

按钮重置使用 :where() 保持低特异性:

:where(.markstream-vue) button {
  appearance: none;
  background: transparent;
  border: 0;
}

7. 双构建输出

构建 输出文件 说明
标准构建 dist/index.css 包含完整 Tailwind 工具类
Tailwind 构建 dist/index.tailwind.css 不含 Tailwind,供宿主项目自行引入

8. 当前主题体系的问题

问题 详情
暗色覆盖不完整 HighlightNode、FootnoteNode、ImageNode 等无暗色适配
变量命名不统一 全局用 HSL 裸值,组件用 HEX/RGB/rgba,缺乏统一规范
暗色触发方式不一致 全局用 .dark,组件用 .is-dark,Mermaid 用条件 class
硬编码颜色散落 #e2e8f0、#eaecef、#cbd5e1 等直接写在组件中
语义色彩未统一 Admonition 语义色与全局体系分离
CSS 变量缺乏 Dark 值 --blockquote-border-color、--table-border 等无暗色默认值