e0a5f57793
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.
4.9 KiB
4.9 KiB
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 等无暗色默认值 |