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

commit166ff0fb0e25f4801698c2d6ddcfc58f6c1b2fd7
parent9ec0fe6d8e
authorLucas Galante <[email protected]>
date2026-07-23 11:54
fix: ListRow skips the border idiom — rows were painted the button border color

The flat Button paint draws a configured border as a FULL rect in the
border color with the fill inset 1px over it — an overdraw idiom that
only reads as a ring when the fill is opaque. ListRow's idle fill is
deliberately transparent, so with button border_color set (config:
#292c37ff) every idle row rendered as a full #292c37 panel — the
'alpha-zero row tint': not a blend quirk, but the border color showing
through, accidentally coupling list-row styling to the button border
config. ListRow now resolves its border to None (same reasoning as its
relief exemption): idle rows paint nothing, hover/selected tints render
as plain rounded fills. The square-corner arm also gains the
transparent-fill skip instead of emitting an invisible quad.

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

 src/widget/input/button.rs | 43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/src/widget/input/button.rs b/src/widget/input/button.rs
index ce7225a..6327bd1 100644
--- a/src/widget/input/button.rs
+++ b/src/widget/input/button.rs
@@ -271,26 +271,35 @@ impl Paint for Button {
         if self.raised && self.kind != ButtonKind::ListRow {
             let depth = crate::layout::bevel_width().min(h * 0.2);
             ctx.inset_plate(rect, (radius, radius, radius, radius), color, depth);
-        } else
-        // Background (+ optional configured border), split by radius exactly as the legacy
-        // `all_rounded_quads` (rounded) / `extra_quads` (square) overrides emitted it.
-        if radius > 0.0 {
-            if let Some(bc) = colors::button_border_color() {
-                ctx.rounded_rect(rect, radius, (true, true, true, true), bc);
-                ctx.rounded_rect(
-                    Rect { x: x + 1.0, y: y + 1.0, width: w - 2.0, height: h - 2.0 },
-                    (radius - 1.0).max(0.0),
-                    (true, true, true, true),
-                    color,
-                );
-            } else if color[3].abs() > 0.001 {
-                ctx.rounded_rect(rect, radius, (true, true, true, true), color);
-            }
         } else {
-            if let Some(bc) = colors::button_border_color() {
+            // ListRow also skips the border idiom below: it draws the border
+            // color as a FULL rect with the fill inset over it, which only
+            // reads as a 1px ring when the fill is opaque — a row's
+            // transparent idle fill left the whole row painted in the config
+            // button border_color (an accidental coupling).
+            let border_color = if self.kind == ButtonKind::ListRow {
+                None
+            } else {
+                colors::button_border_color()
+            };
+            // Background (+ optional configured border), split by radius exactly as the legacy
+            // `all_rounded_quads` (rounded) / `extra_quads` (square) overrides emitted it.
+            if radius > 0.0 {
+                if let Some(bc) = border_color {
+                    ctx.rounded_rect(rect, radius, (true, true, true, true), bc);
+                    ctx.rounded_rect(
+                        Rect { x: x + 1.0, y: y + 1.0, width: w - 2.0, height: h - 2.0 },
+                        (radius - 1.0).max(0.0),
+                        (true, true, true, true),
+                        color,
+                    );
+                } else if color[3].abs() > 0.001 {
+                    ctx.rounded_rect(rect, radius, (true, true, true, true), color);
+                }
+            } else if let Some(bc) = border_color {
                 ctx.quad(rect, bc);
                 ctx.quad(Rect { x: x + 1.0, y: y + 1.0, width: w - 2.0, height: h - 2.0 }, color);
-            } else {
+            } else if color[3].abs() > 0.001 {
                 ctx.quad(rect, color);
             }
         }