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