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