From 3a22b62694c894cc01605fbdf0611b719f7f9c54 Mon Sep 17 00:00:00 2001 From: Breadway Date: Wed, 26 Aug 2026 09:26:39 +0800 Subject: [PATCH] bread-theme: differentiate liquid-motion/glass-workbench launcher geometry per approved demos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two built-in launcher themes previously shared the same row radius, padding, icon treatment, and selection fill (only mode/width/top/radius/ icon_px were themed), so breadbox's overlay rendered as one launcher recoloured rather than two different instruments. Adds row_radius, row_inset, row_padding_v/h, icon_radius, search_font_size, search_padding_v/h, and selection_alpha to [launcher], all consumed by breadbox's build_css in the paired breadbox commit. Sets liquid-motion to the soft/roomy demo numbers (row radius 12, 28px icons, 22% selection alpha, Recent/Apps section headers) and glass-workbench to the dense/technical demo numbers (row radius 6, 22px icons, 28% selection alpha, flat list). Also wires up three previously-declared-but-unconsumed tokens (font_family, font_fallback, font_size_base) for breadbox's launcher panel specifically — scoped consumption, not the full ecosystem-wide font system replacement (breadbar/stylesheet() are unaffected). Updated the stale doc comments in types.rs/mod.rs and both theme.toml files to match, and updated the two existing launcher-geometry tests plus added a glass-workbench equivalent. Defaults for all new keys reproduce breadbox's pre-redesign hardcoded CSS values, so themes that don't set them (spotlight's capsule doesn't read any of this) are unaffected. --- .../assets/shell/glass-workbench/theme.toml | 44 +++++++---- .../assets/shell/liquid-motion/theme.toml | 76 +++++++++--------- bread-theme/src/shell/manifest.rs | 25 ++++++ bread-theme/src/shell/mod.rs | 54 ++++++++++--- bread-theme/src/shell/types.rs | 79 +++++++++++++++---- 5 files changed, 202 insertions(+), 76 deletions(-) diff --git a/bread-theme/assets/shell/glass-workbench/theme.toml b/bread-theme/assets/shell/glass-workbench/theme.toml index 1f54b23..2de1bdf 100644 --- a/bread-theme/assets/shell/glass-workbench/theme.toml +++ b/bread-theme/assets/shell/glass-workbench/theme.toml @@ -11,18 +11,21 @@ # — it is new, so demo fidelity is the only source of truth. See Phase 5's # task notes for the two exceptions: font (IBM Plex Sans is not installed on # the dev machine, so this renders in fallback until the user installs -# ttf-ibm-plex) and colour (the demo's #7a9a88 sage is a *flat* accent, so it -# maps to the palette's `green` token for both accent_from and accent_to — -# never a literal hex value, or pywal theming breaks). +# ttf-ibm-plex — this now matters for real: breadbox's launcher panel +# consumes font_family/font_fallback below, see [tokens]'s own note) and +# colour (the demo's #7a9a88 sage is a *flat* accent, so it maps to the +# palette's `green` token for both accent_from and accent_to — never a +# literal hex value, or pywal theming breaks). name = "Glass Workbench" id = "glass-workbench" [tokens] -# Declared-but-not-yet-consumed: see liquid-motion/theme.toml's identical -# note next to these three keys — neither breadbar nor breadbox reads them; -# the font that actually renders comes from bread_theme::stylesheet()'s own -# hardcoded constant instead. +# font_family/font_fallback/font_size_base are consumed by breadbox's +# launcher panel only (breadbox::main::build_css's entry.search/row rules — +# see Tokens::font_family's doc comment for the exact scope); breadbar's +# bar/chip/clock text still comes from bread_theme::stylesheet()'s own +# hardcoded FONT_FAMILY constant, unaffected by this key. font_family = "IBM Plex Sans" font_fallback = "Inter, Noto Sans, sans-serif" font_size_base = 13 @@ -91,21 +94,34 @@ format = "%H:%M" show_date = true [launcher] +# Glass Workbench — dense and technical, the deliberate opposite of Liquid +# Motion's soft/roomy numbers: a tight panel radius, snug row insets/padding, +# small 22px icons, a flat (no section headers) list, and a denser accent +# selection fill. Spec: bos-ui-demos/proposed/glass-workbench.html's `.bx` +# block. breadbox reads every key below now; see main.rs's build_css. mode = "overlay" width = 560 top = "64px" -radius = 12 -icon_px = 32 +radius = 10 +icon_px = 22 row_anim = "stagger" rule = "hairline" footer = "count_results" -# Declared-but-not-consumed, exactly like liquid-motion's own launcher block: -# breadbox's Phase 4b-i wiring only reads mode/width/top/radius/icon_px. -# row_anim/rule/footer are this theme's demo-derived aspirations breadbox -# does not implement yet; sections/modes describe today's actual (trivial, -# apps-only) behaviour but are equally unread by any code path. sections = false modes = ["apps"] +# `.bx .r { border-radius: 6px; margin: 0 6px; padding: 8px 10px }` +row_radius = 6 +row_inset = 6 +row_padding_v = 8 +row_padding_h = 10 +# `.bx .ico { border-radius: 5px }` (paired with icon_px = 22 above) +icon_radius = 5 +# `.bx .q { padding: 12px 15px; font-size: 14px }` +search_font_size = 14 +search_padding_v = 12 +search_padding_h = 15 +# `.bx .r.sel { background: rgba(accent, .28) }` +selection_alpha = 0.28 # Same four satellite namespaces as liquid-motion, keyed identically so the # two manifests validate against the same [compositor.*] keyspace. Offsets diff --git a/bread-theme/assets/shell/liquid-motion/theme.toml b/bread-theme/assets/shell/liquid-motion/theme.toml index 54fbd7e..1a05056 100644 --- a/bread-theme/assets/shell/liquid-motion/theme.toml +++ b/bread-theme/assets/shell/liquid-motion/theme.toml @@ -1,28 +1,31 @@ -# The compiled-in builtin theme (bread-theme/src/shell/builtin.rs). Describes -# breadbar/breadbox AS THEY EXIST TODAY, not the 01-liquid-motion.html demo — -# where the two disagree (bar side margin, launcher width/top, the two easing -# curves), this file follows the current Rust source, since Phase 2's -# acceptance test is pixel-identical rendering against today's bar. +# The compiled-in builtin theme (bread-theme/src/shell/builtin.rs). The bar +# side (workspaces/clock/chips/satellites) describes breadbar AS IT EXISTS +# TODAY, not the 01-liquid-motion.html demo — where the two disagree (bar +# side margin, the two easing curves), this file follows the current Rust +# source, since Phase 2's acceptance test is pixel-identical rendering +# against today's bar. The `[launcher]` table is the one exception: it now +# follows bos-ui-demos/proposed/liquid-motion.html's `.bx` block (the +# launcher-core redesign's spec) rather than breadbox's old, pre-redesign +# hardcoded CSS — see that section's own note. # # Sources: breadbar/src/main.rs:16-22 (BAR_* / CHIP_HEIGHT / ICON_PX consts), # breadbar/src/theme.rs (load_css's radius/pad/spring locals and the actual # CSS selectors), breadbar/src/{panel,osd}.rs and # breadbar/src/notifications/{popup,history}.rs (satellite window anchors, -# margins, namespaces), breadbox/breadbox/src/main.rs:341-346 (launcher -# margin/size), :151 (build_css's .launcher-bg radius), :174-193 (make_icon's -# set_pixel_size calls), ~/.config/hypr/scripts/ui/rules.lua (compositor -# rules). +# margins, namespaces), bos-ui-demos/proposed/liquid-motion.html (launcher), +# ~/.config/hypr/scripts/ui/rules.lua (compositor rules). name = "Liquid Motion" id = "liquid-motion" [tokens] -# Declared-but-not-yet-consumed: neither breadbar nor breadbox reads -# font_family/font_fallback/font_size_base. Both get the font that actually -# renders from bread_theme::stylesheet()'s own hardcoded FONT_FAMILY -# constant — a separate, ecosystem-wide system shared by every bread GUI, -# not this per-theme manifest. See Tokens::font_family's doc comment. -font_family = "Varela Round, sans-serif" +# font_family/font_fallback are now consumed, but only by breadbox's launcher +# panel (breadbox::main::build_css's entry.search/row font-family) — see +# Tokens::font_family's doc comment for the exact scope. breadbar's bar/chip/ +# clock text still comes from bread_theme::stylesheet()'s own hardcoded +# FONT_FAMILY constant, unaffected by this key. font_size_base is likewise +# now consumed for the launcher's row font-size only. +font_family = "Outfit, sans-serif" font_fallback = "sans-serif" font_size_base = 14 radius_bar = 16 @@ -100,35 +103,34 @@ format = "%H:%M" show_date = false [launcher] -# breadbox/breadbox/src/main.rs:341-344 sets vbox.set_margin_top(120) and -# vbox.set_size_request(600, -1) — the demo's "540px overlay, 16% top" is a -# design-doc approximation, not what the code does today. +# Liquid Motion / Glass Workbench redesign (bos-ui-demos/proposed/ +# liquid-motion.html's `.bx` block is the spec): soft and roomy — a big +# panel radius, generous row insets/padding, 28px icons, section headers, +# and a translucent (not solid) accent selection fill. breadbox reads every +# key below now; see main.rs's build_css for the consuming CSS. mode = "overlay" width = 600 top = "120px" -# .launcher-bg { border-radius: 8px } (build_css, main.rs:151) — corrected -# from an earlier demo-derived 20px; breadbox does not implement the demo's -# 20px rounding. -radius = 8 -# make_icon() (main.rs:174-193) calls img.set_pixel_size(32) on both the -# cached-texture (gio::File/gdk::Texture) path and the GTK icon-theme -# fallback path — corrected from a demo-derived 36px. -icon_px = 32 -# Declared-but-not-yet-consumed: breadbox's Phase 4b-i wiring reads only -# mode/width/top/radius/icon_px above; it does not read any of the five keys -# below. row_anim/rule/footer are demo-derived aspirations breadbox -# implements not at all today (no row entrance/exit animation, no -# rule/divider element between the search entry and the list, no footer -# widget summarizing app count). sections/modes happen to already describe -# today's actual (trivial) behaviour — one flat unsectioned list, plain app -# search with no calc/command/url modes — but are likewise unread by any -# code path; a real sections/modes implementation is Phase 5/6, same as the -# other three. +radius = 20 +icon_px = 28 row_anim = "flip" rule = "gradient" footer = "count_apps" -sections = false +sections = true modes = ["apps"] +# `.bx .r { border-radius: 12px; margin: 0 8px; padding: 10px 12px }` +row_radius = 12 +row_inset = 8 +row_padding_v = 10 +row_padding_h = 12 +# `.bx .ico { border-radius: 9px }` (paired with icon_px = 28 above) +icon_radius = 9 +# `.bx .q { padding: 16px 18px; font-size: 16px }` +search_font_size = 16 +search_padding_v = 16 +search_padding_h = 18 +# `.bx .r.sel { background: rgba(accent, .22) }` +selection_alpha = 0.22 # Keyed by layer-shell namespace, matching [compositor.*] below, so the two # tables share one keyspace and can be validated against each other. diff --git a/bread-theme/src/shell/manifest.rs b/bread-theme/src/shell/manifest.rs index 6f44c61..0bd8640 100644 --- a/bread-theme/src/shell/manifest.rs +++ b/bread-theme/src/shell/manifest.rs @@ -194,6 +194,15 @@ pub(super) struct RawLauncher { pub(super) modes: Option>, pub(super) search_width: Option, pub(super) search_radius: Option, + pub(super) row_radius: Option, + pub(super) row_inset: Option, + pub(super) row_padding_v: Option, + pub(super) row_padding_h: Option, + pub(super) icon_radius: Option, + pub(super) search_font_size: Option, + pub(super) search_padding_v: Option, + pub(super) search_padding_h: Option, + pub(super) selection_alpha: Option, } #[derive(Debug, serde::Deserialize)] @@ -411,6 +420,22 @@ fn resolve_launcher(theme_id: &str, l: Option<&RawLauncher>) -> anyhow::Result, /// `LauncherMode::Embedded` only (theme 04/spotlight, plan §7 phase 6c): @@ -214,6 +228,38 @@ pub struct Launcher { /// vs the collapsed 22px `radius`). Same default-to-`radius` fallback /// reasoning as `search_width`. pub search_radius: i32, + /// Result row `border-radius` (px) — `breadbox::main::build_css`'s + /// `row { border-radius: ... }`. Liquid Motion's soft 12px vs Glass + /// Workbench's dense 6px is the clearest single signal that the two + /// themes are different instruments, not one launcher recoloured. + pub row_radius: i32, + /// Result row horizontal inset (px) from the panel's edge — + /// `row { margin: 0 {row_inset}px; }`. Mirrors the demos' `.bx .r` + /// `margin: 0 Npx` rule (liquid-motion 8px, glass-workbench 6px). + pub row_inset: i32, + /// Result row vertical padding (px) — `row { padding: {row_padding_v}px + /// {row_padding_h}px; }`'s first component. + pub row_padding_v: i32, + /// Result row horizontal padding (px) — same rule's second component. + pub row_padding_h: i32, + /// Row icon `border-radius` (px) — `breadbox::main::build_css`'s + /// `image { border-radius: ...; }`, paired with `icon_px` for the + /// swatch's size. Liquid Motion's rounder 9px vs Glass Workbench's + /// tighter 5px. + pub icon_radius: i32, + /// Search entry font-size (px) — distinct from `tokens.font_size_base` + /// (which sizes the result rows): both demos give the search field a + /// larger face than its rows (liquid-motion 16 vs its rows' 14, + /// glass-workbench 14 vs its rows' 13). + pub search_font_size: i32, + /// Search entry vertical padding (px). + pub search_padding_v: i32, + /// Search entry horizontal padding (px). + pub search_padding_h: i32, + /// Selected/hovered row background: `alpha(@accent, selection_alpha)`. + /// Liquid Motion's softer 0.22 vs Glass Workbench's denser 0.28 — see + /// each demo's `.bx .r.sel` rule. + pub selection_alpha: f64, } /// A satellite surface, keyed by layer-shell namespace in `[surfaces.*]` — @@ -350,27 +396,28 @@ impl Tokens { } } - /// Declared-but-not-yet-consumed in production: neither breadbar nor - /// breadbox calls this accessor. Both get their actual rendered font - /// from [`crate::stylesheet`]'s own hardcoded `crate::tokens::FONT_FAMILY` - /// constant — a completely separate, ecosystem-wide font system shared - /// by every bread GUI (not just shell-themed ones), unrelated to this - /// per-theme manifest field. Setting `[tokens] font_family = "..."` in a - /// theme.toml today has zero effect on what actually renders; every - /// built-in theme sets this key anyway (see the "not yet consumed" note - /// next to it in each `theme.toml`), preserved as an honest declaration - /// of the demo's intended font pending someone deciding how (or - /// whether) a per-shell-theme font should override the ecosystem-wide - /// one — that's a design decision for whoever owns `stylesheet()`, not - /// a mechanical wire-up this crate can do to itself. + /// Consumed by `breadbox::main::build_css` for the launcher panel's + /// `font-family` (the `entry.search`/`row` rule) as of the + /// liquid-motion/glass-workbench redesign — combined with + /// [`Self::font_fallback`] into a CSS font stack. Still NOT consumed by + /// `breadbar` (bar/chip/clock text) or by [`crate::stylesheet`]'s + /// ecosystem-wide base rule, which still hardcodes + /// `crate::tokens::FONT_FAMILY` for every non-launcher widget — this is + /// a scoped, launcher-only wire-up, not the full "per-shell-theme font + /// everywhere" replacement a `stylesheet()` owner would need to decide + /// on separately. pub fn font_family(&self) -> String { self.str_or("font_family", crate::tokens::FONT_FAMILY) } - /// See [`Self::font_family`] — same "declared but never read" status. + /// See [`Self::font_family`] — same scoped (launcher-only) consumption, + /// appended after `font_family` in the CSS font stack breadbox builds. pub fn font_fallback(&self) -> String { self.str_or("font_fallback", "sans-serif") } - /// See [`Self::font_family`] — same "declared but never read" status. + /// Consumed by `breadbox::main::build_css` for the result rows' + /// `font-size` (the search entry uses `[launcher].search_font_size` + /// instead — both demos give the search field a larger face than its + /// rows). Still not read by `breadbar`. pub fn font_size_base(&self) -> i64 { self.int_or("font_size_base", crate::tokens::FONT_SIZE_BASE as i64) }