Tooling · Catalogs: the audit reads active and code; avatar and container sizes

The audit now holds fg_subtle on active, a selected row's fill, and
each syntax color over the editor's surface, a code block and the
current line. What it found is fixed at the source: fg_subtle is
#696764 light and #94928f dark, syntax.comment follows it, and the
light number, constant and attribute darken to #a3591b, #aa5529 and
#9f5d12. The token viewer adds avatar and container sizes, draws a
container at its share of the widest so it stays in its row, and
names what it shows: the shared colors and scales. Tests pin every
variant, the hue each chart row reads and the code rows.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-28 08:57:52 -04:00
1 parent d5271d03ea
commit a7e492f28e
7 files changed
+153 -27

No files matched your search

+45 -6
View File
@@ -6,7 +6,7 @@ use gpui::{
use crate::{
data_display::{Badge, Tone},
devtools::{contrast, over},
theme::{ActiveTheme, HUE_NAMES, Palette, Radius, TextSize},
theme::{ActiveTheme, HUE_NAMES, Palette, Radius, Syntax, TextSize},
typography::{Ellipsis, literal, tabular},
};
@@ -27,7 +27,7 @@ const TEXT_PAIRS: &[(&str, &[&str])] = &[
),
(
"fg_subtle",
&["bg", "surface", "sunken", "overlay", "hover"],
&["bg", "surface", "sunken", "overlay", "hover", "active"],
),
("link", &["bg", "surface", "sunken"]),
("on_accent", &["accent", "accent_hover"]),
@@ -38,6 +38,9 @@ const TEXT_PAIRS: &[(&str, &[&str])] = &[
("info", &["bg", "info_subtle"]),
];
/// The surfaces code sits on: the editor, a code block, the editor's current line.
const CODE: [&str; 3] = ["surface", "sunken", "hover"];
/// A color, what it stands on, the contrast between them, and the contrast it needs.
#[derive(Clone, Debug)]
struct Check {
@@ -63,7 +66,7 @@ impl Check {
}
}
/// Every pair in `palette`: its text over its surfaces at 4.5:1, the focus ring and the chart hues beside the page at 3:1.
/// Every pair in `palette`: its text over its surfaces and its code colors over the code surfaces at 4.5:1, the focus ring and the chart hues beside the page at 3:1.
fn audit(palette: &Palette) -> Vec<Check> {
let check = |front: String, fg: Hsla, back: &'static str, need: f32| {
let bg = palette.token(back);
@@ -81,6 +84,16 @@ fn audit(palette: &Palette) -> Vec<Check> {
.iter()
.map(move |back| check(front.to_string(), palette.token(front), back, TEXT))
});
let code = Syntax::NAMES.iter().flat_map(|name| {
CODE.iter().map(move |back| {
check(
format!("syntax.{name}"),
palette.syntax.token(name),
back,
TEXT,
)
})
});
let focus = ["bg", "surface"]
.into_iter()
.map(|back| check("focus".into(), palette.focus, back, MARK));
@@ -92,10 +105,10 @@ fn audit(palette: &Palette) -> Vec<Check> {
MARK,
)
});
text.chain(focus).chain(hues).collect()
text.chain(code).chain(focus).chain(hues).collect()
}
/// Audits the theme's contrast in the mode shown: each text color over the surfaces it sits on at 4.5:1, the focus ring and the chart hues beside the page at 3:1, failures first under a count. It reads the theme as it stands, an owner's palette and high contrast included.
/// Audits the theme's contrast in the mode shown: each text color over the surfaces it sits on and each code color over the editor's surfaces at 4.5:1, the focus ring and the chart hues beside the page at 3:1, failures first under a count. It reads the theme as it stands, an owner's palette and high contrast included.
#[derive(IntoElement, Default)]
pub struct A11yChecker;
@@ -206,7 +219,12 @@ mod tests {
let checks = audit(&palette);
let subtle: Vec<&Check> = checks.iter().filter(|c| c.front == "fg_subtle").collect();
assert!(subtle.iter().all(|check| check.grade() == "Fails"));
assert_eq!(checks.len(), 41, "31 text pairs, 2 for the ring, 8 hues");
assert_eq!(
checks.len(),
81,
"32 text pairs, 39 for code, 2 for the ring, 8 hues"
);
assert_eq!(subtle.len(), 6);
}
#[test]
@@ -225,6 +243,27 @@ mod tests {
assert_eq!(grade("fg_muted"), Some("Fails"), "text at 3.3:1");
}
#[test]
fn code_and_hues_read_their_own_colors() {
let mut palette = Palette::light(false);
palette.syntax.comment = palette.surface;
let checks = audit(&palette);
let failing: Vec<&str> = checks
.iter()
.filter(|check| !check.passes())
.map(|check| check.back)
.collect();
assert_eq!(
failing,
["surface", "sunken", "hover"],
"the comment over code"
);
for (ix, name) in crate::theme::HUE_NAMES.iter().enumerate() {
let hue = checks.iter().find(|c| c.front == format!("chart {name}"));
assert_eq!(hue.map(|check| check.fg), Some(palette.chart[ix]));
}
}
#[test]
fn translucent_text_counts_as_it_shows() {
let mut palette = Palette::light(false);