1#![allow(missing_docs)]
2
3use std::sync::Arc;
4
5use crate::prelude::*;
6
7/// A [`Checkbox`] that has a [`Label`].
8#[derive(IntoElement)]
9pub struct RadioWithLabel {
10 id: ElementId,
11 label: Label,
12 selected: bool,
13 on_click: Arc<dyn Fn(&bool, &mut Window, &mut App) + 'static>,
14}
15
16impl RadioWithLabel {
17 pub fn new(
18 id: impl Into<ElementId>,
19 label: Label,
20 selected: bool,
21 on_click: impl Fn(&bool, &mut Window, &mut App) + 'static,
22 ) -> Self {
23 Self {
24 id: id.into(),
25 label,
26 selected,
27 on_click: Arc::new(on_click),
28 }
29 }
30}
31
32impl RenderOnce for RadioWithLabel {
33 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
34 let inner_diameter = rems_from_px(6.);
35 let outer_diameter = rems_from_px(16.);
36 let border_width = rems_from_px(1.);
37 h_flex()
38 .id(self.id)
39 .gap(DynamicSpacing::Base08.rems(cx))
40 .group("")
41 .child(
42 div()
43 .size(outer_diameter)
44 .rounded(outer_diameter / 2.)
45 .border_color(cx.theme().colors().border)
46 .border(border_width)
47 .group_hover("", |el| el.bg(cx.theme().colors().element_hover))
48 .when(self.selected, |el| {
49 el.child(
50 div()
51 .m((outer_diameter - inner_diameter) / 2. - border_width)
52 .size(inner_diameter)
53 .rounded(inner_diameter / 2.)
54 .bg(cx.theme().colors().icon_accent),
55 )
56 }),
57 )
58 .child(self.label)
59 .on_click(move |_event, window, cx| {
60 (self.on_click)(&true, window, cx);
61 })
62 }
63}