Detailed changes
@@ -16,7 +16,6 @@ pub enum ComponentStory {
AutoHeightEditor,
Avatar,
Button,
- Checkbox,
CollabNotification,
ContextMenu,
Cursor,
@@ -52,7 +51,6 @@ impl ComponentStory {
Self::AutoHeightEditor => AutoHeightEditorStory::new(cx).into(),
Self::Avatar => cx.new_view(|_| ui::AvatarStory).into(),
Self::Button => cx.new_view(|_| ui::ButtonStory).into(),
- Self::Checkbox => cx.new_view(|_| ui::CheckboxStory).into(),
Self::CollabNotification => cx
.new_view(|_| collab_ui::notifications::CollabNotificationStory)
.into(),
@@ -1,7 +1,4 @@
#![allow(missing_docs)]
-mod checkbox_with_label;
-
-pub use checkbox_with_label::*;
use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext};
@@ -163,3 +160,89 @@ impl ComponentPreview for Checkbox {
]
}
}
+
+use std::sync::Arc;
+
+/// A [`Checkbox`] that has a [`Label`].
+#[derive(IntoElement)]
+pub struct CheckboxWithLabel {
+ id: ElementId,
+ label: Label,
+ checked: Selection,
+ on_click: Arc<dyn Fn(&Selection, &mut WindowContext) + 'static>,
+}
+
+impl CheckboxWithLabel {
+ pub fn new(
+ id: impl Into<ElementId>,
+ label: Label,
+ checked: Selection,
+ on_click: impl Fn(&Selection, &mut WindowContext) + 'static,
+ ) -> Self {
+ Self {
+ id: id.into(),
+ label,
+ checked,
+ on_click: Arc::new(on_click),
+ }
+ }
+}
+
+impl RenderOnce for CheckboxWithLabel {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ h_flex()
+ .gap(Spacing::Large.rems(cx))
+ .child(Checkbox::new(self.id.clone(), self.checked).on_click({
+ let on_click = self.on_click.clone();
+ move |checked, cx| {
+ (on_click)(checked, cx);
+ }
+ }))
+ .child(
+ div()
+ .id(SharedString::from(format!("{}-label", self.id)))
+ .on_click(move |_event, cx| {
+ (self.on_click)(&self.checked.inverse(), cx);
+ })
+ .child(self.label),
+ )
+ }
+}
+
+impl ComponentPreview for CheckboxWithLabel {
+ fn description() -> impl Into<Option<&'static str>> {
+ "A checkbox with an associated label, allowing users to select an option while providing a descriptive text."
+ }
+
+ fn examples() -> Vec<ComponentExampleGroup<Self>> {
+ vec![example_group(vec![
+ single_example(
+ "Unselected",
+ CheckboxWithLabel::new(
+ "checkbox_with_label_unselected",
+ Label::new("Always save on quit"),
+ Selection::Unselected,
+ |_, _| {},
+ ),
+ ),
+ single_example(
+ "Indeterminate",
+ CheckboxWithLabel::new(
+ "checkbox_with_label_indeterminate",
+ Label::new("Always save on quit"),
+ Selection::Indeterminate,
+ |_, _| {},
+ ),
+ ),
+ single_example(
+ "Selected",
+ CheckboxWithLabel::new(
+ "checkbox_with_label_selected",
+ Label::new("Always save on quit"),
+ Selection::Selected,
+ |_, _| {},
+ ),
+ ),
+ ])]
+ }
+}
@@ -1,114 +0,0 @@
-#![allow(missing_docs)]
-
-use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext};
-
-use crate::prelude::*;
-use crate::{Color, Icon, IconName, Selection};
-
-/// # Checkbox
-///
-/// Checkboxes are used for multiple choices, not for mutually exclusive choices.
-/// Each checkbox works independently from other checkboxes in the list,
-/// therefore checking an additional box does not affect any other selections.
-#[derive(IntoElement)]
-pub struct Checkbox {
- id: ElementId,
- checked: Selection,
- disabled: bool,
- on_click: Option<Box<dyn Fn(&Selection, &mut WindowContext) + 'static>>,
-}
-
-impl Checkbox {
- pub fn new(id: impl Into<ElementId>, checked: Selection) -> Self {
- Self {
- id: id.into(),
- checked,
- disabled: false,
- on_click: None,
- }
- }
-
- pub fn disabled(mut self, disabled: bool) -> Self {
- self.disabled = disabled;
- self
- }
-
- pub fn on_click(mut self, handler: impl Fn(&Selection, &mut WindowContext) + 'static) -> Self {
- self.on_click = Some(Box::new(handler));
- self
- }
-}
-
-impl RenderOnce for Checkbox {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
- let group_id = format!("checkbox_group_{:?}", self.id);
-
- let icon = match self.checked {
- Selection::Selected => Some(Icon::new(IconName::Check).size(IconSize::Small).color(
- if self.disabled {
- Color::Disabled
- } else {
- Color::Selected
- },
- )),
- Selection::Indeterminate => Some(
- Icon::new(IconName::Dash)
- .size(IconSize::Small)
- .color(if self.disabled {
- Color::Disabled
- } else {
- Color::Selected
- }),
- ),
- Selection::Unselected => None,
- };
-
- let selected =
- self.checked == Selection::Selected || self.checked == Selection::Indeterminate;
-
- let (bg_color, border_color) = match (self.disabled, selected) {
- (true, _) => (
- cx.theme().colors().ghost_element_disabled,
- cx.theme().colors().border_disabled,
- ),
- (false, true) => (
- cx.theme().colors().element_selected,
- cx.theme().colors().border,
- ),
- (false, false) => (
- cx.theme().colors().element_background,
- cx.theme().colors().border,
- ),
- };
-
- h_flex()
- .id(self.id)
- .justify_center()
- .items_center()
- .size(crate::styles::custom_spacing(cx, 20.))
- .group(group_id.clone())
- .child(
- div()
- .flex()
- .flex_none()
- .justify_center()
- .items_center()
- .m(Spacing::Small.px(cx))
- .size(crate::styles::custom_spacing(cx, 16.))
- .rounded_sm()
- .bg(bg_color)
- .border_1()
- .border_color(border_color)
- .when(!self.disabled, |this| {
- this.group_hover(group_id.clone(), |el| {
- el.bg(cx.theme().colors().element_hover)
- })
- })
- .children(icon),
- )
- .when_some(
- self.on_click.filter(|_| !self.disabled),
- |this, on_click| this.on_click(move |_, cx| on_click(&self.checked.inverse(), cx)),
- )
- }
-}
@@ -1,51 +0,0 @@
-#![allow(missing_docs)]
-
-use std::sync::Arc;
-
-use crate::{prelude::*, Checkbox};
-
-/// A [`Checkbox`] that has a [`Label`].
-#[derive(IntoElement)]
-pub struct CheckboxWithLabel {
- id: ElementId,
- label: Label,
- checked: Selection,
- on_click: Arc<dyn Fn(&Selection, &mut WindowContext) + 'static>,
-}
-
-impl CheckboxWithLabel {
- pub fn new(
- id: impl Into<ElementId>,
- label: Label,
- checked: Selection,
- on_click: impl Fn(&Selection, &mut WindowContext) + 'static,
- ) -> Self {
- Self {
- id: id.into(),
- label,
- checked,
- on_click: Arc::new(on_click),
- }
- }
-}
-
-impl RenderOnce for CheckboxWithLabel {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
- h_flex()
- .gap(Spacing::Large.rems(cx))
- .child(Checkbox::new(self.id.clone(), self.checked).on_click({
- let on_click = self.on_click.clone();
- move |checked, cx| {
- (on_click)(checked, cx);
- }
- }))
- .child(
- div()
- .id(SharedString::from(format!("{}-label", self.id)))
- .on_click(move |_event, cx| {
- (self.on_click)(&self.checked.inverse(), cx);
- })
- .child(self.label),
- )
- }
-}
@@ -3,7 +3,6 @@
#![allow(missing_docs)]
mod avatar;
mod button;
-mod checkbox;
mod context_menu;
mod disclosure;
mod icon;
@@ -20,7 +19,6 @@ mod tool_strip;
pub use avatar::*;
pub use button::*;
-pub use checkbox::*;
pub use context_menu::*;
pub use disclosure::*;
pub use icon::*;
@@ -1,47 +0,0 @@
-use gpui::{Render, ViewContext};
-use story::Story;
-
-use crate::prelude::*;
-use crate::{h_flex, Checkbox};
-
-pub struct CheckboxStory;
-
-impl Render for CheckboxStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- Story::container()
- .child(Story::title_for::<Checkbox>())
- .child(Story::label("Default"))
- .child(
- h_flex()
- .p_2()
- .gap_2()
- .rounded_md()
- .border_1()
- .border_color(cx.theme().colors().border)
- .child(Checkbox::new("checkbox-enabled", Selection::Unselected))
- .child(Checkbox::new(
- "checkbox-intermediate",
- Selection::Indeterminate,
- ))
- .child(Checkbox::new("checkbox-selected", Selection::Selected)),
- )
- .child(Story::label("Disabled"))
- .child(
- h_flex()
- .p_2()
- .gap_2()
- .rounded_md()
- .border_1()
- .border_color(cx.theme().colors().border)
- .child(Checkbox::new("checkbox-disabled", Selection::Unselected).disabled(true))
- .child(
- Checkbox::new("checkbox-disabled-intermediate", Selection::Indeterminate)
- .disabled(true),
- )
- .child(
- Checkbox::new("checkbox-disabled-selected", Selection::Selected)
- .disabled(true),
- ),
- )
- }
-}
@@ -9,9 +9,9 @@ pub enum ExampleLabelSide {
Left,
/// Right side
Right,
+ #[default]
/// Top side
Top,
- #[default]
/// Bottom side
Bottom,
}
@@ -81,7 +81,7 @@ pub trait ComponentPreview: IntoElement {
v_flex()
.gap_2()
.when_some(group.title, |this, title| {
- this.child(Headline::new(title).size(HeadlineSize::Small))
+ this.child(Label::new(title).size(LabelSize::Small))
})
.child(
h_flex()
@@ -5,7 +5,7 @@ use theme::all_theme_colors;
use ui::{
element_cell, prelude::*, string_cell, utils::calculate_contrast_ratio, AudioStatus,
Availability, Avatar, AvatarAudioStatusIndicator, AvatarAvailabilityIndicator, ButtonLike,
- Checkbox, ElevationIndex, Facepile, Indicator, Table, TintColor, Tooltip,
+ Checkbox, CheckboxWithLabel, ElevationIndex, Facepile, Indicator, Table, TintColor, Tooltip,
};
use crate::{Item, Workspace};
@@ -510,6 +510,7 @@ impl ThemePreview {
.size_full()
.gap_2()
.child(Checkbox::render_component_previews(cx))
+ .child(CheckboxWithLabel::render_component_previews(cx))
.child(Facepile::render_component_previews(cx))
.child(Button::render_component_previews(cx))
.child(Indicator::render_component_previews(cx))