From 9b097218fde2d6886a10784c2757289e9a99383c Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 30 Jul 2026 20:01:47 +0800 Subject: [PATCH] bread-theme: fix libadwaita class collisions and restore boxed-list styling Two bare class selectors (.title, .subtitle) were colliding with libadwaita's own internal row/window-title label classes of the same name, causing every AdwActionRow/AdwSwitchRow/AdwSpinRow title to inherit the 1.4em heading size meant for app view-titles - the root cause of breadman settings' ~24px row-title bug found in design review. Renamed to .page-title/.page-subtitle (breadhelp, the only caller, updated separately). Also scoped a .boxed-list override so AdwPreferencesGroup's boxed-list GtkListBox gets its surface fill + radius back - the shared `list, listbox { background-color: transparent }` rule (needed for plain GTK4 sidebars) was stripping it with equal specificity. --- bread-theme/src/lib.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/bread-theme/src/lib.rs b/bread-theme/src/lib.rs index 5d1ff7f..fd50c53 100644 --- a/bread-theme/src/lib.rs +++ b/bread-theme/src/lib.rs @@ -166,9 +166,20 @@ pub fn stylesheet(p: &Palette) -> String { would override a container's colour on its own child labels. */\n\ window {{ background-color: @bg; color: @on-bg; }}\n\ .dim-label, .dim {{ opacity: 0.6; font-size: {sec}px; }}\n\ - .title {{ font-size: 1.4em; font-weight: bold; }}\n\ + /* Named `.page-title`, not the more obvious `.title` - libadwaita's\ + own row/window-title widgets (AdwActionRow, AdwWindowTitle, GtkHeaderBar)\ + put a bare `title` CSS class on their internal label, so a generic\ + `.title` rule here would inflate every libadwaita row's title text\ + to 1.4em too (this is exactly what caused the settings screen's\ + ~24px row-title bug). Scoping the name avoids the collision instead\ + of trying to out-specificity a first-party GTK/libadwaita class. */\n\ + .page-title {{ font-size: 1.4em; font-weight: bold; }}\n\ .heading {{ font-weight: bold; opacity: 0.85; }}\n\ - .subtitle {{ opacity: 0.7; font-size: {sec}px; }}\n\ + /* Same libadwaita-collision reasoning as `.page-title` above - a bare\ + `.subtitle` also matches libadwaita's internal row-subtitle labels.\ + Unused by any app today, but scoped so a future caller doesn't\ + reintroduce the fight. */\n\ + .page-subtitle {{ opacity: 0.7; font-size: {sec}px; }}\n\ button {{ background-color: @surface; color: @on-surface; border: none;\ border-radius: {r1}px; padding: {sm}px {lg}px; }}\n\ button:hover {{ background-color: alpha(@on-surface, 0.14); }}\n\ @@ -198,6 +209,14 @@ pub fn stylesheet(p: &Palette) -> String { scale trough highlight {{ background-color: @accent; border-radius: {pill}px; min-height: 6px; }}\n\ scale slider {{ background-color: @on-bg; border-radius: {pill}px; }}\n\ list, listbox {{ background-color: transparent; }}\n\ + /* libadwaita's AdwPreferencesGroup wraps its rows in a GtkListBox\ + carrying the `boxed-list` class, expecting a surface fill + radius\ + to read as a card. The bare-type rule above (needed so plain\ + GTK4 sidebars/lists stay transparent) was overriding that with\ + equal specificity and no fill ever won, leaving preference groups\ + as a bare bordered table instead of a card. This is scoped to the\ + class only, so it doesn't touch any non-adw list. */\n\ + list.boxed-list, listbox.boxed-list {{ background-color: @surface; border-radius: {r1}px; }}\n\ row {{ border-radius: {r2}px; }}\n\ row:selected, list row:selected {{ background-color: @accent; color: @on-accent; }}\n\ .sidebar {{ background-color: @surface; color: @on-surface; }}\n\ @@ -321,7 +340,7 @@ mod tests { assert!(css.contains(&format!("@define-color {name} ")), "missing @define-color {name}"); } // a representative spread of the shared component selectors - for sel in &["button", "entry", "switch:checked", ".card", ".sidebar", "scrollbar slider", ".title"] { + for sel in &["button", "entry", "switch:checked", ".card", ".sidebar", "scrollbar slider", ".page-title"] { assert!(css.contains(sel), "stylesheet missing selector: {sel}"); } assert!(css.contains("Varela Round"));