fix: pick panel text colour by higher WCAG contrast (#4, I-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2e8ab31bbd
commit
081b4691fc
@ -841,8 +841,10 @@ CLIENT_COLORS_JS = """function panelColors(bg) {
|
|||||||
bg = bg.toLowerCase();
|
bg = bg.toLowerCase();
|
||||||
const rgb = h => [1, 3, 5].map(i => parseInt(h.slice(i, i + 2), 16));
|
const rgb = h => [1, 3, 5].map(i => parseInt(h.slice(i, i + 2), 16));
|
||||||
const lin = c => (c /= 255) <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
const lin = c => (c /= 255) <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
||||||
const [r, g, b] = rgb(bg).map(lin); // относительная яркость по WCAG
|
const lum = h => { const [r, g, b] = rgb(h).map(lin); return 0.2126 * r + 0.7152 * g + 0.0722 * b; };
|
||||||
const fg = 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.4 ? '__LIGHT__' : '__DARK__';
|
const ratio = (a, c) => (Math.max(a, c) + 0.05) / (Math.min(a, c) + 0.05); // контраст по WCAG
|
||||||
|
const L = lum(bg); // текст — тот из двух, что контрастнее фону
|
||||||
|
const fg = ratio(lum('__LIGHT__'), L) > ratio(lum('__DARK__'), L) ? '__LIGHT__' : '__DARK__';
|
||||||
const f = rgb(fg), k = rgb(bg); // dim — как у темы: 60% текста, 40% фона
|
const f = rgb(fg), k = rgb(bg); // dim — как у темы: 60% текста, 40% фона
|
||||||
const dim = '#' + f.map((c, i) => Math.round(c * 0.6 + k[i] * 0.4).toString(16).padStart(2, '0')).join('');
|
const dim = '#' + f.map((c, i) => Math.round(c * 0.6 + k[i] * 0.4).toString(16).padStart(2, '0')).join('');
|
||||||
return {bg, fg, dim};
|
return {bg, fg, dim};
|
||||||
|
|||||||
@ -145,8 +145,10 @@ tmux; фон выставлен под тему Termius и держится ме
|
|||||||
- 2026-10-18 (план) — Копия скрипта для службы — `~/.local/share/claude-agents/claude_agents.py`,
|
- 2026-10-18 (план) — Копия скрипта для службы — `~/.local/share/claude-agents/claude_agents.py`,
|
||||||
отдельно от копии в AutoLaunch. Обоснование: служба не зависит от каталога iTerm2. Цена ошибки:
|
отдельно от копии в AutoLaunch. Обоснование: служба не зависит от каталога iTerm2. Цена ошибки:
|
||||||
два места при ручном обновлении (`install.sh` обновляет оба).
|
два места при ручном обновлении (`install.sh` обновляет оба).
|
||||||
- 2026-10-18 (план) — Текст на светлом фоне `#3b4a50`, порог — относительная яркость фона по WCAG
|
- 2026-10-18 (план) — Текст — `#3b4a50` (светлый фон) или `#aacace` (как в профиле, тёмный фон);
|
||||||
> 0.4; на тёмном фоне текст `#aacace` (как в профиле). Цена ошибки: подобрать другие значения.
|
выбирается тот, у которого выше коэффициент контраста WCAG `(Lmax+0.05)/(Lmin+0.05)` с фоном
|
||||||
|
(было: порог яркости > 0.4, на средних тонах давал ~1.5:1 — находка I-1). Цена ошибки:
|
||||||
|
на отдельных средних фонах контраст всё равно не дотянет до 4.5:1; подобрать другие цвета текста.
|
||||||
- 2026-10-18 (план) — Область нажатия ⚙, образцов и кнопок — не меньше 36×36 CSS px. Цена ошибки:
|
- 2026-10-18 (план) — Область нажатия ⚙, образцов и кнопок — не меньше 36×36 CSS px. Цена ошибки:
|
||||||
поправить размер после приёмки на iPad.
|
поправить размер после приёмки на iPad.
|
||||||
- 2026-10-18 (план) — В этой ветке заодно закрываются O-1 (устаревший docstring) и O-3
|
- 2026-10-18 (план) — В этой ветке заодно закрываются O-1 (устаревший docstring) и O-3
|
||||||
|
|||||||
@ -56,6 +56,13 @@ class ClientColors(unittest.TestCase):
|
|||||||
{"bg": "#002b36", "fg": "#aacace", "dim": "#668a91"},
|
{"bg": "#002b36", "fg": "#aacace", "dim": "#668a91"},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_text_colour_by_contrast(self):
|
||||||
|
cases = {"#a0a0a0": "#3b4a50", "#999999": "#3b4a50", "#6699cc": "#3b4a50", "#333333": "#aacace"}
|
||||||
|
js = ca.CLIENT_COLORS_JS + (
|
||||||
|
"\nconsole.log(JSON.stringify(%s.map(c => panelColors(c).fg)))" % json.dumps(list(cases)))
|
||||||
|
out = subprocess.run(["node", "-e", js], capture_output=True, text=True, check=True).stdout
|
||||||
|
self.assertEqual(json.loads(out), list(cases.values()))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user