fix(theme): derive readable text for overlays and toasts (#451)
Use contrast-based text colors for the link status overlay, mode legend, and mode/level toasts instead of hardcoded white or background colors.
- commit
- 7635eef80360bd5c023ed093ec3aeeef5a393caf
- author
- bnema · · 2026-09-24 05:24 UTC
- committer
- GitHub · · 2026-09-24 05:24 UTC
- parent
- 677167c
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown
4 files · +45 -23
M internal/ui/theme/css.go +10 -10
| @@ -1380,25 +1380,25 @@ func generateToasterCSS(p Palette) string { | |||
| 1380 | 1380 | /* Toast level: info (default, accent color) */ | |
| 1381 | 1381 | .toast-info { | |
| 1382 | 1382 | background-color: alpha(var(--accent), 0.9); | |
| 1383 | - | color: var(--bg); | |
| 1383 | + | color: var(--accent-text); | |
| 1384 | 1384 | } | |
| 1385 | 1385 | ||
| 1386 | 1386 | /* Toast level: success */ | |
| 1387 | 1387 | .toast-success { | |
| 1388 | 1388 | background-color: alpha(var(--success), 0.9); | |
| 1389 | - | color: var(--bg); | |
| 1389 | + | color: var(--success-text); | |
| 1390 | 1390 | } | |
| 1391 | 1391 | ||
| 1392 | 1392 | /* Toast level: warning */ | |
| 1393 | 1393 | .toast-warning { | |
| 1394 | 1394 | background-color: alpha(var(--warning), 0.9); | |
| 1395 | - | color: var(--bg); | |
| 1395 | + | color: var(--warning-text); | |
| 1396 | 1396 | } | |
| 1397 | 1397 | ||
| 1398 | 1398 | /* Toast level: error */ | |
| 1399 | 1399 | .toast-error { | |
| 1400 | 1400 | background-color: alpha(var(--destructive), 0.9); | |
| 1401 | - | color: var(--bg); | |
| 1401 | + | color: var(--destructive-text); | |
| 1402 | 1402 | } | |
| 1403 | 1403 | ||
| 1404 | 1404 | /* Toast with custom styling (mode indicator toasters) */ | |
| @@ -1409,27 +1409,27 @@ func generateToasterCSS(p Palette) string { | |||
| 1409 | 1409 | /* Mode-specific toast colors */ | |
| 1410 | 1410 | .toast-pane-mode { | |
| 1411 | 1411 | background-color: var(--pane-mode-color); | |
| 1412 | - | color: #ffffff; | |
| 1412 | + | color: var(--pane-mode-text); | |
| 1413 | 1413 | } | |
| 1414 | 1414 | ||
| 1415 | 1415 | .toast-vim-mode { | |
| 1416 | 1416 | background-color: var(--vim-mode-color); | |
| 1417 | - | color: #ffffff; | |
| 1417 | + | color: var(--vim-mode-text); | |
| 1418 | 1418 | } | |
| 1419 | 1419 | ||
| 1420 | 1420 | .toast-tab-mode { | |
| 1421 | 1421 | background-color: var(--tab-mode-color); | |
| 1422 | - | color: #ffffff; | |
| 1422 | + | color: var(--tab-mode-text); | |
| 1423 | 1423 | } | |
| 1424 | 1424 | ||
| 1425 | 1425 | .toast-session-mode { | |
| 1426 | 1426 | background-color: var(--session-mode-color); | |
| 1427 | - | color: #ffffff; | |
| 1427 | + | color: var(--session-mode-text); | |
| 1428 | 1428 | } | |
| 1429 | 1429 | ||
| 1430 | 1430 | .toast-resize-mode { | |
| 1431 | 1431 | background-color: var(--resize-mode-color); | |
| 1432 | - | color: #ffffff; | |
| 1432 | + | color: var(--resize-mode-text); | |
| 1433 | 1433 | } | |
| 1434 | 1434 | ` | |
| 1435 | 1435 | } | |
| @@ -1461,7 +1461,7 @@ func generateLinkStatusCSS(p Palette) string { | |||
| 1461 | 1461 | ||
| 1462 | 1462 | /* Link status label text */ | |
| 1463 | 1463 | .link-status label { | |
| 1464 | - | color: var(--muted); | |
| 1464 | + | color: var(--control-muted); | |
| 1465 | 1465 | } | |
| 1466 | 1466 | ` | |
| 1467 | 1467 | } | |
| @@ -1380,25 +1380,25 @@ func generateToasterCSS(p Palette) string { | |||||
| 1380 | /* Toast level: info (default, accent color) */ | 1380 | /* Toast level: info (default, accent color) */ | ||
| 1381 | .toast-info { | 1381 | .toast-info { | ||
| 1382 | background-color: alpha(var(--accent), 0.9); | 1382 | background-color: alpha(var(--accent), 0.9); | ||
| 1383 | - | color: var(--bg); | 1383 | + | color: var(--accent-text); |
| 1384 | } | 1384 | } | ||
| 1385 | 1385 | ||||
| 1386 | /* Toast level: success */ | 1386 | /* Toast level: success */ | ||
| 1387 | .toast-success { | 1387 | .toast-success { | ||
| 1388 | background-color: alpha(var(--success), 0.9); | 1388 | background-color: alpha(var(--success), 0.9); | ||
| 1389 | - | color: var(--bg); | 1389 | + | color: var(--success-text); |
| 1390 | } | 1390 | } | ||
| 1391 | 1391 | ||||
| 1392 | /* Toast level: warning */ | 1392 | /* Toast level: warning */ | ||
| 1393 | .toast-warning { | 1393 | .toast-warning { | ||
| 1394 | background-color: alpha(var(--warning), 0.9); | 1394 | background-color: alpha(var(--warning), 0.9); | ||
| 1395 | - | color: var(--bg); | 1395 | + | color: var(--warning-text); |
| 1396 | } | 1396 | } | ||
| 1397 | 1397 | ||||
| 1398 | /* Toast level: error */ | 1398 | /* Toast level: error */ | ||
| 1399 | .toast-error { | 1399 | .toast-error { | ||
| 1400 | background-color: alpha(var(--destructive), 0.9); | 1400 | background-color: alpha(var(--destructive), 0.9); | ||
| 1401 | - | color: var(--bg); | 1401 | + | color: var(--destructive-text); |
| 1402 | } | 1402 | } | ||
| 1403 | 1403 | ||||
| 1404 | /* Toast with custom styling (mode indicator toasters) */ | 1404 | /* Toast with custom styling (mode indicator toasters) */ | ||
| @@ -1409,27 +1409,27 @@ func generateToasterCSS(p Palette) string { | |||||
| 1409 | /* Mode-specific toast colors */ | 1409 | /* Mode-specific toast colors */ | ||
| 1410 | .toast-pane-mode { | 1410 | .toast-pane-mode { | ||
| 1411 | background-color: var(--pane-mode-color); | 1411 | background-color: var(--pane-mode-color); | ||
| 1412 | - | color: #ffffff; | 1412 | + | color: var(--pane-mode-text); |
| 1413 | } | 1413 | } | ||
| 1414 | 1414 | ||||
| 1415 | .toast-vim-mode { | 1415 | .toast-vim-mode { | ||
| 1416 | background-color: var(--vim-mode-color); | 1416 | background-color: var(--vim-mode-color); | ||
| 1417 | - | color: #ffffff; | 1417 | + | color: var(--vim-mode-text); |
| 1418 | } | 1418 | } | ||
| 1419 | 1419 | ||||
| 1420 | .toast-tab-mode { | 1420 | .toast-tab-mode { | ||
| 1421 | background-color: var(--tab-mode-color); | 1421 | background-color: var(--tab-mode-color); | ||
| 1422 | - | color: #ffffff; | 1422 | + | color: var(--tab-mode-text); |
| 1423 | } | 1423 | } | ||
| 1424 | 1424 | ||||
| 1425 | .toast-session-mode { | 1425 | .toast-session-mode { | ||
| 1426 | background-color: var(--session-mode-color); | 1426 | background-color: var(--session-mode-color); | ||
| 1427 | - | color: #ffffff; | 1427 | + | color: var(--session-mode-text); |
| 1428 | } | 1428 | } | ||
| 1429 | 1429 | ||||
| 1430 | .toast-resize-mode { | 1430 | .toast-resize-mode { | ||
| 1431 | background-color: var(--resize-mode-color); | 1431 | background-color: var(--resize-mode-color); | ||
| 1432 | - | color: #ffffff; | 1432 | + | color: var(--resize-mode-text); |
| 1433 | } | 1433 | } | ||
| 1434 | ` | 1434 | ` | ||
| 1435 | } | 1435 | } | ||
| @@ -1461,7 +1461,7 @@ func generateLinkStatusCSS(p Palette) string { | |||||
| 1461 | 1461 | ||||
| 1462 | /* Link status label text */ | 1462 | /* Link status label text */ | ||
| 1463 | .link-status label { | 1463 | .link-status label { | ||
| 1464 | - | color: var(--muted); | 1464 | + | color: var(--control-muted); |
| 1465 | } | 1465 | } | ||
| 1466 | ` | 1466 | ` | ||
| 1467 | } | 1467 | } | ||
M internal/ui/theme/mode_legend_css.go +12 -13
| @@ -5,13 +5,13 @@ import ( | |||
| 5 | 5 | "strings" | |
| 6 | 6 | ) | |
| 7 | 7 | ||
| 8 | - | // modeLegendColors maps legend mode classes to the palette variable of their mode. | |
| 9 | - | var modeLegendColors = []struct{ mode, color string }{ | |
| 10 | - | {"pane", "--pane-mode-color"}, | |
| 11 | - | {"vim", "--vim-mode-color"}, | |
| 12 | - | {"resize", "--resize-mode-color"}, | |
| 13 | - | {"tab", "--tab-mode-color"}, | |
| 14 | - | {"session", "--session-mode-color"}, | |
| 8 | + | // modeLegendColors maps legend mode classes to the palette variables of their mode. | |
| 9 | + | var modeLegendColors = []struct{ mode, color, text string }{ | |
| 10 | + | {"pane", "--pane-mode-color", "--pane-mode-text"}, | |
| 11 | + | {"vim", "--vim-mode-color", "--vim-mode-text"}, | |
| 12 | + | {"resize", "--resize-mode-color", "--resize-mode-text"}, | |
| 13 | + | {"tab", "--tab-mode-color", "--tab-mode-text"}, | |
| 14 | + | {"session", "--session-mode-color", "--session-mode-text"}, | |
| 15 | 15 | } | |
| 16 | 16 | ||
| 17 | 17 | func generateModeLegendCSS() string { | |
| @@ -31,7 +31,6 @@ func generateModeLegendCSS() string { | |||
| 31 | 31 | font-family: var(--font-mono); | |
| 32 | 32 | font-size: 0.8125em; | |
| 33 | 33 | font-weight: bold; | |
| 34 | - | color: #ffffff; | |
| 35 | 34 | padding: 0.375em 0.75em; | |
| 36 | 35 | margin-bottom: 0.375em; | |
| 37 | 36 | } | |
| @@ -48,7 +47,7 @@ func generateModeLegendCSS() string { | |||
| 48 | 47 | font-family: var(--font-mono); | |
| 49 | 48 | font-size: 0.75em; | |
| 50 | 49 | font-weight: bold; | |
| 51 | - | color: var(--text); | |
| 50 | + | color: var(--control-text); | |
| 52 | 51 | background-color: var(--surface-variant); | |
| 53 | 52 | border-style: solid; | |
| 54 | 53 | border-width: 0.0625em; | |
| @@ -57,7 +56,7 @@ func generateModeLegendCSS() string { | |||
| 57 | 56 | margin-right: 0.375em; | |
| 58 | 57 | transition: background-color 120ms ease-out, color 120ms ease-out; | |
| 59 | 58 | } | |
| 60 | - | .mode-legend-description { font-size: 0.75em; color: var(--muted); } | |
| 59 | + | .mode-legend-description { font-size: 0.75em; color: var(--surface-muted); } | |
| 61 | 60 | .mode-legend-row.mode-legend-dim { opacity: 0.3; } | |
| 62 | 61 | @keyframes mode-legend-appear { | |
| 63 | 62 | from { opacity: 0; } | |
| @@ -66,11 +65,11 @@ func generateModeLegendCSS() string { | |||
| 66 | 65 | `) | |
| 67 | 66 | for _, m := range modeLegendColors { | |
| 68 | 67 | fmt.Fprintf(&sb, `.omnibox-container.mode-legend-panel.mode-legend-%[1]s { border-color: var(%[2]s); } | |
| 69 | - | .mode-legend-%[1]s .mode-legend-title { background-color: var(%[2]s); } | |
| 68 | + | .mode-legend-%[1]s .mode-legend-title { background-color: var(%[2]s); color: var(%[3]s); } | |
| 70 | 69 | .mode-legend-%[1]s .mode-legend-group-title { color: var(%[2]s); } | |
| 71 | 70 | .mode-legend-%[1]s .mode-legend-keycap { border-color: alpha(var(%[2]s), 0.6); } | |
| 72 | - | .mode-legend-%[1]s .mode-legend-keycap.mode-legend-flash { background-color: var(%[2]s); color: #ffffff; } | |
| 73 | - | `, m.mode, m.color) | |
| 71 | + | .mode-legend-%[1]s .mode-legend-keycap.mode-legend-flash { background-color: var(%[2]s); color: var(%[3]s); } | |
| 72 | + | `, m.mode, m.color, m.text) | |
| 74 | 73 | } | |
| 75 | 74 | return sb.String() | |
| 76 | 75 | } | |
| @@ -5,13 +5,13 @@ import ( | |||||
| 5 | "strings" | 5 | "strings" | ||
| 6 | ) | 6 | ) | ||
| 7 | 7 | ||||
| 8 | - | // modeLegendColors maps legend mode classes to the palette variable of their mode. | 8 | + | // modeLegendColors maps legend mode classes to the palette variables of their mode. |
| 9 | - | var modeLegendColors = []struct{ mode, color string }{ | 9 | + | var modeLegendColors = []struct{ mode, color, text string }{ |
| 10 | - | {"pane", "--pane-mode-color"}, | 10 | + | {"pane", "--pane-mode-color", "--pane-mode-text"}, |
| 11 | - | {"vim", "--vim-mode-color"}, | 11 | + | {"vim", "--vim-mode-color", "--vim-mode-text"}, |
| 12 | - | {"resize", "--resize-mode-color"}, | 12 | + | {"resize", "--resize-mode-color", "--resize-mode-text"}, |
| 13 | - | {"tab", "--tab-mode-color"}, | 13 | + | {"tab", "--tab-mode-color", "--tab-mode-text"}, |
| 14 | - | {"session", "--session-mode-color"}, | 14 | + | {"session", "--session-mode-color", "--session-mode-text"}, |
| 15 | } | 15 | } | ||
| 16 | 16 | ||||
| 17 | func generateModeLegendCSS() string { | 17 | func generateModeLegendCSS() string { | ||
| @@ -31,7 +31,6 @@ func generateModeLegendCSS() string { | |||||
| 31 | font-family: var(--font-mono); | 31 | font-family: var(--font-mono); | ||
| 32 | font-size: 0.8125em; | 32 | font-size: 0.8125em; | ||
| 33 | font-weight: bold; | 33 | font-weight: bold; | ||
| 34 | - | color: #ffffff; | |||
| 35 | padding: 0.375em 0.75em; | 34 | padding: 0.375em 0.75em; | ||
| 36 | margin-bottom: 0.375em; | 35 | margin-bottom: 0.375em; | ||
| 37 | } | 36 | } | ||
| @@ -48,7 +47,7 @@ func generateModeLegendCSS() string { | |||||
| 48 | font-family: var(--font-mono); | 47 | font-family: var(--font-mono); | ||
| 49 | font-size: 0.75em; | 48 | font-size: 0.75em; | ||
| 50 | font-weight: bold; | 49 | font-weight: bold; | ||
| 51 | - | color: var(--text); | 50 | + | color: var(--control-text); |
| 52 | background-color: var(--surface-variant); | 51 | background-color: var(--surface-variant); | ||
| 53 | border-style: solid; | 52 | border-style: solid; | ||
| 54 | border-width: 0.0625em; | 53 | border-width: 0.0625em; | ||
| @@ -57,7 +56,7 @@ func generateModeLegendCSS() string { | |||||
| 57 | margin-right: 0.375em; | 56 | margin-right: 0.375em; | ||
| 58 | transition: background-color 120ms ease-out, color 120ms ease-out; | 57 | transition: background-color 120ms ease-out, color 120ms ease-out; | ||
| 59 | } | 58 | } | ||
| 60 | - | .mode-legend-description { font-size: 0.75em; color: var(--muted); } | 59 | + | .mode-legend-description { font-size: 0.75em; color: var(--surface-muted); } |
| 61 | .mode-legend-row.mode-legend-dim { opacity: 0.3; } | 60 | .mode-legend-row.mode-legend-dim { opacity: 0.3; } | ||
| 62 | @keyframes mode-legend-appear { | 61 | @keyframes mode-legend-appear { | ||
| 63 | from { opacity: 0; } | 62 | from { opacity: 0; } | ||
| @@ -66,11 +65,11 @@ func generateModeLegendCSS() string { | |||||
| 66 | `) | 65 | `) | ||
| 67 | for _, m := range modeLegendColors { | 66 | for _, m := range modeLegendColors { | ||
| 68 | fmt.Fprintf(&sb, `.omnibox-container.mode-legend-panel.mode-legend-%[1]s { border-color: var(%[2]s); } | 67 | fmt.Fprintf(&sb, `.omnibox-container.mode-legend-panel.mode-legend-%[1]s { border-color: var(%[2]s); } | ||
| 69 | - | .mode-legend-%[1]s .mode-legend-title { background-color: var(%[2]s); } | 68 | + | .mode-legend-%[1]s .mode-legend-title { background-color: var(%[2]s); color: var(%[3]s); } |
| 70 | .mode-legend-%[1]s .mode-legend-group-title { color: var(%[2]s); } | 69 | .mode-legend-%[1]s .mode-legend-group-title { color: var(%[2]s); } | ||
| 71 | .mode-legend-%[1]s .mode-legend-keycap { border-color: alpha(var(%[2]s), 0.6); } | 70 | .mode-legend-%[1]s .mode-legend-keycap { border-color: alpha(var(%[2]s), 0.6); } | ||
| 72 | - | .mode-legend-%[1]s .mode-legend-keycap.mode-legend-flash { background-color: var(%[2]s); color: #ffffff; } | 71 | + | .mode-legend-%[1]s .mode-legend-keycap.mode-legend-flash { background-color: var(%[2]s); color: var(%[3]s); } |
| 73 | - | `, m.mode, m.color) | 72 | + | `, m.mode, m.color, m.text) |
| 74 | } | 73 | } | ||
| 75 | return sb.String() | 74 | return sb.String() | ||
| 76 | } | 75 | } | ||
M internal/ui/theme/palette.go +10 -0
| @@ -53,6 +53,11 @@ func (m ModeColors) ToCSSVars() string { | |||
| 53 | 53 | sb.WriteString(" --tab-mode-color: " + m.TabMode + ";\n") | |
| 54 | 54 | sb.WriteString(" --session-mode-color: " + m.SessionMode + ";\n") | |
| 55 | 55 | sb.WriteString(" --resize-mode-color: " + m.ResizeMode + ";\n") | |
| 56 | + | sb.WriteString(" --pane-mode-text: " + readableTextColor(m.PaneMode, "#ffffff") + ";\n") | |
| 57 | + | sb.WriteString(" --vim-mode-text: " + readableTextColor(m.VimMode, "#ffffff") + ";\n") | |
| 58 | + | sb.WriteString(" --tab-mode-text: " + readableTextColor(m.TabMode, "#ffffff") + ";\n") | |
| 59 | + | sb.WriteString(" --session-mode-text: " + readableTextColor(m.SessionMode, "#ffffff") + ";\n") | |
| 60 | + | sb.WriteString(" --resize-mode-text: " + readableTextColor(m.ResizeMode, "#ffffff") + ";\n") | |
| 56 | 61 | return sb.String() | |
| 57 | 62 | } | |
| 58 | 63 | ||
| @@ -273,6 +278,8 @@ func (p Palette) ToCSSVars() string { | |||
| 273 | 278 | sb.WriteString(" --surface: " + p.Surface + ";\n") | |
| 274 | 279 | sb.WriteString(" --surface-variant: " + p.SurfaceVariant + ";\n") | |
| 275 | 280 | sb.WriteString(" --control-text: " + readableTextColor(p.SurfaceVariant, p.Text) + ";\n") | |
| 281 | + | sb.WriteString(" --control-muted: " + readableTextColor(p.SurfaceVariant, p.Muted) + ";\n") | |
| 282 | + | sb.WriteString(" --surface-muted: " + readableTextColor(p.Surface, p.Muted) + ";\n") | |
| 276 | 283 | sb.WriteString(" --text: " + p.Text + ";\n") | |
| 277 | 284 | sb.WriteString(" --muted: " + p.Muted + ";\n") | |
| 278 | 285 | sb.WriteString(" --accent: " + p.Accent + ";\n") | |
| @@ -281,6 +288,9 @@ func (p Palette) ToCSSVars() string { | |||
| 281 | 288 | sb.WriteString(" --success: " + p.Success + ";\n") | |
| 282 | 289 | sb.WriteString(" --warning: " + p.Warning + ";\n") | |
| 283 | 290 | sb.WriteString(" --destructive: " + p.Destructive + ";\n") | |
| 291 | + | sb.WriteString(" --success-text: " + readableTextColor(p.Success, p.Background) + ";\n") | |
| 292 | + | sb.WriteString(" --warning-text: " + readableTextColor(p.Warning, p.Background) + ";\n") | |
| 293 | + | sb.WriteString(" --destructive-text: " + readableTextColor(p.Destructive, p.Background) + ";\n") | |
| 284 | 294 | return sb.String() | |
| 285 | 295 | } | |
| 286 | 296 | ||
| @@ -53,6 +53,11 @@ func (m ModeColors) ToCSSVars() string { | |||||
| 53 | sb.WriteString(" --tab-mode-color: " + m.TabMode + ";\n") | 53 | sb.WriteString(" --tab-mode-color: " + m.TabMode + ";\n") | ||
| 54 | sb.WriteString(" --session-mode-color: " + m.SessionMode + ";\n") | 54 | sb.WriteString(" --session-mode-color: " + m.SessionMode + ";\n") | ||
| 55 | sb.WriteString(" --resize-mode-color: " + m.ResizeMode + ";\n") | 55 | sb.WriteString(" --resize-mode-color: " + m.ResizeMode + ";\n") | ||
| 56 | + | sb.WriteString(" --pane-mode-text: " + readableTextColor(m.PaneMode, "#ffffff") + ";\n") | |||
| 57 | + | sb.WriteString(" --vim-mode-text: " + readableTextColor(m.VimMode, "#ffffff") + ";\n") | |||
| 58 | + | sb.WriteString(" --tab-mode-text: " + readableTextColor(m.TabMode, "#ffffff") + ";\n") | |||
| 59 | + | sb.WriteString(" --session-mode-text: " + readableTextColor(m.SessionMode, "#ffffff") + ";\n") | |||
| 60 | + | sb.WriteString(" --resize-mode-text: " + readableTextColor(m.ResizeMode, "#ffffff") + ";\n") | |||
| 56 | return sb.String() | 61 | return sb.String() | ||
| 57 | } | 62 | } | ||
| 58 | 63 | ||||
| @@ -273,6 +278,8 @@ func (p Palette) ToCSSVars() string { | |||||
| 273 | sb.WriteString(" --surface: " + p.Surface + ";\n") | 278 | sb.WriteString(" --surface: " + p.Surface + ";\n") | ||
| 274 | sb.WriteString(" --surface-variant: " + p.SurfaceVariant + ";\n") | 279 | sb.WriteString(" --surface-variant: " + p.SurfaceVariant + ";\n") | ||
| 275 | sb.WriteString(" --control-text: " + readableTextColor(p.SurfaceVariant, p.Text) + ";\n") | 280 | sb.WriteString(" --control-text: " + readableTextColor(p.SurfaceVariant, p.Text) + ";\n") | ||
| 281 | + | sb.WriteString(" --control-muted: " + readableTextColor(p.SurfaceVariant, p.Muted) + ";\n") | |||
| 282 | + | sb.WriteString(" --surface-muted: " + readableTextColor(p.Surface, p.Muted) + ";\n") | |||
| 276 | sb.WriteString(" --text: " + p.Text + ";\n") | 283 | sb.WriteString(" --text: " + p.Text + ";\n") | ||
| 277 | sb.WriteString(" --muted: " + p.Muted + ";\n") | 284 | sb.WriteString(" --muted: " + p.Muted + ";\n") | ||
| 278 | sb.WriteString(" --accent: " + p.Accent + ";\n") | 285 | sb.WriteString(" --accent: " + p.Accent + ";\n") | ||
| @@ -281,6 +288,9 @@ func (p Palette) ToCSSVars() string { | |||||
| 281 | sb.WriteString(" --success: " + p.Success + ";\n") | 288 | sb.WriteString(" --success: " + p.Success + ";\n") | ||
| 282 | sb.WriteString(" --warning: " + p.Warning + ";\n") | 289 | sb.WriteString(" --warning: " + p.Warning + ";\n") | ||
| 283 | sb.WriteString(" --destructive: " + p.Destructive + ";\n") | 290 | sb.WriteString(" --destructive: " + p.Destructive + ";\n") | ||
| 291 | + | sb.WriteString(" --success-text: " + readableTextColor(p.Success, p.Background) + ";\n") | |||
| 292 | + | sb.WriteString(" --warning-text: " + readableTextColor(p.Warning, p.Background) + ";\n") | |||
| 293 | + | sb.WriteString(" --destructive-text: " + readableTextColor(p.Destructive, p.Background) + ";\n") | |||
| 284 | return sb.String() | 294 | return sb.String() | ||
| 285 | } | 295 | } | ||
| 286 | 296 | ||||
M internal/ui/theme/palette_test.go +13 -0
| @@ -51,3 +51,16 @@ func TestPaletteToCSSVarsAddsReadableControlText(t *testing.T) { | |||
| 51 | 51 | t.Fatalf("ToCSSVars() did not add light control text for dark input background:\n%s", css) | |
| 52 | 52 | } | |
| 53 | 53 | } | |
| 54 | + | ||
| 55 | + | func TestModeColorsToCSSVarsAddsReadableModeText(t *testing.T) { | |
| 56 | + | colors := DefaultModeColors() | |
| 57 | + | colors.TabMode = "#ffe066" | |
| 58 | + | ||
| 59 | + | css := colors.ToCSSVars() | |
| 60 | + | if !strings.Contains(css, " --tab-mode-text: #000000;\n") { | |
| 61 | + | t.Fatalf("ToCSSVars() did not add dark text for light tab mode color:\n%s", css) | |
| 62 | + | } | |
| 63 | + | if !strings.Contains(css, " --session-mode-text: #ffffff;\n") { | |
| 64 | + | t.Fatalf("ToCSSVars() did not keep white text for dark session mode color:\n%s", css) | |
| 65 | + | } | |
| 66 | + | } | |
| @@ -51,3 +51,16 @@ func TestPaletteToCSSVarsAddsReadableControlText(t *testing.T) { | |||||
| 51 | t.Fatalf("ToCSSVars() did not add light control text for dark input background:\n%s", css) | 51 | t.Fatalf("ToCSSVars() did not add light control text for dark input background:\n%s", css) | ||
| 52 | } | 52 | } | ||
| 53 | } | 53 | } | ||
| 54 | + | ||||
| 55 | + | func TestModeColorsToCSSVarsAddsReadableModeText(t *testing.T) { | |||
| 56 | + | colors := DefaultModeColors() | |||
| 57 | + | colors.TabMode = "#ffe066" | |||
| 58 | + | ||||
| 59 | + | css := colors.ToCSSVars() | |||
| 60 | + | if !strings.Contains(css, " --tab-mode-text: #000000;\n") { | |||
| 61 | + | t.Fatalf("ToCSSVars() did not add dark text for light tab mode color:\n%s", css) | |||
| 62 | + | } | |||
| 63 | + | if !strings.Contains(css, " --session-mode-text: #ffffff;\n") { | |||
| 64 | + | t.Fatalf("ToCSSVars() did not keep white text for dark session mode color:\n%s", css) | |||
| 65 | + | } | |||
| 66 | + | } | |||