checkbox_row.rs

  1use component::{example_group_with_title, single_example};
  2use gpui::StatefulInteractiveElement as _;
  3use gpui::{AnyElement, App, ClickEvent, IntoElement, RenderOnce, Window};
  4use ui::prelude::*;
  5
  6#[derive(IntoElement, RegisterComponent)]
  7pub struct CheckboxRow {
  8    label: SharedString,
  9    description: Option<SharedString>,
 10    checked: bool,
 11    on_click: Option<Box<dyn Fn(&mut Window, &mut App) + 'static>>,
 12}
 13
 14impl CheckboxRow {
 15    pub fn new(label: impl Into<SharedString>) -> Self {
 16        Self {
 17            label: label.into(),
 18            description: None,
 19            checked: false,
 20            on_click: None,
 21        }
 22    }
 23
 24    pub fn description(mut self, description: impl Into<SharedString>) -> Self {
 25        self.description = Some(description.into());
 26        self
 27    }
 28
 29    pub fn checked(mut self, checked: bool) -> Self {
 30        self.checked = checked;
 31        self
 32    }
 33
 34    pub fn on_click(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self {
 35        self.on_click = Some(Box::new(handler));
 36        self
 37    }
 38}
 39
 40impl RenderOnce for CheckboxRow {
 41    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
 42        let checked = self.checked;
 43        let on_click = self.on_click;
 44
 45        let checkbox = gpui::div()
 46            .w_4()
 47            .h_4()
 48            .rounded_sm()
 49            .border_1()
 50            .border_color(cx.theme().colors().border)
 51            .when(checked, |this| {
 52                this.bg(cx.theme().colors().element_selected)
 53                    .border_color(cx.theme().colors().border_selected)
 54            })
 55            .hover(|this| this.bg(cx.theme().colors().element_hover))
 56            .child(gpui::div().when(checked, |this| {
 57                this.size_full()
 58                    .flex()
 59                    .items_center()
 60                    .justify_center()
 61                    .child(Icon::new(IconName::Check))
 62            }));
 63
 64        let main_row = if let Some(on_click) = on_click {
 65            gpui::div()
 66                .id("checkbox-row")
 67                .h_flex()
 68                .gap_2()
 69                .items_center()
 70                .child(checkbox)
 71                .child(Label::new(self.label))
 72                .cursor_pointer()
 73                .on_click(move |_event, window, cx| on_click(window, cx))
 74        } else {
 75            gpui::div()
 76                .id("checkbox-row")
 77                .h_flex()
 78                .gap_2()
 79                .items_center()
 80                .child(checkbox)
 81                .child(Label::new(self.label))
 82        };
 83
 84        v_flex()
 85            .px_5()
 86            .py_1()
 87            .gap_1()
 88            .child(main_row)
 89            .when_some(self.description, |this, desc| {
 90                this.child(
 91                    gpui::div()
 92                        .ml_6()
 93                        .child(Label::new(desc).size(LabelSize::Small).color(Color::Muted)),
 94                )
 95            })
 96    }
 97}
 98
 99impl Component for CheckboxRow {
100    fn scope() -> ComponentScope {
101        ComponentScope::Layout
102    }
103
104    fn sort_name() -> &'static str {
105        "RowCheckbox"
106    }
107
108    fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
109        let examples = example_group_with_title(
110            "CheckboxRow Examples",
111            vec![
112                single_example(
113                    "Unchecked",
114                    CheckboxRow::new("Enable Vim Mode").into_any_element(),
115                ),
116                single_example(
117                    "Checked",
118                    CheckboxRow::new("Send Crash Reports")
119                        .checked(true)
120                        .into_any_element(),
121                ),
122                single_example(
123                    "With Description",
124                    CheckboxRow::new("Send Telemetry")
125                        .description("Help improve Zed by sending anonymous usage data")
126                        .checked(true)
127                        .into_any_element(),
128                ),
129            ],
130        );
131
132        Some(v_flex().p_4().gap_4().child(examples).into_any_element())
133    }
134}