From a890ba6baf5d59ee46f26531adfa1d6274caeb17 Mon Sep 17 00:00:00 2001 From: Kaloyan Danchev Date: Sat, 24 Oct 2026 15:55:33 +0300 Subject: [PATCH] Clip glow to card inset and simplify slider modal UX Inset glow clip rects by 6px on all card types to prevent radial glow from bleeding past rounded corners. Simplify slider modal: remove close button (Back key closes), Left/Right adjust the focused slider, Up/Down move between sliders. Co-Authored-By: Claude Opus 4.6 --- src/state.rs | 16 ++-------------- src/view.rs | 28 +++++++++------------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/state.rs b/src/state.rs index 643cbe3..d7357b8 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1411,7 +1411,6 @@ impl State { match &self.focus { Target::HaSliderBrightness => match direction { - Direction::Up => self.focus(Target::HaSliderClose, controls), Direction::Down if has_color_temp => { self.focus(Target::HaSliderColorTemp, controls); } @@ -1429,10 +1428,6 @@ impl State { } _ => {} }, - Target::HaSliderClose => match direction { - Direction::Down => self.focus(Target::HaSliderBrightness, controls), - _ => {} - }, _ => {} } vec![] @@ -1821,15 +1816,8 @@ impl State { } } } - Target::HaSliderBrightness | Target::HaSliderColorTemp => { - // scroll handles these — OK does nothing on slider tracks - } - Target::HaSliderClose => { - self.ha.slider_open = false; - self.focus = Target::HaCard(self.ha.room, - self.ha.config.rooms[self.ha.room].cards.iter() - .position(|c| c.entity_id == self.ha.slider_entity) - .unwrap_or(0)); + Target::HaSliderBrightness | Target::HaSliderColorTemp | Target::HaSliderClose => { + // sliders adjusted via Left/Right/scroll — OK does nothing } Target::HaVacuumRoom(index) => { if index < self.ha.vacuum_selected.len() { diff --git a/src/view.rs b/src/view.rs index bac2415..00af35d 100644 --- a/src/view.rs +++ b/src/view.rs @@ -1909,14 +1909,14 @@ fn ha_toggle_card( let accent = ha_state_color(entity); let is_on = entity.is_some_and(|e| e.state == "on" || e.state == "open"); - // Radial glow from icon + // Radial glow from icon (inset clip to hide bleed past rounded corners) if is_on { let fill_color = ha_fill_color(&card.card_type, entity); let icon_cx = rect.x + 40.; let icon_cy = rect.y + 40.; let glow_size = 80.; let glow_rect = Rect::new(icon_cx - glow_size, icon_cy - glow_size, glow_size * 2., glow_size * 2.); - out.draw.push(Draw::Clip(Some(rect))); + out.draw.push(Draw::Clip(Some(rect.inset(6.)))); out.glow(glow_rect, glow_size, glow_size * 0.8, fill_color); out.draw.push(Draw::Clip(None)); } @@ -2001,7 +2001,7 @@ fn ha_range_card( c(0xbbbbbb, 0.5) }; - // Radial glow from icon center, clipped to card + // Radial glow from icon center, clipped to card (inset to hide corner bleed) if is_on && pct > 0 { let glow_alpha = (pct as f32 / 100.).clamp(0.1, 0.45); let glow_color = [accent[0], accent[1], accent[2], glow_alpha]; @@ -2009,7 +2009,7 @@ fn ha_range_card( let icon_cy = rect.y + 40.; let glow_size = 80.; let glow_rect = Rect::new(icon_cx - glow_size, icon_cy - glow_size, glow_size * 2., glow_size * 2.); - out.draw.push(Draw::Clip(Some(rect))); + out.draw.push(Draw::Clip(Some(rect.inset(6.)))); out.glow(glow_rect, glow_size, glow_size * 0.8, glow_color); out.draw.push(Draw::Clip(None)); } @@ -2096,7 +2096,7 @@ fn ha_climate_card( let icon_cy = rect.y + 40.; let glow_size = 80.; let glow_rect = Rect::new(icon_cx - glow_size, icon_cy - glow_size, glow_size * 2., glow_size * 2.); - out.draw.push(Draw::Clip(Some(rect))); + out.draw.push(Draw::Clip(Some(rect.inset(6.)))); out.glow(glow_rect, glow_size, glow_size * 0.8, glow_color); out.draw.push(Draw::Clip(None)); } @@ -2410,7 +2410,7 @@ fn ha_media_card( let art_cy = art_y + art_size / 2.; let glow_r = art_size; let glow_rect = Rect::new(art_cx - glow_r, art_cy - glow_r, glow_r * 2., glow_r * 2.); - out.draw.push(Draw::Clip(Some(rect))); + out.draw.push(Draw::Clip(Some(rect.inset(6.)))); out.glow(glow_rect, glow_r, glow_r * 0.7, [accent[0], accent[1], accent[2], glow_alpha]); out.draw.push(Draw::Clip(None)); } @@ -2529,7 +2529,7 @@ fn ha_cover_card( let fill_color = ha_fill_color(&card.card_type, entity); let glow_alpha = (open_pct * fill_color[3]).clamp(0.05, 0.40); let glow_color = [fill_color[0], fill_color[1], fill_color[2], glow_alpha]; - out.draw.push(Draw::Clip(Some(rect))); + out.draw.push(Draw::Clip(Some(rect.inset(6.)))); if is_curtain { // Curtain: glow from center of card let cx = rect.x + rect.w / 2.; @@ -2853,7 +2853,7 @@ fn ha_slider_modal(out: &mut Scene, state: &State, assets: &Assets) { let has_color_temp = matches!(card_type, HaCardType::Range) && entity.and_then(|e| e.attributes.get("color_temp")).is_some(); - let modal_h = if has_color_temp { 400. } else { 280. }; + let modal_h = if has_color_temp { 340. } else { 220. }; let modal = Rect::new(480., (1080. - modal_h) / 2., 960., modal_h); ha_glass(out, modal, false); @@ -2879,16 +2879,6 @@ fn ha_slider_modal(out: &mut Scene, state: &State, assets: &Assets) { false, ); - // Close button - let close_rect = Rect::new(modal.x + modal.w - 72., modal.y + 24., 40., 40.); - out.shape(close_rect, 20., c(0xffffff, 0.08)); - out.icon(assets, "close", close_rect.inset(10.), c(0xeeeeee, 0.7)); - let close_focused = state.focus == Target::HaSliderClose; - if close_focused { - out.border(close_rect.inset(-3.), 23., 2., WHITE); - } - out.control(Target::HaSliderClose, close_rect, false); - // Primary slider (brightness / temperature / position) let slider_y = modal.y + 88.; let slider_x = modal.x + 40.; @@ -2987,7 +2977,7 @@ fn ha_slider_modal(out: &mut Scene, state: &State, assets: &Assets) { // Hint text at bottom let hint_y = modal.y + modal_h - 44.; out.text( - "Scroll or ◀ ▶ to adjust", + "◀ ▶ to adjust · Back to close", Rect::new(slider_x, hint_y, slider_w, 20.), text(14., 400, -0.01), c(0xeeeeee, 0.4),