GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
feat: slide toggle button is glass — translucent fill, unconditional bevel
The gliding button's crossfaded state fill is knocked down to a
mostly-transparent tint (style.control.toggle.button_opacity, default
0.25) so the track and pane show through, and its beveled rim now draws in
both DE styles rather than only under control_relief — the rim is the
style's defining edge; the glass fill alone wouldn't read.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/layout.rs | 9 +++++++++
src/widget/input/checkbox.rs | 25 +++++++++++++++----------
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/src/layout.rs b/src/layout.rs
index 28d4371..d34e190 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -106,6 +106,7 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
"style.control.textbox.multiline.line_wrap" | "style.textbox.multiline.line_wrap" | "style.data.textbox.multiline.line_wrap" => "textbox_line_wrap",
"style.control.textbox.multiline.border_width" | "style.textbox.multiline.border_width" | "style.data.textbox.multiline.border_width" => "textbox_multiline_border_width",
"style.control.toggle.style" => "toggle_style",
+ "style.control.toggle.button_opacity" => "toggle_button_opacity",
"style.control.toggle.height" => "toggle_height",
"style.control.toggle.border_width" => "toggle_border_width",
"style.control.toggle.disabled_color" => "toggle_disabled_color",
@@ -1771,6 +1772,14 @@ pub fn toggle_slide() -> bool {
.is_some_and(|s| s == "slide")
}
+/// The slide toggle button's fill opacity (`style.control.toggle.button_opacity`):
+/// a mostly-transparent glass tint over the track — the beveled rim carries the
+/// button's read.
+pub fn toggle_button_opacity() -> f32 {
+ lazy_init_style_registry();
+ get_style_registry().read().unwrap().get_float("toggle_button_opacity").unwrap_or(0.25)
+}
+
/// The slider's render style: `style.control.slider.style = "band"` swaps the
/// track/fill/thumb for a thin full-range band that inflates smoothly at the
/// value (see `Slider::paint`). Anything else — or unset — keeps the default
diff --git a/src/widget/input/checkbox.rs b/src/widget/input/checkbox.rs
index 279e04f..1a4fcc7 100644
--- a/src/widget/input/checkbox.rs
+++ b/src/widget/input/checkbox.rs
@@ -291,7 +291,10 @@ impl Toggle {
}
/// The slide button's face color: the off/on state colors crossfaded by
- /// the animated position, so the fill morphs while the button glides.
+ /// the animated position, so the fill morphs while the button glides —
+ /// then knocked down to a mostly-transparent glass tint
+ /// (`style.control.toggle.button_opacity`): the beveled edges carry the
+ /// button's read, the fill is a whisper over the track.
pub fn slide_button_color(&self) -> [f32; 4] {
let off = colors::toggle_off_color();
let on = colors::toggle_on_color();
@@ -300,7 +303,7 @@ impl Toggle {
off[0] + (on[0] - off[0]) * t,
off[1] + (on[1] - off[1]) * t,
off[2] + (on[2] - off[2]) * t,
- off[3] + (on[3] - off[3]) * t,
+ (off[3] + (on[3] - off[3]) * t) * crate::layout::toggle_button_opacity(),
]
}
@@ -435,15 +438,17 @@ impl Paint for Toggle {
}
if let Some(btn) = self.slide_button(rect) {
let fill = self.slide_button_color();
- if radius > 0.0 {
- ctx.rounded_rect(btn, radius, (true, true, true, true), fill);
- } else {
- ctx.quad(btn, fill);
- }
- if self.raised {
- let depth = crate::layout::bevel_width().min(h * 0.2);
- ctx.boss_edges(btn, (radius, radius, radius, radius), depth, (true, true, true, true));
+ if fill[3] > 0.003 {
+ if radius > 0.0 {
+ ctx.rounded_rect(btn, radius, (true, true, true, true), fill);
+ } else {
+ ctx.quad(btn, fill);
+ }
}
+ // The beveled rim is the style's defining edge — the glass
+ // fill alone wouldn't read — so it draws in both DE styles.
+ let depth = crate::layout::bevel_width().min(h * 0.2);
+ ctx.boss_edges(btn, (radius, radius, radius, radius), depth, (true, true, true, true));
}
} else if self.raised {
// The rocker: two FLAT half faces (see `rocker_reliefs`) — the