Skip to content

6.4 颜色 Token

学习目标

完成本节后,你将能够:

  1. 读懂 Langfuse 前端颜色不是散落的 Tailwind class,而是一套 CSS 变量契约。
  2. 区分基础 UI token、业务强调色、图表色、Search Bar 语法色。
  3. 判断新增 UI 或图表时应该复用哪个 token。

6.4.1 先给结论:Langfuse 的颜色服务于“高密度观测 UI”

Langfuse 不是营销页,也不是内容站。它的主界面是 tracing、scores、sessions、datasets、evals、dashboards 这类高密度工作台。因此颜色策略偏克制:

  • 大面积背景保持低干扰;
  • border、muted、card、popover 负责层级;
  • primary accent 用于关键动作和当前状态;
  • chart tokens 用于多序列分析;
  • Search Bar 语法色帮助读 query;
  • light/dark 通过同一组语义 token 切换。

源码入口是:

  • web/src/styles/globals.css
  • web/src/features/score-analytics/lib/color-scales.ts
  • web/src/components/editor/shared-theme.ts

6.4.2 Token 的两层结构

第一层是 CSS 变量,例如:

css
:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary-accent: 243 75.4% 58.6%;
  --chart-1: 239 84% 58%;
}

第二层是 Tailwind v4 的 @theme inline 映射:

css
@theme inline {
  --color-background: hsl(var(--background));
  --color-foreground: hsl(var(--foreground));
  --color-primary-accent: hsl(var(--primary-accent));
  --color-chart-1: hsl(var(--chart-1));
}

组件使用的是 bg-backgroundtext-foregroundtext-primary-accent 这类语义 token,而不是直接写十六进制颜色。这样 light/dark 和主题调整可以集中发生。

6.4.3 基础 UI 色板

Token作用典型场景
background / foreground页面底色和主要文字页面主体、普通文本
card / card-foreground可复用内容块panel、dialog、列表项
popover / popover-foreground浮层dropdown、command palette、tooltip
muted / muted-foreground次级背景和说明文字空状态、辅助说明、低权重 metadata
border / input / ring交互边界表单、focus、分隔线
primary / primary-foreground主要按钮语义primary action
destructive / destructive-foreground破坏性操作delete、danger state

这套 token 的设计目标是让复杂页面先靠层级和间距可读,而不是靠大量彩色标签制造噪声。

6.4.4 业务强调色

globals.css 还定义了几组业务强调色:

Token颜色意图用法
primary-accent品牌/关键强调当前导航、CTA、重要 active state
muted-blue / muted-green / muted-magenta柔和彩色区分轻量标签、状态辅助
light-red / dark-red错误、危险、失败error badge、失败状态
light-yellow / dark-yellowwarning、pendingwarning badge、等待状态
light-green / dark-green成功、通过success badge、positive state
light-blue / dark-blue信息、链接、辅助强调info badge、secondary highlight

注意这些 token 通常成对出现:浅色负责背景,深色负责文字或边框。这样在高密度表格里不会出现大片高饱和色块。

6.4.5 Dark mode 不是反色

dark mode 在 .dark 里重新定义同一批语义变量:

css
.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 83%;
  --muted: 217.2 32.6% 17.5%;
  --border: 217.2 32.6% 27.5%;
}

这说明组件不应该自己判断 dark mode 后改颜色。组件应该继续使用语义 token,让主题层负责 light/dark。

错误示例:

tsx
<div className="bg-white dark:bg-slate-950 text-black dark:text-white" />

更符合本项目的写法:

tsx
<div className="bg-background text-foreground" />

6.4.6 图表颜色是单独契约

图表颜色由 --chart-1--chart-8 管理:

Token意图
chart-1主序列
chart-2第二序列
chart-3中性色/单分数默认
chart-4chart-8多类别扩展
chart-grid图表网格线

web/src/features/score-analytics/lib/color-scales.ts 在这些 token 上继续封装:

  • 单分数图使用 getSingleScoreColor()
  • 双分数对比使用 getTwoScoreColors()
  • heatmap 使用 OKLCH lightness 生成单色阶;
  • fallback hex 保证 CSS variable 解析失败时仍能显示。

这说明图表颜色不是随便从 Tailwind palette 里取。它需要稳定映射,避免用户隐藏/显示分类时颜色漂移。

6.4.7 Search Bar 语法色

Search Bar 有自己的 query language token:

Token表示
qlang-field字段名
qlang-value字符串值
qlang-number数字
qlang-keyword关键字

源码注释明确说这是一套“editor-style syntax theme”,它不完全跟随应用色板。原因是搜索栏类似代码编辑器,颜色职责是帮助用户解析语法结构,而不是表达业务状态。

这和架构契约也有关:Search Bar 不是随意拼查询字符串,它最终要生成 FilterState,再由后端 lower 成 ClickHouse SQL。

6.4.8 颜色如何服务架构

UI 场景颜色职责对应架构
trace / observation 表格减少噪声,突出状态、层级和 hover高密度 observability 工作台
Search Bar强化 query grammarFilterState 契约
score analytics保持序列和类别颜色稳定分析查询和可视化
destructive actions让危险操作和普通 action 分离控制面变更
dark mode通过 token 层统一切换组件不感知主题实现

所以颜色不是纯视觉细节。对这种 infra/product 混合系统来说,颜色 token 是前端稳定性的组成部分。

6.4.9 新增颜色的原则

新增颜色前先问:

  1. 这是业务状态,还是普通视觉层级?
  2. 是否已有 mutedaccentdestructivechart-* 能表达?
  3. 这个颜色是否需要 light/dark 两套值?
  4. 是否会被图表、Search Bar、editor、table 共同使用?
  5. 是否需要稳定映射,避免数据重排后颜色变化?

如果只是一个局部装饰,不要加全局 token。全局 token 应该表达跨组件语义。

下一节

Search Bar