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

commit837547c375020434df084c0c0e1bccdc4d7548c5
parent80d50de46d
authorLucas Galante <[email protected]>
date2026-07-22 12:45
style: rocker faces reflect the DE light

Each flat half carries a uniform lighting overlay under its beveled
edges — the raised plateau's face catches the light (white), the
recessed floor sits in the surround's shade (black). Uniform, not a
gradient: a flat face has one normal, which is what keeps this the
flat-step read rather than the retired tilted-plane tints. Amplitude
rides bevel_depth so faces and walls answer to the same knob.

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

 src/widget/container/parameters_bg.rs |  3 ++-
 src/widget/input/checkbox.rs          | 40 ++++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index b806bcf..5374ff9 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -1024,7 +1024,8 @@ impl ParametersBg {
             } else if p.2 == "button" {
                 self.buttons[i].as_ref().map(|w| (w as &dyn WidgetHost, crate::layout::button_corner_radius(), true))
             } else if p.2 == "toggle" || p.2 == "checkbox" {
-                // The rocker's bg pill arrives through the rounded-quad view;
+                // The rocker's bg pill and its faces' uniform light overlays
+                // (`Toggle::face_light`) arrive through the rounded-quad view;
                 // the entries here are its two flat halves' beveled edges
                 // (`Toggle::rocker_reliefs`, exactly what the widget's own
                 // raised paint emits): the state half a raised plateau, the
diff --git a/src/widget/input/checkbox.rs b/src/widget/input/checkbox.rs
index cda7839..916e183 100644
--- a/src/widget/input/checkbox.rs
+++ b/src/widget/input/checkbox.rs
@@ -269,10 +269,10 @@ impl Toggle {
     /// The rocker's two halves over `rect` as FLAT relief steps: (half rect,
     /// per-corner radii, (top, right, bottom, left) walls, raised). The state
     /// half (top when on, bottom when off) is a plateau raised out of the
-    /// surface (raised → `boss_edges`), the other falls away (`recess_edges`)
-    /// — both faces stay flat and untinted, so the state reads entirely from
-    /// the beveled edges. The hinge wall is open on both so the halves meet
-    /// in a single step, not a double-shaded trough.
+    /// surface (raised → `boss_edges`), the other falls away (`recess_edges`).
+    /// Both faces stay flat — the lit read comes from `face_light`, not a
+    /// tilt gradient. The hinge wall is open on both so the halves meet in a
+    /// single step, not a double-shaded trough.
     pub fn rocker_reliefs(
         &self,
         rect: Rect,
@@ -287,6 +287,22 @@ impl Toggle {
         let (state, other) = if self.toggled { (top_half, bottom_half) } else { (bottom_half, top_half) };
         [(state.0, state.1, state.2, true), (other.0, other.1, other.2, false)]
     }
+
+    /// A rocker face's UNIFORM lighting overlay — flat faces under the same
+    /// DE light the bevels answer to: the raised plateau's face catches the
+    /// light (white), the recessed floor sits in the surround's shade
+    /// (black). Uniform because a flat face has one normal; the amplitude
+    /// rides `bevel_depth` — the knob that scales the walls' shading — so
+    /// faces and bevels brighten and flatten together (both go to zero at
+    /// depth 0, the mesa-flat config).
+    pub fn face_light(raised: bool) -> [f32; 4] {
+        let s = (crate::layout::bevel_depth() / 0.15).clamp(0.0, 2.0);
+        if raised {
+            [1.0, 1.0, 1.0, 0.08 * s]
+        } else {
+            [0.0, 0.0, 0.0, 0.14 * s]
+        }
+    }
 }
 
 impl Adapted<Toggle> {
@@ -348,10 +364,11 @@ impl Paint for Toggle {
         if self.raised {
             // The rocker: two FLAT half faces (see `rocker_reliefs`) — the
             // state half a raised plateau, the other recessed, hinge wall
-            // open so they meet in a single step. The faces carry no tint;
-            // the state reads entirely from the beveled edges. This is the
-            // physical read of the flat style's state gradient, which this
-            // style drops entirely.
+            // open so they meet in a single step. Each face carries its
+            // uniform `face_light` overlay (lit plateau, shaded floor) under
+            // the beveled edges, so faces reflect the same light the walls
+            // do. This is the physical read of the flat style's state
+            // gradient, which this style drops entirely.
             if bg[3] > 0.001 {
                 if radius > 0.0 {
                     ctx.rounded_rect(rect, radius, (true, true, true, true), bg);
@@ -359,6 +376,13 @@ impl Paint for Toggle {
                     ctx.quad(rect, bg);
                 }
             }
+            for (half, radii, _, raised) in self.rocker_reliefs(rect) {
+                let light = Self::face_light(raised);
+                if light[3] > 0.001 {
+                    let corners = (radii.0 > 0.0, radii.1 > 0.0, radii.2 > 0.0, radii.3 > 0.0);
+                    ctx.rounded_rect(half, radius, corners, light);
+                }
+            }
             let depth = crate::layout::bevel_width().min(h * 0.2);
             for (half, radii, walls, raised) in self.rocker_reliefs(rect) {
                 if raised {