Files
Ely-GPUI-Components/src/tooling/tests/catalogs.rs
T
ZacharyZhang-NY d5271d03ea Tooling · Catalogs: token viewer, contrast audit; fg_subtle meets AA
DesignTokenViewer shows every token of the theme in the mode shown,
named as code reads it: colors with their hex, syntax, chart and
terminal colors, the type scale, radii, control and icon sizes,
elevations and spacing. A11yChecker audits each text color over the
surfaces it sits on at 4.5:1 and the focus ring and chart hues at
3:1, failures first. The audit found fg_subtle under 4.5:1 on hover
and overlay; it is #6f6d6a light and #8c8a87 dark now, and a test
holds all four Ely palettes to the audit. IconBrowser points to
forms::IconPicker and the ScreenshotTest Harness to the gallery's
capture, each with a section on the tooling page.
2026-09-28 08:23:39 -04:00

107 lines
3.4 KiB
Rust

use gpui::{
Context, IntoElement, ParentElement, Render, Rgba, Styled, TestAppContext, VisualTestContext,
Window, div, px,
};
use crate::{
forms::hex,
theme::{ControlSize, Density, Palette, Theme},
tooling::{A11yChecker, DesignTokenViewer},
};
/// gpui takes a static selector, so a formatted one is leaked.
fn shown(selector: &str, cx: &mut VisualTestContext) -> bool {
cx.debug_bounds(Box::leak(selector.into())).is_some()
}
struct Tokens;
impl Render for Tokens {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div().w(px(900.0)).child(DesignTokenViewer::new())
}
}
/// Each token shows its name as code reads it and its value in the mode shown; a changed theme shows through.
#[gpui::test]
fn the_viewer_names_each_token_with_its_value(cx: &mut TestAppContext) {
cx.update(Theme::init);
let (_, cx) = cx.add_window_view(|_, _| Tokens);
cx.run_until_parked();
let light = Palette::light(false);
let keyword = format!(
"token-colors.syntax.keyword-{}",
hex(Rgba::from(light.syntax.keyword))
);
let blue = format!(
"token-colors.hue(0) Blue-{}",
hex(Rgba::from(light.chart[0]))
);
for selector in [
"token-colors.fg_subtle-#6f6d6a",
&keyword,
&blue,
"token-TextSize::Sm-12",
"token-Radius::Md-6",
"token-ControlSize::Md-28",
"token-IconSize::Md-16",
"token-gap_2-8",
"token-Elevation::Modal",
] {
assert!(shown(selector, cx), "{selector}");
}
cx.update(|_, cx| {
Theme::update(cx, |theme| {
theme.colors = Palette::dark(false);
theme.density = Density::Compact;
})
});
cx.run_until_parked();
assert!(
shown("token-colors.fg_subtle-#8c8a87", cx),
"the dark palette"
);
let compact = cx.update(|window, cx| {
use crate::theme::ActiveTheme;
cx.theme()
.control_height(ControlSize::Md)
.to_pixels(window.rem_size())
});
assert_eq!(compact, px(24.0));
assert!(shown("token-ControlSize::Md-24", cx), "compact density");
}
struct Audit;
impl Render for Audit {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div().w(px(600.0)).child(A11yChecker::new())
}
}
/// Ely's palette passes; a color moved under its need fails, counted, and lists first.
#[gpui::test]
fn the_checker_counts_failures_first(cx: &mut TestAppContext) {
cx.update(Theme::init);
let (_, cx) = cx.add_window_view(|_, _| Audit);
cx.run_until_parked();
assert!(shown("contrast-summary-41-0", cx), "every pair passes");
assert!(shown("contrast-fg-bg-AAA", cx));
assert!(shown("contrast-fg_subtle-hover-AA", cx), "4.53:1 on hover");
assert!(shown("contrast-focus-surface-AA", cx));
assert!(shown("contrast-chart Blue-bg-AA", cx));
cx.update(|_, cx| Theme::update(cx, |theme| theme.colors.fg_subtle = theme.colors.bg));
cx.run_until_parked();
assert!(
shown("contrast-summary-41-5", cx),
"five surfaces under fg_subtle"
);
let failing = cx
.debug_bounds("contrast-fg_subtle-hover-Fails")
.expect("a failing row");
let passing = cx
.debug_bounds("contrast-fg-bg-AAA")
.expect("a passing row");
assert!(failing.top() < passing.top(), "failures list first");
}