From 1a40e98413a81f8130197a0fef4190c81773564b Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 13 Jun 2024 16:05:47 -0400 Subject: [PATCH] Render editor fold indicators using `Disclosure`s (#13008) This PR updates the spots where we render the fold indicators in editors to use the `Disclosure` component instead of re-implementing similar UI. This makes this UI more consistent across Zed. Release Notes: - N/A --- crates/assistant/src/assistant_panel.rs | 19 +++++---------- crates/editor/src/editor.rs | 31 ++++++++++--------------- crates/ui/src/components/disclosure.rs | 17 ++++++++++++++ 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 8ae491adaf78ef2f85a9b375dbe144956675e4fc..c4bf50eba134479935241833ffc53b9a97a3b74c 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -54,8 +54,8 @@ use std::{ }; use telemetry_events::AssistantKind; use ui::{ - popover_menu, prelude::*, ButtonLike, ContextMenu, ElevationIndex, KeyBinding, ListItem, - ListItemSpacing, PopoverMenuHandle, Tab, TabBar, Tooltip, + popover_menu, prelude::*, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, + ListItem, ListItemSpacing, PopoverMenuHandle, Tab, TabBar, Tooltip, }; use util::{paths::CONTEXTS_DIR, post_inc, ResultExt, TryFutureExt}; use uuid::Uuid; @@ -3132,17 +3132,10 @@ fn render_slash_command_output_toggle( fold: ToggleFold, _cx: &mut WindowContext, ) -> AnyElement { - IconButton::new( - ("slash-command-output-fold-indicator", row.0), - ui::IconName::ChevronDown, - ) - .on_click(move |_e, cx| fold(!is_folded, cx)) - .icon_color(ui::Color::Muted) - .icon_size(ui::IconSize::Small) - .selected(is_folded) - .selected_icon(ui::IconName::ChevronRight) - .size(ui::ButtonSize::None) - .into_any_element() + Disclosure::new(("slash-command-output-fold-indicator", row.0), !is_folded) + .selected(is_folded) + .on_click(move |_e, cx| fold(!is_folded, cx)) + .into_any_element() } fn render_pending_slash_command_gutter_decoration( diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 404989b408ab12f760389cd5b1813c2b89f4e3d6..19a04446ebfde02176d4653d20f98b294ef929d0 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -138,8 +138,8 @@ use theme::{ ThemeColors, ThemeSettings, }; use ui::{ - h_flex, prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, ListItem, Popover, - Tooltip, + h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, + ListItem, Popover, Tooltip, }; use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::item::{ItemHandle, PreviewTabsSettings}; @@ -11752,23 +11752,16 @@ impl EditorSnapshot { || (self.starts_indent(buffer_row) && (row_contains_cursor || self.gutter_hovered)) { Some( - IconButton::new( - ("indent-fold-indicator", buffer_row.0), - ui::IconName::ChevronDown, - ) - .on_click(cx.listener_for(&editor, move |this, _e, cx| { - if folded { - this.unfold_at(&UnfoldAt { buffer_row }, cx); - } else { - this.fold_at(&FoldAt { buffer_row }, cx); - } - })) - .icon_color(ui::Color::Muted) - .icon_size(ui::IconSize::Small) - .selected(folded) - .selected_icon(ui::IconName::ChevronRight) - .size(ui::ButtonSize::None) - .into_any_element(), + Disclosure::new(("indent-fold-indicator", buffer_row.0), !folded) + .selected(folded) + .on_click(cx.listener_for(&editor, move |this, _e, cx| { + if folded { + this.unfold_at(&UnfoldAt { buffer_row }, cx); + } else { + this.fold_at(&FoldAt { buffer_row }, cx); + } + })) + .into_any_element(), ) } else { None diff --git a/crates/ui/src/components/disclosure.rs b/crates/ui/src/components/disclosure.rs index 3223a2d57c5a2c74b84563a1af13e821074c849f..09f817f021b0c01c3273834ba6d452c0e588205d 100644 --- a/crates/ui/src/components/disclosure.rs +++ b/crates/ui/src/components/disclosure.rs @@ -8,6 +8,7 @@ use crate::{prelude::*, Color, IconButton, IconButtonShape, IconName, IconSize}; pub struct Disclosure { id: ElementId, is_open: bool, + selected: bool, on_toggle: Option>, } @@ -16,6 +17,7 @@ impl Disclosure { Self { id: id.into(), is_open, + selected: false, on_toggle: None, } } @@ -29,6 +31,20 @@ impl Disclosure { } } +impl Selectable for Disclosure { + fn selected(mut self, selected: bool) -> Self { + self.selected = selected; + self + } +} + +impl Clickable for Disclosure { + fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self { + self.on_toggle = Some(Arc::new(handler)); + self + } +} + impl RenderOnce for Disclosure { fn render(self, _cx: &mut WindowContext) -> impl IntoElement { IconButton::new( @@ -41,6 +57,7 @@ impl RenderOnce for Disclosure { .shape(IconButtonShape::Square) .icon_color(Color::Muted) .icon_size(IconSize::Small) + .selected(self.selected) .when_some(self.on_toggle, move |this, on_toggle| { this.on_click(move |event, cx| on_toggle(event, cx)) })