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

commit54b8393c80e92ca56326c21981cc35722361f2d9
parent53960abd35
authorLucas Galante <[email protected]>
date2026-08-20 16:03
Dropdowns: transparent face by default, trough offered to flat hosts

The DE-wide closed-dropdown treatment becomes the cce-files look: no
fill of its own — the control picks up whatever surface it sits on —
with the flush inset trough as its whole chrome. DROPDOWN_BACKGROUND_
COLOR's compiled default goes transparent (the modern paint's raw-alpha
judgment then carves edges only); a configured `dropdown color=` opts a
theme back into a filled face. The open menu is unaffected: draw_popover
already substitutes the opaque page-low plate when the fill is
transparent — the grown surface must cover the content beneath it.

Flat-path hosts never rendered any of this: render_widget replays
all_quads, which never carried the modern paint's relief prims, so
PageLayoutBuilder pages showed dropdowns as bare text (cce-files carved
its trough app-side to compensate — that workaround stands, its host
never implemented the hook). The bridge now offers each Dropdown's
trough through RenderTarget::inset_plate at the widget's laid-out rect:
relief-capable hosts carve it for real, tuple hosts degrade to a flat
rounded fill that the transparent default keeps invisible — no visual
change anywhere until a host opts in.

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

 src/color.rs  |  6 +++++-
 src/layout.rs | 21 ++++++++++++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/color.rs b/src/color.rs
index 67e3d64..4897ac4 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -53,7 +53,11 @@ static PAGE_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
 static LAYER_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
 static BACKPLATE_CORNER_RADIUS: RwLock<f32> = RwLock::new(12.0);
 
-static DROPDOWN_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 1.0]);
+// Transparent by default (alpha 0): a dropdown picks up the surface it sits
+// on, and its closed-state chrome is the flush inset trough alone — the
+// cce-files treatment, DE-wide. A configured `dropdown color=` opts a theme
+// back into a filled face (the paint path judges the RAW alpha).
+static DROPDOWN_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new([0.0, 0.0, 0.0, 0.0]);
 
 static TEXTBOX_PLACEHOLDER_TEXT_COLOR: RwLock<[u8; 3]> = RwLock::new([0x60, 0x60, 0x6a]);
 static TEXTBOX_BACKGROUND_COLOR: RwLock<[f32; 4]> = RwLock::new([0.08, 0.08, 0.12, 1.0]);
diff --git a/src/layout.rs b/src/layout.rs
index 6696214..500d873 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -3538,7 +3538,26 @@ pub fn render_widget<T: WidgetHost + 'static>(pc: &mut dyn RenderTarget, w: &mut
     let top_room = crate::widget::label_offset(w);
     wy += top_room;
     whh -= top_room;
- 
+
+    // The Dropdown's closed-state chrome is its modern paint's flush inset
+    // trough — relief prims the legacy `all_quads` stream never carried, so
+    // flat-path hosts rendered dropdowns as bare text (cce-files carved the
+    // trough app-side to compensate). Offer it through the RenderTarget hook:
+    // relief-capable hosts carve it for real; tuple hosts degrade to a flat
+    // rounded fill, invisible under the transparent default face.
+    if control_relief() && w.as_any().is::<crate::widget::Dropdown>() {
+        let depth = bevel_width().min(whh * 0.2);
+        pc.inset_plate(
+            crate::color::dropdown_background_color(),
+            wx,
+            wy,
+            www,
+            whh,
+            dropdown_corner_radius(),
+            depth,
+        );
+    }
+
     for (qx, qy, qw, qh, qc) in w.all_quads(ctx) {
         let extra_corners = (
             corners.0 && qx <= wx + 1.5 && qy <= wy + 1.5,