git.lucas.co / cce-fonts
font browser

commit204e4ea37b541cd2c1531966ecb98ed70b4efee6
parent7f590a69df
authorLucas Galante <[email protected]>
date2026-09-01 12:49
scrollbars: designer raise/sink treatment on both panels

The font list and mid panel regions adopt the toolkit ScrollRegion's
sink-behind mode: idle the bar sinks under the region's translucent bg
fill, a scroll raises it over the rows, 0.7s of quiet sinks it back;
stood off the panel edge by the DE scrollbar inset. emit_region_quads
splits into bg (sunk layer rides inside push_quads) and a separate
emit_region_bar after the panel content, so the raised bar rides over
the rows instead of under them.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/main.rs | 46 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index e378f96..98f6f1f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -29,13 +29,25 @@ enum AppMessage {
     RefreshFonts,
 }
 
-/// The retired local ScrollRegion's `push_prims` look, verbatim: flat bg fill
-/// plus a flat scrollbar (the toolkit `ScrollRegion::push_prims` draws the
-/// bordered frame + pill bars, which this app's panels never had).
+/// The retired local ScrollRegion's flat bg fill (the toolkit
+/// `ScrollRegion::push_prims` draws the bordered frame + pill bars, which this
+/// app's panels never had). With the regions on sink-behind, `push_quads` also
+/// lays a sunk scrollbar UNDER the translucent fill; the raised layer is
+/// emitted separately, after the rows, by [`emit_region_bar`].
 fn emit_region_quads(r: &ScrollRegion, pc: &mut cce_ui::scene::paint::PaintCtx) {
     use cce_ui::scene::layout::Rect;
     let mut v = Vec::new();
     r.push_quads(&mut v);
+    for (x, y, w, h, c) in v {
+        pc.quad(Rect { x, y, width: w, height: h }, c);
+    }
+}
+
+/// The raised scrollbar layer (quiet while the bar is sunk): emitted after the
+/// panel content so the bar rides over the rows, the designer treatment.
+fn emit_region_bar(r: &ScrollRegion, pc: &mut cce_ui::scene::paint::PaintCtx) {
+    use cce_ui::scene::layout::Rect;
+    let mut v = Vec::new();
     r.push_scrollbar_quads(&mut v);
     for (x, y, w, h, c) in v {
         pc.quad(Rect { x, y, width: w, height: h }, c);
@@ -478,7 +490,9 @@ impl Application for TypefaceApp {
         let mut app = Self {
             keys: FontsKeys::load(),
             search_box,
-            list_region: ScrollRegion::new(0.0, 4.0),
+            list_region: ScrollRegion::new(0.0, 4.0)
+                .with_sink_behind(true)
+                .with_edge_inset(cce_ui::layout::scrollbar_inset()),
             list_item_h,
             font_buttons: Vec::new(),
             style_dropdown,
@@ -508,7 +522,9 @@ impl Application for TypefaceApp {
             scale_factor: 1.0,
             font_system: cce_ui::create_font_system_with_system_fonts(),
             needs_rebuild: true,
-            mid_region: ScrollRegion::new(0.0, 4.0),
+            mid_region: ScrollRegion::new(0.0, 4.0)
+                .with_sink_behind(true)
+                .with_edge_inset(cce_ui::layout::scrollbar_inset()),
             widgets_registered: false,
             ui_context: cce_ui::context::UiContext::new(),
         };
@@ -686,6 +702,18 @@ impl Application for TypefaceApp {
             self.needs_rebuild = true;
         }
 
+        // Raise/sink upkeep for the panel scrollbars: true while the
+        // post-scroll hold runs or on the depth flip, keeping frames coming
+        // so the sink actually renders.
+        if self.list_region.tick(dt) {
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+        if self.mid_region.tick(dt) {
+            *needs_rebuild = true;
+            self.needs_rebuild = true;
+        }
+
         if self.click_timer > 0.0 {
             self.click_timer -= dt;
         }
@@ -960,6 +988,14 @@ impl Application for TypefaceApp {
             self.push_alphabet_preview(&mut pc);
         }
 
+        // Raised scrollbars ride over the panel content (the sunk layers went
+        // under the region bg fills inside emit_region_quads); the style
+        // dropdown's popover still stacks above them.
+        emit_region_bar(&self.list_region, &mut pc);
+        if self.selected_family.is_some() {
+            emit_region_bar(&self.mid_region, &mut pc);
+        }
+
         if self.select_mode {
             let bar_y = h_f32 - select_bar_h - 10.0;
             // Draw bottom bar separator, side borders, and bottom border