Rework Disclosure component

This commit is contained in:
Marshall Bowers 2023-11-29 14:07:48 -05:00
parent e99fa77bda
commit 6f5cc0af94
6 changed files with 76 additions and 27 deletions

View file

@ -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(),

View file

@ -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<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
) -> 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<Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>>,
) -> 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))
}),
)
}
}

View file

@ -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<IconButton>),
@ -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),
)

View file

@ -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)

View file

@ -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::*;

View file

@ -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>) -> Self::Element {
Story::container()
.child(Story::title_for::<Disclosure>())
.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))
}
}