From d2c68f18b01d950af6918367b8e8748ce5fdfc7d Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 25 Aug 2026 11:46:28 +0800 Subject: [PATCH] shell: widen spotlight's launcher schema for phase 6c (modes/sections/search geometry) [launcher].modes now lists calc/cmd/url alongside apps, sections is enabled, and two new keys (search_width/search_radius) let an embedded launcher theme declare its search-state capsule geometry, defaulting to the idle value when a theme omits them. Also gives spotlight's [bar.slots] a widget:left_of_stats entry so a Lua widget requesting that placement (e.g. git-branch-widget.lua) has a home instead of being silently dropped. --- bread-theme/assets/shell/spotlight/theme.toml | 48 +++++++++++++----- bread-theme/src/shell/manifest.rs | 13 ++++- bread-theme/src/shell/mod.rs | 50 +++++++++++++++++++ bread-theme/src/shell/types.rs | 13 +++++ 4 files changed, 109 insertions(+), 15 deletions(-) diff --git a/bread-theme/assets/shell/spotlight/theme.toml b/bread-theme/assets/shell/spotlight/theme.toml index f2dc39d..e7aa597 100644 --- a/bread-theme/assets/shell/spotlight/theme.toml +++ b/bread-theme/assets/shell/spotlight/theme.toml @@ -14,16 +14,13 @@ # palette's `pink` token for both accent_from and accent_to, never a literal # hex value). # -# What this builtin does NOT model (THEME_SYSTEM_PLAN.md phase 6 scope, task -# "OUT OF SCOPE" list — deferred to phase 6c): query modes (`=` calc, `>` -# command, `.` url) and result sections ("recent"/"apps") — `modes` stays -# `["apps"]` and `sections` stays `false`, same trivial values every other -# builtin already carries. The demo's `.searching .capsule { border-radius: -# 20px }` (22px collapsed, 20px while actively searching) also has no -# corresponding schema key — `[launcher].radius` is a single value, so this -# builtin uses the collapsed 22px; the 2px searching-state shrink is an -# unmodeled gap, not an oversight (see breadbar's launcher_entry/results -# task notes for where this is implemented in Rust instead). +# Phase 6c (this pass): query modes (`=` calc, `>` command, `.` url) and +# result sections ("recent"/"apps") are now implemented — `modes` lists all +# four and `sections` is `true`. The demo's `.searching .capsule` state +# (480px -> 520px width, 22px -> 20px radius) is modeled via two new +# `[launcher]` keys, `search_width`/`search_radius`, read only by +# `LauncherMode::Embedded` hosts (breadbar's capsule; unread by breadbox's +# overlay window, which stays `mode = "overlay"`). name = "Spotlight" id = "spotlight" @@ -84,7 +81,19 @@ layer = "top" [bar.slots] left = ["workspaces"] centre = ["launcher_entry"] -right = ["battery"] +# `widget:left_of_stats` (Phase 6c decision, see task notes): a Lua widget +# that requests this same placement (`bread-shared`'s `WidgetPlacement:: +# LeftOfStats`, e.g. a real user's `git-branch-widget.lua`) would otherwise +# be silently undeliverable under spotlight — no `[bar.slots]` entry named +# any `widget:*` key at all, so `reconcile_widgets` drops it every time +# (quietly, since the Phase 6b fix, but still dropped). Deliberately just +# this one alias, not all five liquid-motion carries: spotlight has no +# clock module to anchor `left_of_clock`/`right_of_clock` against and no +# workspace-adjacent affordance next to its compact dots, so adding those +# would clutter a launcher-focused capsule with slots nothing here asks +# for. `left_of_stats` sits right where `battery` already does, matching +# liquid-motion's own ordering (`widget:left_of_stats` before its module). +right = ["widget:left_of_stats", "battery"] drawer = ["launcher_results"] [modules.workspaces] @@ -118,8 +127,21 @@ icon_px = 22 row_anim = "none" rule = "none" footer = "count_apps" -sections = false -modes = ["apps"] +# Phase 6c: "recent" / "apps" headers in the idle (empty-query) drawer view +# — `bread_launcher::split_sections` groups the same already-loaded/sorted +# entries `LaunchHistory`'s counts already rank, no new tracking needed. +sections = true +# `04-spotlight.html`'s three prefixes: `=` calc, `>` command, `.` url — +# `bread_launcher::parse_query`/`eval_calc`/`filter_commands` implement the +# pure logic; breadbar's capsule wiring (main.rs) gates on this list so an +# unlisted prefix character just falls through to a literal "apps" query. +modes = ["apps", "calc", "cmd", "url"] +# `04-spotlight.html`: `.searching .capsule { width: 520px; border-radius: +# 20px }` vs the idle 480px/22px above — animated via +# `bread_theme::anim::spring_to` (width) and a `.searching` CSS class +# (radius) in breadbar's capsule wiring. +search_width = 520 +search_radius = 20 # Same five satellite namespaces as liquid-motion/glass-workbench, keyed # identically. This bar's edge sits at margin.top(16) + height(36) = 52px — diff --git a/bread-theme/src/shell/manifest.rs b/bread-theme/src/shell/manifest.rs index 998b1f6..724eb25 100644 --- a/bread-theme/src/shell/manifest.rs +++ b/bread-theme/src/shell/manifest.rs @@ -185,6 +185,8 @@ pub(super) struct RawLauncher { pub(super) footer: Option, pub(super) sections: Option, pub(super) modes: Option>, + pub(super) search_width: Option, + pub(super) search_radius: Option, } #[derive(Debug, serde::Deserialize)] @@ -374,13 +376,15 @@ fn resolve_launcher(theme_id: &str, l: Option<&RawLauncher>) -> anyhow::Result) -> anyhow::Result, + /// `LauncherMode::Embedded` only (theme 04/spotlight, plan §7 phase 6c): + /// the capsule's own width while a search is in progress + /// (`04-spotlight.html`: `.searching .capsule { width: 520px }` vs the + /// idle 480px). Defaults to `width` (no widen) for a theme that omits + /// it, so an `Overlay`-mode theme — which never reads this field at all + /// — and an `Embedded` theme that just doesn't want the widen both fall + /// back to "no change" rather than a hardcoded magic number. + pub search_width: i32, + /// `LauncherMode::Embedded` only: `border-radius` while searching + /// (`04-spotlight.html`: `.searching .capsule { border-radius: 20px }` + /// vs the collapsed 22px `radius`). Same default-to-`radius` fallback + /// reasoning as `search_width`. + pub search_radius: i32, } /// A satellite surface, keyed by layer-shell namespace in `[surfaces.*]` —