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. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d2ac6c7753
commit
ed1014bc34
7 files changed
+153
-27
No files matched your search
@@ -224,4 +224,4 @@ Ely GPUI Component. A component library for GPUI, in light and dark.
|
|||||||
- 2026-09-28: QRCodeScanner proven with `rqrr` 0.11: the host hands in frames as `RenderImage`s, read off the main thread; gpui 0.2.2 has no camera.
|
- 2026-09-28: QRCodeScanner proven with `rqrr` 0.11: the host hands in frames as `RenderImage`s, read off the main thread; gpui 0.2.2 has no camera.
|
||||||
- 2026-09-28: WebView proven with `wry` 0.57: a child WKWebView over the window, placed from a canvas in prepaint at its box each frame and hidden once the box leaves the view. It draws above everything gpui paints and gpui's clipping does not reach it; gpui's test windows have no native handle, so the capture proves it.
|
- 2026-09-28: WebView proven with `wry` 0.57: a child WKWebView over the window, placed from a canvas in prepaint at its box each frame and hidden once the box leaves the view. It draws above everything gpui paints and gpui's clipping does not reach it; gpui's test windows have no native handle, so the capture proves it.
|
||||||
- 2026-09-28: InspectorOverlay is gpui's inspector drawn by Ely, `tooling::install_inspector`, in debug builds only, as gpui has it.
|
- 2026-09-28: InspectorOverlay is gpui's inspector drawn by Ely, `tooling::install_inspector`, in debug builds only, as gpui has it.
|
||||||
- 2026-09-28: `fg_subtle` meets 4.5:1 on every surface it sits on, #6f6d6a light and #8c8a87 dark; the contrast audit found #82807d and #858380 under it.
|
- 2026-09-28: every text color meets 4.5:1 on the surfaces it sits on: `fg_subtle` is #696764 light and #94928f dark, `syntax.comment` with it, and the light syntax's number, constant and attribute are #a3591b, #aa5529 and #9f5d12; the contrast audit found them under.
|
||||||
@@ -17,7 +17,7 @@ pub fn sections(window: &mut Window, cx: &mut App) -> Vec<AnyElement> {
|
|||||||
vec![
|
vec![
|
||||||
section(
|
section(
|
||||||
"DesignTokenViewer",
|
"DesignTokenViewer",
|
||||||
"Every token of the theme in the mode shown, each named as code reads it: the colors with their hex, the syntax, chart and terminal colors, the type scale, radii, control and icon sizes, elevations and the spacing steps.",
|
"The theme's shared colors and scales in the mode shown, each named as code reads it: every palette, syntax, chart and terminal color with its hex, and the type, radius, control, icon, avatar and container sizes, the elevations and the spacing steps.",
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.child(div().max_w(px(840.0)).child(DesignTokenViewer::new()))
|
.child(div().max_w(px(840.0)).child(DesignTokenViewer::new()))
|
||||||
@@ -56,7 +56,7 @@ pub fn sections(window: &mut Window, cx: &mut App) -> Vec<AnyElement> {
|
|||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
section(
|
section(
|
||||||
"A11yChecker",
|
"A11yChecker",
|
||||||
"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. Ely's palettes pass in both modes, with high contrast and without.",
|
"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 at 4.5:1, the focus ring and the chart hues beside the page at 3:1, failures first. Ely's palettes pass in both modes, with high contrast and without.",
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.child(div().max_w(px(560.0)).child(A11yChecker::new()))
|
.child(div().max_w(px(560.0)).child(A11yChecker::new()))
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ impl Palette {
|
|||||||
border_strong: c(0xcccac8),
|
border_strong: c(0xcccac8),
|
||||||
fg: c(0x181613),
|
fg: c(0x181613),
|
||||||
fg_muted: c(0x605d5a),
|
fg_muted: c(0x605d5a),
|
||||||
fg_subtle: c(0x6f6d6a),
|
fg_subtle: c(0x696764),
|
||||||
fg_disabled: c(0xacaaa8),
|
fg_disabled: c(0xacaaa8),
|
||||||
accent: c(0x181613),
|
accent: c(0x181613),
|
||||||
accent_hover: c(0x302d2b),
|
accent_hover: c(0x302d2b),
|
||||||
@@ -221,14 +221,14 @@ impl Palette {
|
|||||||
syntax: Syntax {
|
syntax: Syntax {
|
||||||
keyword: c(0x714ca6),
|
keyword: c(0x714ca6),
|
||||||
string: c(0x317a45),
|
string: c(0x317a45),
|
||||||
number: c(0xb3621e),
|
number: c(0xa3591b),
|
||||||
comment: c(0x82807d),
|
comment: c(0x696764),
|
||||||
function: c(0x2863ab),
|
function: c(0x2863ab),
|
||||||
type_name: c(0x1e7777),
|
type_name: c(0x1e7777),
|
||||||
constant: c(0xb1582b),
|
constant: c(0xaa5529),
|
||||||
property: c(0xa14759),
|
property: c(0xa14759),
|
||||||
tag: c(0xa14759),
|
tag: c(0xa14759),
|
||||||
attribute: c(0xa25f12),
|
attribute: c(0x9f5d12),
|
||||||
operator: c(0x605d5a),
|
operator: c(0x605d5a),
|
||||||
punctuation: c(0x605d5a),
|
punctuation: c(0x605d5a),
|
||||||
variable: c(0x181613),
|
variable: c(0x181613),
|
||||||
@@ -256,7 +256,7 @@ impl Palette {
|
|||||||
border_strong: c(0x413f3d),
|
border_strong: c(0x413f3d),
|
||||||
fg: c(0xf3f1f0),
|
fg: c(0xf3f1f0),
|
||||||
fg_muted: c(0xafadab),
|
fg_muted: c(0xafadab),
|
||||||
fg_subtle: c(0x8c8a87),
|
fg_subtle: c(0x94928f),
|
||||||
fg_disabled: c(0x5c5a58),
|
fg_disabled: c(0x5c5a58),
|
||||||
accent: c(0xf3f1f0),
|
accent: c(0xf3f1f0),
|
||||||
accent_hover: c(0xd9d7d5),
|
accent_hover: c(0xd9d7d5),
|
||||||
@@ -293,7 +293,7 @@ impl Palette {
|
|||||||
keyword: c(0xbba3e8),
|
keyword: c(0xbba3e8),
|
||||||
string: c(0x8ac596),
|
string: c(0x8ac596),
|
||||||
number: c(0xeaab78),
|
number: c(0xeaab78),
|
||||||
comment: c(0x858380),
|
comment: c(0x94928f),
|
||||||
function: c(0x85b6e9),
|
function: c(0x85b6e9),
|
||||||
type_name: c(0x84c9c8),
|
type_name: c(0x84c9c8),
|
||||||
constant: c(0xeda382),
|
constant: c(0xeda382),
|
||||||
|
|||||||
+45
-6
@@ -6,7 +6,7 @@ use gpui::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
data_display::{Badge, Tone},
|
data_display::{Badge, Tone},
|
||||||
devtools::{contrast, over},
|
devtools::{contrast, over},
|
||||||
theme::{ActiveTheme, HUE_NAMES, Palette, Radius, TextSize},
|
theme::{ActiveTheme, HUE_NAMES, Palette, Radius, Syntax, TextSize},
|
||||||
typography::{Ellipsis, literal, tabular},
|
typography::{Ellipsis, literal, tabular},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ const TEXT_PAIRS: &[(&str, &[&str])] = &[
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"fg_subtle",
|
"fg_subtle",
|
||||||
&["bg", "surface", "sunken", "overlay", "hover"],
|
&["bg", "surface", "sunken", "overlay", "hover", "active"],
|
||||||
),
|
),
|
||||||
("link", &["bg", "surface", "sunken"]),
|
("link", &["bg", "surface", "sunken"]),
|
||||||
("on_accent", &["accent", "accent_hover"]),
|
("on_accent", &["accent", "accent_hover"]),
|
||||||
@@ -38,6 +38,9 @@ const TEXT_PAIRS: &[(&str, &[&str])] = &[
|
|||||||
("info", &["bg", "info_subtle"]),
|
("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.
|
/// A color, what it stands on, the contrast between them, and the contrast it needs.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Check {
|
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> {
|
fn audit(palette: &Palette) -> Vec<Check> {
|
||||||
let check = |front: String, fg: Hsla, back: &'static str, need: f32| {
|
let check = |front: String, fg: Hsla, back: &'static str, need: f32| {
|
||||||
let bg = palette.token(back);
|
let bg = palette.token(back);
|
||||||
@@ -81,6 +84,16 @@ fn audit(palette: &Palette) -> Vec<Check> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(move |back| check(front.to_string(), palette.token(front), back, TEXT))
|
.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"]
|
let focus = ["bg", "surface"]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|back| check("focus".into(), palette.focus, back, MARK));
|
.map(|back| check("focus".into(), palette.focus, back, MARK));
|
||||||
@@ -92,10 +105,10 @@ fn audit(palette: &Palette) -> Vec<Check> {
|
|||||||
MARK,
|
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)]
|
#[derive(IntoElement, Default)]
|
||||||
pub struct A11yChecker;
|
pub struct A11yChecker;
|
||||||
|
|
||||||
@@ -206,7 +219,12 @@ mod tests {
|
|||||||
let checks = audit(&palette);
|
let checks = audit(&palette);
|
||||||
let subtle: Vec<&Check> = checks.iter().filter(|c| c.front == "fg_subtle").collect();
|
let subtle: Vec<&Check> = checks.iter().filter(|c| c.front == "fg_subtle").collect();
|
||||||
assert!(subtle.iter().all(|check| check.grade() == "Fails"));
|
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]
|
#[test]
|
||||||
@@ -225,6 +243,27 @@ mod tests {
|
|||||||
assert_eq!(grade("fg_muted"), Some("Fails"), "text at 3.3:1");
|
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]
|
#[test]
|
||||||
fn translucent_text_counts_as_it_shows() {
|
fn translucent_text_counts_as_it_shows() {
|
||||||
let mut palette = Palette::light(false);
|
let mut palette = Palette::light(false);
|
||||||
|
|||||||
@@ -37,8 +37,47 @@ fn the_viewer_names_each_token_with_its_value(cx: &mut TestAppContext) {
|
|||||||
"token-colors.hue(0) Blue-{}",
|
"token-colors.hue(0) Blue-{}",
|
||||||
hex(Rgba::from(light.chart[0]))
|
hex(Rgba::from(light.chart[0]))
|
||||||
);
|
);
|
||||||
|
let measures: [(&str, &[&str], &[u32]); 7] = [
|
||||||
|
(
|
||||||
|
"TextSize::",
|
||||||
|
&["Xs", "Sm", "Base", "Md", "Lg", "Xl", "Xxl", "Display"],
|
||||||
|
&[11, 12, 13, 14, 16, 20, 24, 32],
|
||||||
|
),
|
||||||
|
("Radius::", &["Sm", "Md", "Lg", "Xl"], &[4, 6, 8, 12]),
|
||||||
|
("ControlSize::", &["Sm", "Md", "Lg"], &[24, 28, 32]),
|
||||||
|
(
|
||||||
|
"IconSize::",
|
||||||
|
&["Xs", "Sm", "Md", "Lg", "Xl", "Xxl"],
|
||||||
|
&[12, 14, 16, 20, 24, 32],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"AvatarSize::",
|
||||||
|
&["Xs", "Sm", "Md", "Lg", "Xl"],
|
||||||
|
&[20, 24, 32, 40, 56],
|
||||||
|
),
|
||||||
|
("ContainerSize::", &["Sm", "Md", "Lg"], &[640, 960, 1200]),
|
||||||
|
(
|
||||||
|
"gap_",
|
||||||
|
&["1", "2", "3", "4", "6", "8"],
|
||||||
|
&[4, 8, 12, 16, 24, 32],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
for (kind, names, sizes) in measures {
|
||||||
|
for (name, size) in names.iter().zip(sizes) {
|
||||||
|
let selector = format!("token-{kind}{name}-{size}");
|
||||||
|
assert!(shown(&selector, cx), "{selector}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for level in ["Raised", "Floating", "Modal"] {
|
||||||
|
assert!(shown(&format!("token-Elevation::{level}"), cx), "{level}");
|
||||||
|
}
|
||||||
|
for (ix, name) in [(0, "black"), (15, "bright white")] {
|
||||||
|
let code = hex(Rgba::from(light.ansi[ix]));
|
||||||
|
let selector = format!("token-colors.ansi[{ix}] {name}-{code}");
|
||||||
|
assert!(shown(&selector, cx), "{selector}");
|
||||||
|
}
|
||||||
for selector in [
|
for selector in [
|
||||||
"token-colors.fg_subtle-#6f6d6a",
|
"token-colors.fg_subtle-#696764",
|
||||||
&keyword,
|
&keyword,
|
||||||
&blue,
|
&blue,
|
||||||
"token-TextSize::Sm-12",
|
"token-TextSize::Sm-12",
|
||||||
@@ -58,7 +97,7 @@ fn the_viewer_names_each_token_with_its_value(cx: &mut TestAppContext) {
|
|||||||
});
|
});
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
assert!(
|
assert!(
|
||||||
shown("token-colors.fg_subtle-#8c8a87", cx),
|
shown("token-colors.fg_subtle-#94928f", cx),
|
||||||
"the dark palette"
|
"the dark palette"
|
||||||
);
|
);
|
||||||
let compact = cx.update(|window, cx| {
|
let compact = cx.update(|window, cx| {
|
||||||
@@ -85,16 +124,23 @@ fn the_checker_counts_failures_first(cx: &mut TestAppContext) {
|
|||||||
cx.update(Theme::init);
|
cx.update(Theme::init);
|
||||||
let (_, cx) = cx.add_window_view(|_, _| Audit);
|
let (_, cx) = cx.add_window_view(|_, _| Audit);
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
assert!(shown("contrast-summary-41-0", cx), "every pair passes");
|
assert!(shown("contrast-summary-81-0", cx), "every pair passes");
|
||||||
assert!(shown("contrast-fg-bg-AAA", cx));
|
assert!(shown("contrast-fg-bg-AAA", cx));
|
||||||
assert!(shown("contrast-fg_subtle-hover-AA", cx), "4.53:1 on hover");
|
assert!(
|
||||||
|
shown("contrast-fg_subtle-active-AA", cx),
|
||||||
|
"a selected row's detail"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
shown("contrast-syntax.comment-hover-AA", cx),
|
||||||
|
"a comment on the current line"
|
||||||
|
);
|
||||||
assert!(shown("contrast-focus-surface-AA", cx));
|
assert!(shown("contrast-focus-surface-AA", cx));
|
||||||
assert!(shown("contrast-chart Blue-bg-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.update(|_, cx| Theme::update(cx, |theme| theme.colors.fg_subtle = theme.colors.bg));
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
assert!(
|
assert!(
|
||||||
shown("contrast-summary-41-5", cx),
|
shown("contrast-summary-81-6", cx),
|
||||||
"five surfaces under fg_subtle"
|
"six surfaces under fg_subtle"
|
||||||
);
|
);
|
||||||
let failing = cx
|
let failing = cx
|
||||||
.debug_bounds("contrast-fg_subtle-hover-Fails")
|
.debug_bounds("contrast-fg_subtle-hover-Fails")
|
||||||
|
|||||||
+44
-3
@@ -1,13 +1,14 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, App, FontWeight, Hsla, InteractiveElement, IntoElement, ParentElement, Pixels,
|
AnyElement, App, FontWeight, Hsla, InteractiveElement, IntoElement, ParentElement, Pixels,
|
||||||
Rems, RenderOnce, Rgba, Styled, Window, div, rems,
|
Rems, RenderOnce, Rgba, Styled, Window, div, relative, rems,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
forms::hex,
|
forms::hex,
|
||||||
primitives::{Icon, IconName},
|
primitives::{Icon, IconName},
|
||||||
theme::{
|
theme::{
|
||||||
ActiveTheme, ControlSize, Elevation, HUE_NAMES, IconSize, Palette, Radius, Syntax, TextSize,
|
ActiveTheme, AvatarSize, ContainerSize, ControlSize, Elevation, HUE_NAMES, IconSize,
|
||||||
|
Palette, Radius, Syntax, TextSize,
|
||||||
},
|
},
|
||||||
typography::{Ellipsis, literal, tabular},
|
typography::{Ellipsis, literal, tabular},
|
||||||
};
|
};
|
||||||
@@ -114,7 +115,7 @@ fn measure(name: String, size: Pixels, sample: impl IntoElement, cx: &App) -> An
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every token of the theme in the mode shown, each named as code reads it: the colors with their hex, the syntax, chart and terminal colors, the type scale, radii, control and icon sizes, elevations and gpui's spacing steps.
|
/// The theme's shared colors and scales in the mode shown, each named as code reads it: every palette, syntax, chart and terminal color with its hex, and the type, radius, control, icon, avatar and container sizes, the elevations and gpui's spacing steps. A chapter's own measures stay with the chapter.
|
||||||
#[derive(IntoElement, Default)]
|
#[derive(IntoElement, Default)]
|
||||||
pub struct DesignTokenViewer;
|
pub struct DesignTokenViewer;
|
||||||
|
|
||||||
@@ -213,6 +214,44 @@ impl RenderOnce for DesignTokenViewer {
|
|||||||
.bg(colors.surface);
|
.bg(colors.surface);
|
||||||
measure(format!("ControlSize::{name}"), at(height), sample, cx)
|
measure(format!("ControlSize::{name}"), at(height), sample, cx)
|
||||||
});
|
});
|
||||||
|
let avatars = [
|
||||||
|
(AvatarSize::Xs, "Xs"),
|
||||||
|
(AvatarSize::Sm, "Sm"),
|
||||||
|
(AvatarSize::Md, "Md"),
|
||||||
|
(AvatarSize::Lg, "Lg"),
|
||||||
|
(AvatarSize::Xl, "Xl"),
|
||||||
|
]
|
||||||
|
.map(|(size, name)| {
|
||||||
|
let side = theme.avatar_size(size);
|
||||||
|
let sample = div()
|
||||||
|
.size(side)
|
||||||
|
.rounded_full()
|
||||||
|
.border_1()
|
||||||
|
.border_color(colors.border_strong)
|
||||||
|
.bg(colors.sunken);
|
||||||
|
measure(format!("AvatarSize::{name}"), at(side), sample, cx)
|
||||||
|
});
|
||||||
|
let containers = [
|
||||||
|
(ContainerSize::Sm, "Sm"),
|
||||||
|
(ContainerSize::Md, "Md"),
|
||||||
|
(ContainerSize::Lg, "Lg"),
|
||||||
|
]
|
||||||
|
.map(|(size, name)| {
|
||||||
|
let width = theme.container_width(size);
|
||||||
|
let widest = theme.container_width(ContainerSize::Lg);
|
||||||
|
// Drawn at its share of the widest, so the bar stays inside the row.
|
||||||
|
let sample = div().relative().flex_1().h_2().child(
|
||||||
|
div()
|
||||||
|
.absolute()
|
||||||
|
.top_0()
|
||||||
|
.left_0()
|
||||||
|
.h_full()
|
||||||
|
.w(relative(width.0 / widest.0))
|
||||||
|
.rounded(theme.radius(Radius::Sm))
|
||||||
|
.bg(colors.border_strong),
|
||||||
|
);
|
||||||
|
measure(format!("ContainerSize::{name}"), at(width), sample, cx)
|
||||||
|
});
|
||||||
let icons = [
|
let icons = [
|
||||||
(IconSize::Xs, "Xs"),
|
(IconSize::Xs, "Xs"),
|
||||||
(IconSize::Sm, "Sm"),
|
(IconSize::Sm, "Sm"),
|
||||||
@@ -276,6 +315,8 @@ impl RenderOnce for DesignTokenViewer {
|
|||||||
.child(group("Radii", cx).children(radii))
|
.child(group("Radii", cx).children(radii))
|
||||||
.child(group("Controls", cx).children(controls))
|
.child(group("Controls", cx).children(controls))
|
||||||
.child(group("Icons", cx).children(icons))
|
.child(group("Icons", cx).children(icons))
|
||||||
|
.child(group("Avatars", cx).children(avatars))
|
||||||
|
.child(group("Containers", cx).children(containers))
|
||||||
.child(
|
.child(
|
||||||
group("Elevation", cx)
|
group("Elevation", cx)
|
||||||
.child(div().flex().flex_wrap().gap_6().p_2().children(elevations)),
|
.child(div().flex().flex_wrap().gap_6().p_2().children(elevations)),
|
||||||
|
|||||||
+2
-2
@@ -366,7 +366,7 @@
|
|||||||
|
|
||||||
## T43c Tooling · Catalogs
|
## T43c Tooling · Catalogs
|
||||||
|
|
||||||
- [x] DesignTokenViewer → `tooling::DesignTokenViewer`: every token of the theme in the mode shown, named as code reads it, with its value
|
- [x] DesignTokenViewer → `tooling::DesignTokenViewer`: the theme's shared colors and scales in the mode shown, named as code reads them, with their values
|
||||||
- [x] IconBrowser → `forms::IconPicker`: the library's icons, searchable
|
- [x] IconBrowser → `forms::IconPicker`: the library's icons, searchable
|
||||||
- [x] A11yChecker — contrast audit → `tooling::A11yChecker`: each text color over its surfaces at 4.5:1, the focus ring and chart hues beside the page at 3:1, failures first
|
- [x] A11yChecker — contrast audit → `tooling::A11yChecker`: each text color over its surfaces and each code color over the editor's at 4.5:1, the focus ring and chart hues beside the page at 3:1, failures first
|
||||||
- [x] ScreenshotTest Harness — self-capture; scripted input since T01 → `examples/gallery --capture`: every page light and dark, then its scripted states
|
- [x] ScreenshotTest Harness — self-capture; scripted input since T01 → `examples/gallery --capture`: every page light and dark, then its scripted states
|
||||||
Reference in new issue
Block a user