bread-ecosystem/bread-theme/src/shell/builtin.rs
Breadway 8c5e42230a shell: add spotlight builtin (theme 04), dots/placeholder-clock schema, and anim::spring_to
- bread-theme:🐚 WorkspacesModule.dot_widths and ClockModule.placeholder_clock,
  resolved/validated in manifest.rs and modeled in types.rs, so a theme can
  actually configure dot-pill widths and an entry-as-clock placeholder
  instead of those staying schema-only.
- New compiled-in builtin "spotlight" (assets/shell/spotlight/), registered
  in builtin.rs so list() returns three themes: centred capsule window spec
  (anchors=[top] only, width=480, exclusive=none, keyboard=on_demand),
  workspaces.style=dots, clock.style=none+placeholder_clock, launcher.mode=
  embedded, drawer=[launcher_results]. Colours are palette token names
  (pink), never hex.
- bread-theme::anim::spring_to: a reusable TickCallback size-interpolation
  helper (GTK4 has no CSS width/height transition on a widget or layer-shell
  surface), generalized from WorkspaceTrail's existing ease/tick pattern, for
  breadbar's capsule-drawer expand/collapse.
- bread_launcher::LAUNCHER_APP: the launcher's one shared on-disk identity
  (cache/config/history), so breadbar's embedded capsule and breadbox's
  overlay window read and write the SAME cache and launch history rather
  than forking into two rankings of a user's apps.

Tests: +6 spotlight builtin tests (loads/in list/capsule window shape/
embedded mode/dots widths/flat-pink-not-hex), bread-theme --lib 63->69,
bread-launcher --lib unchanged at 18.
2026-08-31 15:14:44 +08:00

95 lines
3.5 KiB
Rust

//! The compiled-in themes (plan §11 phase 1/5: "**One** built-in manifest
//! (`liquid-motion`) describing the bar as it exists today", extended in
//! Phase 5 with `glass-workbench`, demo 02). Every file here is plain data,
//! not Rust — each `theme.toml` is the manifest text a user override would
//! otherwise supply, and each `<id>.css` is the CSS template `ShellTheme::css`
//! substitutes tokens into (see that method's doc comment for why this
//! template is a representative subset of `breadbar::theme::load_css`'s
//! full stylesheet rather than a byte-for-byte copy of it).
//!
//! All are read with `include_str!` so a broken build can't ship without
//! them, and so [`super`] never touches the filesystem for a builtin — it
//! must work identically whether or not `$XDG_CONFIG_HOME` exists at all.
pub const LIQUID_MOTION_ID: &str = "liquid-motion";
const LIQUID_MOTION_TOML: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/liquid-motion/theme.toml"
));
const LIQUID_MOTION_CSS: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/liquid-motion/liquid-motion.css"
));
pub const GLASS_WORKBENCH_ID: &str = "glass-workbench";
const GLASS_WORKBENCH_TOML: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/glass-workbench/theme.toml"
));
const GLASS_WORKBENCH_CSS: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/glass-workbench/glass-workbench.css"
));
pub const SPOTLIGHT_ID: &str = "spotlight";
const SPOTLIGHT_TOML: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/spotlight/theme.toml"
));
const SPOTLIGHT_CSS: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/shell/spotlight/spotlight.css"
));
/// One compiled-in theme's identity plus its two `include_str!`ed assets.
/// `id`/`name` are also duplicated inside `toml`'s own `id =`/`name =`
/// fields — kept here too so [`all`]/[`find`] can list/look up a builtin
/// without parsing TOML first (`super::list`'s builtin fallback entry, and
/// `super::find_source`'s existence check, both run before any manifest
/// parsing happens).
pub struct BuiltinTheme {
pub id: &'static str,
pub name: &'static str,
pub toml: &'static str,
pub css: &'static str,
}
/// Every compiled-in theme, in the order [`super::list`] should present
/// them. Adding a third builtin is one entry here plus its two asset files
/// — nothing else in `mod.rs` names a specific builtin id except the always-
/// -safe fallback ([`LIQUID_MOTION_ID`], deliberately still hardcoded at
/// its one call site in `super::resolve_builtin` — see that function's doc
/// comment for why that one reference must NOT become "whichever builtin is
/// listed first").
pub const ALL: &[BuiltinTheme] = &[
BuiltinTheme {
id: LIQUID_MOTION_ID,
name: "Liquid Motion",
toml: LIQUID_MOTION_TOML,
css: LIQUID_MOTION_CSS,
},
BuiltinTheme {
id: GLASS_WORKBENCH_ID,
name: "Glass Workbench",
toml: GLASS_WORKBENCH_TOML,
css: GLASS_WORKBENCH_CSS,
},
BuiltinTheme {
id: SPOTLIGHT_ID,
name: "Spotlight",
toml: SPOTLIGHT_TOML,
css: SPOTLIGHT_CSS,
},
];
/// Looks up a compiled-in theme by id — `None` means "not a builtin",
/// exactly like a miss in the user/system theme directories.
pub fn find(id: &str) -> Option<&'static BuiltinTheme> {
ALL.iter().find(|t| t.id == id)
}