fix(theme): 浅色主题标签强调色改为按 WCAG 加深(实测 4.0:1 -> 4.9:1)

浅色分支此前固定 mix(accent, #000, 0.35),默认绿 #3fb950 得 #297834:在强调色
染过的激活标签底(≈#dae8df)上只有 4.0:1,低于 AA,用户自定义的浅色强调色还会
更差。改用 darkenToRatio(accent, chromeBg, 5.5)——对 chrome 底色保证 5.5:1,
落到更深的染色底上仍有 4.9:1。深色分支(mix 白 0.18)不动。

chrome.ts 新增 chromeBg 记录当前 chrome 底色(applyTabAccent 可能在
applyChromeTheme 之前被设置变更单独调用);#181818 是 pre-JS 深色默认值,
登记进 css-theme-vars 白名单(与 global.css 的 --chrome-bg 同值)。
This commit is contained in:
Bill committed 2026-10-16 23:44:48 +08:00
1 parent 3b86d62111
commit 81748e4470
2 files changed
+15 -3

No files matched your search

+13 -2
View File
@@ -1,5 +1,5 @@
import type { ThemeColors } from '@shared/theme'
import { contrast, isLightTheme, mix, semanticCssVars } from './semantic'
import { contrast, darkenToRatio, isLightTheme, mix, semanticCssVars } from './semantic'
// 兼容既有导入方(main.tsx 的 mix);新代码请直接从 ./semantic 导入。
export { contrast, luminance, mix } from './semantic'
@@ -8,6 +8,10 @@ export { contrast, luminance, mix } from './semantic'
* from it flip their overlay direction (white-on-dark vs black-on-light). */
let chromeIsLight = false
/** Last chrome background; applyTabAccent() needs it to derive a readable
* accent foreground for light themes. */
let chromeBg = '#181818'
/** Dark-chrome tab label: the background mixed toward the theme's own foreground
* (the light branch is the same mix toward black), but never below 4.5:1 against
* the background, since a theme foreground dimmed by 0.68 can land unreadable. */
@@ -32,6 +36,7 @@ export function applyChromeTheme(colors: ThemeColors): void {
set('--chrome-bg', colors.background)
set('--chrome-fg', colors.foreground)
chromeIsLight = isLightTheme(colors.background)
chromeBg = colors.background
if (chromeIsLight) {
// Light chrome: keep the bar close to the background (a big mix toward
// black turns pale themes into a muddy gray strip) and overlay tabs with
@@ -82,6 +87,12 @@ export function applyTabAccent(color: string): void {
return
}
style.setProperty('--tab-accent', color)
const fg = chromeIsLight ? mix(color, '#000000', 0.35) : mix(color, '#ffffff', 0.18)
// Light chrome: a fixed 0.35 mix toward black left the default green
// (#3fb950 -> #297834) at 4.0:1 on the accent-tinted tab, just under AA, and
// arbitrary user accents could be far worse. darkenToRatio() guarantees the
// ratio against the chrome background; the tinted surfaces it also lands on
// are slightly darker, hence the margin above 4.5. Dark chrome keeps the
// existing lighten mix (its accents sit on dark tabs).
const fg = chromeIsLight ? darkenToRatio(color, chromeBg, 5.5) : mix(color, '#ffffff', 0.18)
style.setProperty('--tab-accent-fg', fg ?? color)
}