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

commit0da111cd819f1cf9e4bbea781b8692f86bcfc49c
parente0afb89d82
authorLucas Galante <[email protected]>
date2026-07-30 12:31
feat: band slider sits in a shape-conforming recessed well

The band appears INSET: a carve whose contour follows the drawn shape —
the thin band and the traveling bulge — a small gap outside it, shaded per
1px column from the same band_height_at profile the fill samples (the rect
recess prims can't follow a bell). Shadow inside the top contour, lit lip
outside the bottom, end walls closing the channel, amplitudes riding
bevel_depth like the rocker faces. Translucent shading columns use exact
widths: an overlap double-blends at every seam into visible ticks (the
opaque fill keeps its anti-AA overlap).

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

 src/widget/input/slider.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/src/widget/input/slider.rs b/src/widget/input/slider.rs
index 8943d9e..a228cc2 100644
--- a/src/widget/input/slider.rs
+++ b/src/widget/input/slider.rs
@@ -234,6 +234,62 @@ impl Slider {
         let cy = g.y + g.h * 0.5;
         let vx = g.track_x + self.value * g.track_w;
 
+        // The well: the band appears INSET — a carve whose contour follows the
+        // drawn shape (band + traveling bulge) a small gap outside it. The rect
+        // recess prims can't follow a bell, so the walls are hand-shaded per
+        // column from the same `band_height_at` profile the fill samples: a
+        // shadow band hugging the top contour, a lit band along the bottom
+        // (the DE light sits upper-left), stepped alphas like the legacy
+        // banded bevels, amplitude riding `bevel_depth` like the rocker's
+        // `face_light`.
+        const WELL_GAP: f32 = 4.0;
+        const WELL_WALL: f32 = 3.0;
+        const WALL_STEPS: usize = 3;
+        let strength = (crate::layout::bevel_depth() / 0.15).clamp(0.0, 2.0);
+        let a_dark = 0.32 * strength;
+        let a_light = 0.16 * strength;
+        let wx0 = g.track_x - WELL_GAP;
+        let wx1 = g.track_x + g.track_w + WELL_GAP;
+        // 1px columns, EXACT widths: translucent shading quads must not
+        // overlap (a seam double-blends into a visible tick) — unlike the
+        // opaque fill columns below, which overlap on purpose against AA gaps.
+        let cols = (wx1 - wx0).ceil().max(1.0) as i32;
+        let colw = (wx1 - wx0) / cols as f32;
+        let sub = WELL_WALL / WALL_STEPS as f32;
+        for i in 0..cols {
+            let x = wx0 + i as f32 * colw;
+            let xm = (x + colw * 0.5).clamp(g.track_x, g.track_x + g.track_w);
+            let c = self.band_height_at(g, xm) * 0.5 + WELL_GAP;
+            for k in 0..WALL_STEPS {
+                let fade = 1.0 - k as f32 / WALL_STEPS as f32;
+                // Shadow INSIDE the well below the top contour; the lit lip
+                // OUTSIDE below the bottom contour — the textbox-recess read.
+                ctx.quad(
+                    Rect { x, y: cy - c + k as f32 * sub, width: colw, height: sub },
+                    [0.0, 0.0, 0.0, a_dark * fade],
+                );
+                ctx.quad(
+                    Rect { x, y: cy + c + k as f32 * sub, width: colw, height: sub },
+                    [1.0, 1.0, 1.0, a_light * fade],
+                );
+            }
+        }
+        // End walls close the well: shadow inside the left end, the lit lip
+        // outside the right, same light.
+        let c0 = self.band_height_at(g, g.track_x) * 0.5 + WELL_GAP;
+        let c1 = self.band_height_at(g, g.track_x + g.track_w) * 0.5 + WELL_GAP;
+        for k in 0..WALL_STEPS {
+            let fade = 1.0 - k as f32 / WALL_STEPS as f32;
+            ctx.quad(
+                Rect { x: wx0 + k as f32 * sub, y: cy - c0, width: sub, height: 2.0 * c0 },
+                [0.0, 0.0, 0.0, a_dark * fade],
+            );
+            ctx.quad(
+                Rect { x: wx1 + k as f32 * sub, y: cy - c1, width: sub, height: 2.0 * c1 },
+                [1.0, 1.0, 1.0, a_light * fade],
+            );
+        }
+
         // Flat runs outside the bulge span.
         let l0 = g.track_x;
         let r1 = g.track_x + g.track_w;