diff --git a/src/widget/radio/mod.rs b/src/widget/radio/mod.rs index 4a3002b..809c4fb 100644 --- a/src/widget/radio/mod.rs +++ b/src/widget/radio/mod.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2026 Liberux Labs, S. L. -use crate::types::{ Rect, WidgetId }; +use crate::types::{ Length, Rect, WidgetId }; use crate::render::Canvas; use super::Element; @@ -48,6 +48,8 @@ pub struct Radio pub( crate ) label: Option, /// Optional stable identifier for focus management. pub( crate ) id: Option, + /// Optional override of the theme row height. + pub( crate ) height: Option, } impl Radio @@ -55,7 +57,7 @@ impl Radio /// Create a radio in the given state, with no label and no callback. pub fn new( selected: bool ) -> Self { - Self { selected, on_select: None, label: None, id: None } + Self { selected, on_select: None, label: None, id: None, height: None } } /// Set the message emitted when this option is picked. The @@ -81,6 +83,17 @@ impl Radio self } + /// Override the preferred height (default: the theme row height, + /// [`theme::HEIGHT`] design px). Accepts any [`Length`] so dense + /// layouts can tie the row height to the viewport. The resolved + /// value is floored at the outer circle size so the ring never + /// clips; the circle keeps its theme size and stays centred. + pub fn height( mut self, h: impl Into ) -> Self + { + self.height = Some( h.into() ); + self + } + pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> (f32, f32) { let outer = canvas.geom_px( theme::OUTER_SIZE ); @@ -91,7 +104,12 @@ impl Radio } else { outer.min( max_width ) }; - ( w, canvas.geom_px( theme::HEIGHT ) ) + let h = match self.height + { + Some( l ) => canvas.resolve_geom( l ).max( outer ), + None => canvas.geom_px( theme::HEIGHT ), + }; + ( w, h ) } /// Focus ring on the outer circle extends `FOCUS_W + 2 + FOCUS_W/2 ≈ 6.5 px` @@ -159,6 +177,7 @@ impl Radio on_select: self.on_select.map( |m| ( *f )( m ) ), label: self.label, id: self.id, + height: self.height, } } } diff --git a/src/widget/toggle/mod.rs b/src/widget/toggle/mod.rs index 7c8890f..5e17be3 100644 --- a/src/widget/toggle/mod.rs +++ b/src/widget/toggle/mod.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2026 Liberux Labs, S. L. -use crate::types::{ Rect, WidgetId }; +use crate::types::{ Length, Rect, WidgetId }; use crate::render::Canvas; use super::Element; @@ -46,6 +46,8 @@ pub struct Toggle pub( crate ) label: Option, /// Optional stable identifier for focus management. pub( crate ) id: Option, + /// Optional override of the theme row height. + pub( crate ) height: Option, } impl Toggle @@ -56,7 +58,7 @@ impl Toggle /// widget tree, otherwise the toggle is decorative. pub fn new( value: bool ) -> Self { - Self { value, on_toggle: None, label: None, id: None } + Self { value, on_toggle: None, label: None, id: None, height: None } } /// Set the message emitted when the toggle is activated (tap, Enter or @@ -85,6 +87,17 @@ impl Toggle self } + /// Override the preferred height (default: the theme row height, + /// [`theme::HEIGHT`] design px). Accepts any [`Length`] so dense + /// layouts can tie the row height to the viewport. The resolved + /// value is floored at the track height so the pill never clips; + /// the track keeps its theme size and stays vertically centred. + pub fn height( mut self, h: impl Into ) -> Self + { + self.height = Some( h.into() ); + self + } + /// Return the preferred `(width, height)` given available `max_width`. /// /// Width is `track_width` for an unlabelled toggle, or @@ -100,7 +113,12 @@ impl Toggle } else { track_w.min( max_width ) }; - ( w, canvas.geom_px( theme::HEIGHT ) ) + let h = match self.height + { + Some( l ) => canvas.resolve_geom( l ).max( canvas.geom_px( theme::TRACK_H ) ), + None => canvas.geom_px( theme::HEIGHT ), + }; + ( w, h ) } /// Bounding box of everything painted at `rect` across all states. The @@ -179,6 +197,7 @@ impl Toggle on_toggle: self.on_toggle.map( |m| ( *f )( m ) ), label: self.label, id: self.id, + height: self.height, } } }