git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commitfeff3600e08e71e241cea8943f9b4caa40880fb5
parent1984f5ca9b
authorLucas Galante <[email protected]>
date2026-08-06 13:08
style: segment buttons ride inside the full-width well

The recessed well spans the whole widget again (as before the button
rework); each segment is a RAISED plate within it, vertically inset 3px
— the dropdown's recessed-surround + raised-face pairing, per segment.

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

 src/widget/container/breadcrumb.rs | 47 ++++++++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/src/widget/container/breadcrumb.rs b/src/widget/container/breadcrumb.rs
index e2311b0..8b9f20b 100644
--- a/src/widget/container/breadcrumb.rs
+++ b/src/widget/container/breadcrumb.rs
@@ -160,13 +160,25 @@ impl Breadcrumb {
             .and_then(|s| s.logical)
     }
 
-    /// The per-segment button boxes as laid out for `rect`: (x, y, w, h). For flat-path
-    /// hosts (cce-files) that mirror each segment's beveled plate app-side — the
-    /// render_widget geometry path drops relief prims, same as the dropdown's inset.
+    /// Vertical margin between the widget's recessed well and each raised
+    /// segment button inside it.
+    const SEG_INSET_Y: f32 = 3.0;
+
+    /// The per-segment button boxes as laid out for `rect`: (x, y, w, h), inset
+    /// vertically so the raised plates sit within the widget's full-width well.
+    /// For flat-path hosts (cce-files) that mirror the plates app-side — the
+    /// render_widget geometry path drops relief prims, same as the dropdown's.
     pub fn segment_boxes(&self, rect: Rect) -> Vec<(f32, f32, f32, f32)> {
         self.visible_segs(rect)
             .iter()
-            .map(|vs| (vs.x, rect.y, vs.w, rect.height))
+            .map(|vs| {
+                (
+                    vs.x,
+                    rect.y + Self::SEG_INSET_Y,
+                    vs.w,
+                    (rect.height - 2.0 * Self::SEG_INSET_Y).max(0.0),
+                )
+            })
             .collect()
     }
 
@@ -195,21 +207,26 @@ impl Paint for Breadcrumb {
     }
 
     fn paint(&self, rect: Rect, ctx: &mut PaintCtx) {
-        // Each segment is its own button with beveled edges: under
-        // control_relief the DE's flush inset plate (groove ring + beveled
-        // lip, face level with the surface — the Button treatment); in the
-        // flat fallback a rounded fill per segment.
-        let radius = crate::layout::breadcrumb_corner_radius().min(rect.height * 0.5);
+        // The full-width recessed well defines the bar (as it always did);
+        // each segment is a RAISED button plate within it — the dropdown
+        // pairing (recessed surround + raised face), per-segment.
+        let radius = crate::layout::breadcrumb_corner_radius();
         let relief = crate::layout::control_relief();
-        let depth = crate::layout::bevel_width().min(rect.height * 0.2);
-        let segs = self.visible_segs(rect);
+        if relief {
+            let depth = crate::layout::bevel_width().min(rect.height * 0.2);
+            ctx.recess(rect, (radius, radius, radius, radius), depth);
+        }
 
-        for vs in &segs {
-            let seg_rect = Rect { x: vs.x, y: rect.y, width: vs.w, height: rect.height };
+        let segs = self.visible_segs(rect);
+        let boxes = self.segment_boxes(rect);
+        for (vs, &(sx, sy, sw, sh)) in segs.iter().zip(boxes.iter()) {
+            let seg_rect = Rect { x: sx, y: sy, width: sw, height: sh };
+            let r = radius.min(sh * 0.5);
             if relief {
-                ctx.inset_plate(seg_rect, (radius, radius, radius, radius), [0.0; 4], depth);
+                let seg_depth = crate::layout::bevel_width().min(sh * 0.2);
+                ctx.boss(seg_rect, (r, r, r, r), seg_depth);
             } else {
-                ctx.rounded_rect(seg_rect, radius, (true, true, true, true), self.bg_color());
+                ctx.rounded_rect(seg_rect, r, (true, true, true, true), self.bg_color());
             }
             if vs.logical.is_some() && vs.logical == self.hovered_seg {
                 ctx.quad(seg_rect, [1.0, 1.0, 1.0, 0.06]);