capsule: keyboard open, query modes, sections, and search-state geometry (phase 6c)
Completes the spotlight capsule (theme 04), THEME_SYSTEM_PLAN.md §7: - Keyboard open (item A): a new launcher_command module subscribes to bread.command.box.open — only when the active theme's launcher is Embedded — and focuses launcher_entry on receipt, which the existing EventControllerFocus::connect_enter already turns into an open_fn() call, same path a mouse click into the entry takes. breadbox's own keybind-triggered launch now redirects to this same event under an embedded theme instead of stacking its overlay window on top (see the breadbox commit). - Click-away scrim (item B): open_fn/close_fn now show/hide panel.rs's dismiss surface via the new show_capsule_dismiss/hide_dismiss, and panels.set_on_dismiss(close_fn) wires a click-away into the capsule's own close path. The scrim's clickable region starts at a fixed offset (capsule row height + the drawer's own maximum content height, DRAWER_MAX_HEIGHT_PX) rather than the drawer's live height, so it can never geometrically overlap a rendered result row regardless of breadbar-dismiss's overlay layer always rendering above the bar's own. - Query modes (item C): connect_changed now runs bread_launcher::parse_query against the entry text and, when the parsed prefix is listed in [launcher].modes, swaps launcher_results.scroller for a new mode_list populated by populate_mode_list (calc result / filtered commands / an "open this URL" prompt). key_ctrl routes Up/Down/Return at whichever list is active; a `>`/`.` row's action runs through the new ModeAction enum (RunShell for a command's own fixed exec string, OpenUrl straight to xdg-open) so arbitrary typed text is never passed through a shell. - Sections (item D): ResultsList::new's new `sections` bool is threaded from [launcher].sections. - Search-state geometry (item E): root's own width now spring-animates between [launcher].width and .search_width (animate_capsule_width, same set_size_request-driven technique animate_drawer_height already uses), and a `.searching` class on root switches border-radius to .search_radius via a new CSS rule/transition in theme.rs. Also fixes a real bug this surfaced: drawer_target_height was measuring drawer_box itself, whose size_request is continuously overwritten by animate_drawer_height's own tick callback — GTK clamps a widget's measure() up to at least its own explicit size request, so switching from the (tall) app list to a one-row calc result measured the PREVIOUS frame's forced height instead of the new content's actual size. It now sums each visible child's own natural height directly, which also fixes the same latent issue for narrowing app-search results. screenshot.rs gains two new views (capsule-sections, capsule-calc) to exercise D and C's calc path.
This commit is contained in:
parent
c68ed0d7e9
commit
e52c507f32
4 changed files with 490 additions and 5 deletions
26
src/theme.rs
26
src/theme.rs
|
|
@ -75,6 +75,13 @@ fn load_css() -> String {
|
|||
// and unconditional-but-unused block below), so this being "accent" vs
|
||||
// "green" vs "pink" per theme has no visible effect on them.
|
||||
let accent_from = tokens.accent_from();
|
||||
// `[launcher].search_radius` (plan §7 phase 6c) — `LauncherMode::
|
||||
// Embedded` only (spotlight); `.launcher().radius` itself already
|
||||
// equals `radius_bar` for that theme (see its own theme.toml comment),
|
||||
// so a theme that omits `search_radius` gets `radius_search ==
|
||||
// radius_bar` here too, i.e. no visible shrink, matching bread-theme's
|
||||
// own "default to the idle value" fallback.
|
||||
let radius_search = format!("{}px", theme.launcher().search_radius);
|
||||
|
||||
// `tokens.bar_border()` (plan §11 Phase 5): "full" (default, liquid-
|
||||
// motion's floating island) draws a border on all four edges; "bottom"
|
||||
|
|
@ -170,7 +177,12 @@ fn load_css() -> String {
|
|||
@keyframes digit-flip {{ from {{ opacity: 0; margin-top: 7px; }} to {{ opacity: 1; margin-top: 0; }} }}\
|
||||
@keyframes caret-draw {{ from {{ margin-right: 200px; opacity: 0.2; }} to {{ margin-right: 4px; opacity: 1; }} }}\
|
||||
window.breadbar {{ background-color: alpha(@bg, {bg_alpha}); color: @on-bg;\
|
||||
border-radius: {radius_bar}; {window_border} }}\
|
||||
border-radius: {radius_bar}; {window_border}\
|
||||
transition: border-radius 0.3s {spring_settle}; }}\
|
||||
/* `[launcher].search_radius` (plan §7 phase 6c, spotlight only —\
|
||||
`launcher_entry` never gets focus under any other theme, so\
|
||||
`.searching` never lands on `window.breadbar` there). */\
|
||||
window.breadbar.searching {{ border-radius: {radius_search}; }}\
|
||||
/* `> box > centerbox`, not `> centerbox`: the root is a vbox (bar\
|
||||
row + drawer, plan §2) as of the `drawer` slot wiring — every\
|
||||
theme's centerbox is now one level deeper than before, this\
|
||||
|
|
@ -421,8 +433,18 @@ fn load_css() -> String {
|
|||
.bread-drawer row:selected {{ background-color: alpha(@{accent_from}, 0.18);\
|
||||
color: @on-bg; }}\
|
||||
.bread-drawer .app-name {{ font-size: 14px; font-weight: 500; }}\
|
||||
.bread-drawer .app-muted {{ opacity: 0.45; font-size: 11px; }}",
|
||||
.bread-drawer .app-muted {{ opacity: 0.45; font-size: 11px; }}\
|
||||
/* `[launcher].sections` (plan §7 phase 6c) — the idle drawer's\
|
||||
\"Recent\"/\"Apps\" group labels (`bread_launcher::gtk::\
|
||||
build_header_row`). Unconditional, same reasoning as every other\
|
||||
launcher rule above: only spotlight ever builds a row with this\
|
||||
class at all. */\
|
||||
.bread-drawer-section-header {{ padding: 6px 14px 2px; }}\
|
||||
.section-header-label {{ font-size: 11px; font-weight: 600;\
|
||||
letter-spacing: 0.08em; text-transform: uppercase;\
|
||||
opacity: 0.45; }}",
|
||||
radius = radius,
|
||||
radius_search = radius_search,
|
||||
radius_bar = radius_bar,
|
||||
radius_sm = radius_sm,
|
||||
radius_pill = radius_pill,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue