From 6f5cc0af9485183f9924e8280216066b6d80568f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 29 Nov 2023 14:07:48 -0500 Subject: [PATCH] Rework `Disclosure` component --- crates/storybook2/src/story_selector.rs | 2 + crates/ui2/src/components/disclosure.rs | 67 +++++++++++++------ crates/ui2/src/components/list/list_header.rs | 6 +- crates/ui2/src/components/list/list_item.rs | 4 +- crates/ui2/src/components/stories.rs | 2 + .../ui2/src/components/stories/disclosure.rs | 22 ++++++ 6 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 crates/ui2/src/components/stories/disclosure.rs diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index 1e6ade644c..0354097c0b 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -16,6 +16,7 @@ pub enum ComponentStory { Button, Checkbox, ContextMenu, + Disclosure, Focus, Icon, IconButton, @@ -36,6 +37,7 @@ impl ComponentStory { Self::Button => cx.build_view(|_| ui::ButtonStory).into(), Self::Checkbox => cx.build_view(|_| ui::CheckboxStory).into(), Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into(), + Self::Disclosure => cx.build_view(|_| ui::DisclosureStory).into(), Self::Focus => FocusStory::view(cx).into(), Self::Icon => cx.build_view(|_| ui::IconStory).into(), Self::IconButton => cx.build_view(|_| ui::IconButtonStory).into(), diff --git a/crates/ui2/src/components/disclosure.rs b/crates/ui2/src/components/disclosure.rs index 6206a2edd8..350a598abb 100644 --- a/crates/ui2/src/components/disclosure.rs +++ b/crates/ui2/src/components/disclosure.rs @@ -1,30 +1,55 @@ use std::rc::Rc; -use gpui::{div, ClickEvent, Element, IntoElement, ParentElement, WindowContext}; +use gpui::{ClickEvent, Div}; +use crate::prelude::*; use crate::{Color, Icon, IconButton, IconSize, Toggle}; -pub fn disclosure_control( +#[derive(IntoElement)] +pub struct Disclosure { toggle: Toggle, on_toggle: Option>, -) -> impl Element { - match (toggle.is_toggleable(), toggle.is_toggled()) { - (false, _) => div(), - (_, true) => div().child( - IconButton::new("toggle", Icon::ChevronDown) - .color(Color::Muted) - .size(IconSize::Small) - .when_some(on_toggle, move |el, on_toggle| { - el.on_click(move |e, cx| on_toggle(e, cx)) - }), - ), - (_, false) => div().child( - IconButton::new("toggle", Icon::ChevronRight) - .color(Color::Muted) - .size(IconSize::Small) - .when_some(on_toggle, move |el, on_toggle| { - el.on_click(move |e, cx| on_toggle(e, cx)) - }), - ), +} + +impl Disclosure { + pub fn new(toggle: Toggle) -> Self { + Self { + toggle, + on_toggle: None, + } + } + + pub fn on_toggle( + mut self, + handler: impl Into>>, + ) -> Self { + self.on_toggle = handler.into(); + self + } +} + +impl RenderOnce for Disclosure { + type Rendered = Div; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + if !self.toggle.is_toggleable() { + return div(); + } + + div().child( + IconButton::new( + "toggle", + if self.toggle.is_toggled() { + Icon::ChevronDown + } else { + Icon::ChevronRight + }, + ) + .color(Color::Muted) + .size(IconSize::Small) + .when_some(self.on_toggle, move |this, on_toggle| { + this.on_click(move |event, cx| on_toggle(event, cx)) + }), + ) } } diff --git a/crates/ui2/src/components/list/list_header.rs b/crates/ui2/src/components/list/list_header.rs index 248eb23e60..f280991c82 100644 --- a/crates/ui2/src/components/list/list_header.rs +++ b/crates/ui2/src/components/list/list_header.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use gpui::{ClickEvent, Div}; use crate::prelude::*; -use crate::{disclosure_control, h_stack, Icon, IconButton, IconElement, IconSize, Label, Toggle}; +use crate::{h_stack, Disclosure, Icon, IconButton, IconElement, IconSize, Label, Toggle}; pub enum ListHeaderMeta { Tools(Vec), @@ -73,8 +73,6 @@ impl RenderOnce for ListHeader { type Rendered = Div; fn render(self, cx: &mut WindowContext) -> Self::Rendered { - let disclosure_control = disclosure_control(self.toggle, self.on_toggle); - let meta = match self.meta { Some(ListHeaderMeta::Tools(icons)) => div().child( h_stack() @@ -115,7 +113,7 @@ impl RenderOnce for ListHeader { })) .child(Label::new(self.label.clone()).color(Color::Muted)), ) - .child(disclosure_control), + .child(Disclosure::new(self.toggle).on_toggle(self.on_toggle)), ) .child(meta), ) diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index 8a689d140d..dbab306d93 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -6,7 +6,7 @@ use gpui::{ use smallvec::SmallVec; use crate::prelude::*; -use crate::{disclosure_control, Avatar, GraphicSlot, Icon, IconElement, IconSize, Toggle}; +use crate::{Avatar, Disclosure, GraphicSlot, Icon, IconElement, IconSize, Toggle}; #[derive(IntoElement)] pub struct ListItem { @@ -150,7 +150,7 @@ impl RenderOnce for ListItem { .gap_1() .items_center() .relative() - .child(disclosure_control(self.toggle, self.on_toggle)) + .child(Disclosure::new(self.toggle).on_toggle(self.on_toggle)) .map(|this| match self.left_slot { Some(GraphicSlot::Icon(i)) => this.child( IconElement::new(i) diff --git a/crates/ui2/src/components/stories.rs b/crates/ui2/src/components/stories.rs index 8d3675d521..e870515caf 100644 --- a/crates/ui2/src/components/stories.rs +++ b/crates/ui2/src/components/stories.rs @@ -2,6 +2,7 @@ mod avatar; mod button; mod checkbox; mod context_menu; +mod disclosure; mod icon; mod icon_button; mod keybinding; @@ -13,6 +14,7 @@ pub use avatar::*; pub use button::*; pub use checkbox::*; pub use context_menu::*; +pub use disclosure::*; pub use icon::*; pub use icon_button::*; pub use keybinding::*; diff --git a/crates/ui2/src/components/stories/disclosure.rs b/crates/ui2/src/components/stories/disclosure.rs new file mode 100644 index 0000000000..0c27f5b2e9 --- /dev/null +++ b/crates/ui2/src/components/stories/disclosure.rs @@ -0,0 +1,22 @@ +use gpui::{Div, Render}; +use story::Story; + +use crate::prelude::*; +use crate::{Disclosure, Toggle}; + +pub struct DisclosureStory; + +impl Render for DisclosureStory { + type Element = Div; + + fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + Story::container() + .child(Story::title_for::()) + .child(Story::label("Toggled")) + .child(Disclosure::new(Toggle::Toggled(true))) + .child(Story::label("Not Toggled")) + .child(Disclosure::new(Toggle::Toggled(false))) + .child(Story::label("Not Toggleable")) + .child(Disclosure::new(Toggle::NotToggleable)) + } +}