diff --git a/crates/storybook/src/story_selector.rs b/crates/storybook/src/story_selector.rs index 2cf6c0beac90ad5be56af61028c8f8329fb95b7c..7f70d58b3b4e5cfb7c23b60c84b17a6a941f0804 100644 --- a/crates/storybook/src/story_selector.rs +++ b/crates/storybook/src/story_selector.rs @@ -17,16 +17,9 @@ pub enum ComponentStory { ContextMenu, Cursor, Focus, - IconButton, - Keybinding, - List, - ListHeader, - ListItem, OverflowScroll, Picker, Scroll, - Tab, - TabBar, Text, ViewportUnits, WithRemSize, @@ -46,16 +39,9 @@ impl ComponentStory { Self::ContextMenu => cx.new(|_| ui::ContextMenuStory).into(), Self::Cursor => cx.new(|_| crate::stories::CursorStory).into(), Self::Focus => FocusStory::model(window, cx).into(), - Self::IconButton => cx.new(|_| ui::IconButtonStory).into(), - Self::Keybinding => cx.new(|_| ui::KeybindingStory).into(), - Self::List => cx.new(|_| ui::ListStory).into(), - Self::ListHeader => cx.new(|_| ui::ListHeaderStory).into(), - Self::ListItem => cx.new(|_| ui::ListItemStory).into(), Self::OverflowScroll => cx.new(|_| crate::stories::OverflowScrollStory).into(), Self::Picker => PickerStory::new(window, cx).into(), Self::Scroll => ScrollStory::model(cx).into(), - Self::Tab => cx.new(|_| ui::TabStory).into(), - Self::TabBar => cx.new(|_| ui::TabBarStory).into(), Self::Text => TextStory::model(cx).into(), Self::ViewportUnits => cx.new(|_| crate::stories::ViewportUnitsStory).into(), Self::WithRemSize => cx.new(|_| crate::stories::WithRemSizeStory).into(), diff --git a/crates/ui/src/components/list/list.rs b/crates/ui/src/components/list/list.rs index b6950f06a4449265cccd48f9f13590650619a01c..ccae5bed23d9509ea6d4989f84620d444499245b 100644 --- a/crates/ui/src/components/list/list.rs +++ b/crates/ui/src/components/list/list.rs @@ -1,14 +1,15 @@ +use component::{Component, ComponentScope, example_group_with_title, single_example}; use gpui::AnyElement; use smallvec::SmallVec; -use crate::{Label, ListHeader, prelude::*, v_flex}; +use crate::{Label, ListHeader, ListItem, prelude::*}; pub enum EmptyMessage { Text(SharedString), Element(AnyElement), } -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct List { /// Message to display when the list is empty /// Defaults to "No items" @@ -92,3 +93,50 @@ impl RenderOnce for List { }) } } + +impl Component for List { + fn scope() -> ComponentScope { + ComponentScope::Layout + } + + fn description() -> Option<&'static str> { + Some( + "A container component for displaying a collection of list items with optional header and empty state.", + ) + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + v_flex() + .gap_6() + .children(vec![example_group_with_title( + "Basic Lists", + vec![ + single_example( + "Simple List", + List::new() + .child(ListItem::new("item1").child(Label::new("Item 1"))) + .child(ListItem::new("item2").child(Label::new("Item 2"))) + .child(ListItem::new("item3").child(Label::new("Item 3"))) + .into_any_element(), + ), + single_example( + "With Header", + List::new() + .header(ListHeader::new("Section Header")) + .child(ListItem::new("item1").child(Label::new("Item 1"))) + .child(ListItem::new("item2").child(Label::new("Item 2"))) + .into_any_element(), + ), + single_example( + "Empty List", + List::new() + .empty_message("No items to display") + .into_any_element(), + ), + ], + )]) + .into_any_element(), + ) + } +} diff --git a/crates/ui/src/components/list/list_bullet_item.rs b/crates/ui/src/components/list/list_bullet_item.rs index 9ac2095b5757d90bd22496052b806f41a5f8d163..17731488f7139522bf19aeaab18fb395d1eb68b0 100644 --- a/crates/ui/src/components/list/list_bullet_item.rs +++ b/crates/ui/src/components/list/list_bullet_item.rs @@ -1,7 +1,8 @@ use crate::{ListItem, prelude::*}; +use component::{Component, ComponentScope, example_group_with_title, single_example}; use gpui::{IntoElement, ParentElement, SharedString}; -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct ListBulletItem { label: SharedString, } @@ -38,3 +39,45 @@ impl RenderOnce for ListBulletItem { .into_any_element() } } + +impl Component for ListBulletItem { + fn scope() -> ComponentScope { + ComponentScope::DataDisplay + } + + fn description() -> Option<&'static str> { + Some("A list item with a bullet point indicator for unordered lists.") + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + v_flex() + .gap_6() + .child(example_group_with_title( + "Bullet Items", + vec![ + single_example( + "Simple", + ListBulletItem::new("First bullet item").into_any_element(), + ), + single_example( + "Multiple Lines", + v_flex() + .child(ListBulletItem::new("First item")) + .child(ListBulletItem::new("Second item")) + .child(ListBulletItem::new("Third item")) + .into_any_element(), + ), + single_example( + "Long Text", + ListBulletItem::new( + "A longer bullet item that demonstrates text wrapping behavior", + ) + .into_any_element(), + ), + ], + )) + .into_any_element(), + ) + } +} diff --git a/crates/ui/src/components/list/list_header.rs b/crates/ui/src/components/list/list_header.rs index d59af07fa5271c070fca8433156b94301cc134aa..8726dca50dada193b3051f14b6609a373fc60730 100644 --- a/crates/ui/src/components/list/list_header.rs +++ b/crates/ui/src/components/list/list_header.rs @@ -1,11 +1,12 @@ use std::sync::Arc; -use crate::{Disclosure, Label, h_flex, prelude::*}; +use crate::{Disclosure, prelude::*}; +use component::{Component, ComponentScope, example_group_with_title, single_example}; use gpui::{AnyElement, ClickEvent}; use settings::Settings; use theme::ThemeSettings; -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct ListHeader { /// The label of the header. label: SharedString, @@ -138,3 +139,80 @@ impl RenderOnce for ListHeader { ) } } + +impl Component for ListHeader { + fn scope() -> ComponentScope { + ComponentScope::DataDisplay + } + + fn description() -> Option<&'static str> { + Some( + "A header component for lists with support for icons, actions, and collapsible sections.", + ) + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + v_flex() + .gap_6() + .children(vec![ + example_group_with_title( + "Basic Headers", + vec![ + single_example( + "Simple", + ListHeader::new("Section Header").into_any_element(), + ), + single_example( + "With Icon", + ListHeader::new("Files") + .start_slot(Icon::new(IconName::File)) + .into_any_element(), + ), + single_example( + "With End Slot", + ListHeader::new("Recent") + .end_slot(Label::new("5").color(Color::Muted)) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "Collapsible Headers", + vec![ + single_example( + "Expanded", + ListHeader::new("Expanded Section") + .toggle(Some(true)) + .into_any_element(), + ), + single_example( + "Collapsed", + ListHeader::new("Collapsed Section") + .toggle(Some(false)) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "States", + vec![ + single_example( + "Selected", + ListHeader::new("Selected Header") + .toggle_state(true) + .into_any_element(), + ), + single_example( + "Inset", + ListHeader::new("Inset Header") + .inset(true) + .into_any_element(), + ), + ], + ), + ]) + .into_any_element(), + ) + } +} diff --git a/crates/ui/src/components/list/list_item.rs b/crates/ui/src/components/list/list_item.rs index a58291438a1d10bb1b61149f412151375b6b0a1f..d581fad9453d9812f17b7bc9e0297fb9927c8188 100644 --- a/crates/ui/src/components/list/list_item.rs +++ b/crates/ui/src/components/list/list_item.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use component::{Component, ComponentScope, example_group_with_title, single_example}; use gpui::{AnyElement, AnyView, ClickEvent, MouseButton, MouseDownEvent, Pixels, px}; use smallvec::SmallVec; @@ -13,7 +14,7 @@ pub enum ListItemSpacing { Sparse, } -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct ListItem { id: ElementId, group_name: Option, @@ -355,3 +356,115 @@ impl RenderOnce for ListItem { ) } } + +impl Component for ListItem { + fn scope() -> ComponentScope { + ComponentScope::DataDisplay + } + + fn description() -> Option<&'static str> { + Some( + "A flexible list item component with support for icons, actions, disclosure toggles, and hierarchical display.", + ) + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + v_flex() + .gap_6() + .children(vec![ + example_group_with_title( + "Basic List Items", + vec![ + single_example( + "Simple", + ListItem::new("simple") + .child(Label::new("Simple list item")) + .into_any_element(), + ), + single_example( + "With Icon", + ListItem::new("with_icon") + .start_slot(Icon::new(IconName::File)) + .child(Label::new("List item with icon")) + .into_any_element(), + ), + single_example( + "Selected", + ListItem::new("selected") + .toggle_state(true) + .start_slot(Icon::new(IconName::Check)) + .child(Label::new("Selected item")) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "List Item Spacing", + vec![ + single_example( + "Dense", + ListItem::new("dense") + .spacing(ListItemSpacing::Dense) + .child(Label::new("Dense spacing")) + .into_any_element(), + ), + single_example( + "Extra Dense", + ListItem::new("extra_dense") + .spacing(ListItemSpacing::ExtraDense) + .child(Label::new("Extra dense spacing")) + .into_any_element(), + ), + single_example( + "Sparse", + ListItem::new("sparse") + .spacing(ListItemSpacing::Sparse) + .child(Label::new("Sparse spacing")) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "With Slots", + vec![ + single_example( + "End Slot", + ListItem::new("end_slot") + .child(Label::new("Item with end slot")) + .end_slot(Icon::new(IconName::ChevronRight)) + .into_any_element(), + ), + single_example( + "With Toggle", + ListItem::new("with_toggle") + .toggle(Some(true)) + .child(Label::new("Expandable item")) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "States", + vec![ + single_example( + "Disabled", + ListItem::new("disabled") + .disabled(true) + .child(Label::new("Disabled item")) + .into_any_element(), + ), + single_example( + "Non-selectable", + ListItem::new("non_selectable") + .selectable(false) + .child(Label::new("Non-selectable item")) + .into_any_element(), + ), + ], + ), + ]) + .into_any_element(), + ) + } +} diff --git a/crates/ui/src/components/list/list_sub_header.rs b/crates/ui/src/components/list/list_sub_header.rs index e6f5abfe0ab5ee4f7e10a85c3d2b15402df8fc53..b4a82fb2edf5fcfbe068dee2570884698b8b0663 100644 --- a/crates/ui/src/components/list/list_sub_header.rs +++ b/crates/ui/src/components/list/list_sub_header.rs @@ -1,7 +1,7 @@ use crate::prelude::*; -use crate::{Icon, IconName, IconSize, Label, h_flex}; +use component::{Component, ComponentScope, example_group_with_title, single_example}; -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct ListSubHeader { label: SharedString, start_slot: Option, @@ -85,3 +85,65 @@ impl RenderOnce for ListSubHeader { ) } } + +impl Component for ListSubHeader { + fn scope() -> ComponentScope { + ComponentScope::DataDisplay + } + + fn description() -> Option<&'static str> { + Some( + "A sub-header component for organizing list content into subsections with optional icons and end slots.", + ) + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + v_flex() + .gap_6() + .children(vec![ + example_group_with_title( + "Basic Sub-headers", + vec![ + single_example( + "Simple", + ListSubHeader::new("Subsection").into_any_element(), + ), + single_example( + "With Icon", + ListSubHeader::new("Documents") + .left_icon(Some(IconName::File)) + .into_any_element(), + ), + single_example( + "With End Slot", + ListSubHeader::new("Recent") + .end_slot( + Label::new("3").color(Color::Muted).into_any_element(), + ) + .into_any_element(), + ), + ], + ), + example_group_with_title( + "States", + vec![ + single_example( + "Selected", + ListSubHeader::new("Selected") + .toggle_state(true) + .into_any_element(), + ), + single_example( + "Inset", + ListSubHeader::new("Inset Sub-header") + .inset(true) + .into_any_element(), + ), + ], + ), + ]) + .into_any_element(), + ) + } +} diff --git a/crates/ui/src/components/stories.rs b/crates/ui/src/components/stories.rs index 29d72ad08b783f8d2cfa5b62ed8fef9d845c9315..bcfcfd04c3176d6a19385101360ab21bffb9cc8e 100644 --- a/crates/ui/src/components/stories.rs +++ b/crates/ui/src/components/stories.rs @@ -1,17 +1,3 @@ mod context_menu; -mod icon_button; -mod keybinding; -mod list; -mod list_header; -mod list_item; -mod tab; -mod tab_bar; pub use context_menu::*; -pub use icon_button::*; -pub use keybinding::*; -pub use list::*; -pub use list_header::*; -pub use list_item::*; -pub use tab::*; -pub use tab_bar::*; diff --git a/crates/ui/src/components/stories/avatar.rs b/crates/ui/src/components/stories/avatar.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/crates/ui/src/components/stories/button.rs b/crates/ui/src/components/stories/button.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/crates/ui/src/components/stories/disclosure.rs b/crates/ui/src/components/stories/disclosure.rs deleted file mode 100644 index 5a395388f450a19270426a6df7efa78d490792c2..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/disclosure.rs +++ /dev/null @@ -1,18 +0,0 @@ -use gpui::Render; -use story::Story; - -use crate::Disclosure; -use crate::prelude::*; - -pub struct DisclosureStory; - -impl Render for DisclosureStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Toggled")) - .child(Disclosure::new("toggled", true)) - .child(Story::label("Not Toggled")) - .child(Disclosure::new("not_toggled", false)) - } -} diff --git a/crates/ui/src/components/stories/icon_button.rs b/crates/ui/src/components/stories/icon_button.rs deleted file mode 100644 index 166297eabc389ca5cc4dea5070c21cb9efa00133..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/icon_button.rs +++ /dev/null @@ -1,148 +0,0 @@ -use gpui::Render; -use story::{Story, StoryItem, StorySection}; - -use crate::{IconButton, IconName}; -use crate::{IconButtonShape, Tooltip, prelude::*}; - -pub struct IconButtonStory; - -impl Render for IconButtonStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let default_button = StoryItem::new( - "Default", - IconButton::new("default_icon_button", IconName::Hash), - ) - .description("Displays an icon button.") - .usage( - r#" - IconButton::new("default_icon_button", Icon::Hash) - "#, - ); - - let selected_button = StoryItem::new( - "Selected", - IconButton::new("selected_icon_button", IconName::Hash).toggle_state(true), - ) - .description("Displays an icon button that is selected.") - .usage( - r#" - IconButton::new("selected_icon_button", Icon::Hash).selected(true) - "#, - ); - - let selected_with_selected_icon = StoryItem::new( - "Selected with `selected_icon`", - IconButton::new("selected_with_selected_icon_button", IconName::AudioOn) - .toggle_state(true) - .selected_icon(IconName::AudioOff), - ) - .description( - "Displays an icon button that is selected and shows a different icon when selected.", - ) - .usage( - r#" - IconButton::new("selected_with_selected_icon_button", Icon::AudioOn) - .selected(true) - .selected_icon(Icon::AudioOff) - "#, - ); - - let disabled_button = StoryItem::new( - "Disabled", - IconButton::new("disabled_icon_button", IconName::Hash).disabled(true), - ) - .description("Displays an icon button that is disabled.") - .usage( - r#" - IconButton::new("disabled_icon_button", Icon::Hash).disabled(true) - "#, - ); - - let with_on_click_button = StoryItem::new( - "With `on_click`", - IconButton::new("with_on_click_button", IconName::Ai).on_click( - |_event, _window, _cx| { - println!("Clicked!"); - }, - ), - ) - .description("Displays an icon button which triggers an event on click.") - .usage( - r#" - IconButton::new("with_on_click_button", Icon::Ai).on_click(|_event, _cx| { - println!("Clicked!"); - }) - "#, - ); - - let with_tooltip_button = StoryItem::new( - "With `tooltip`", - IconButton::new("with_tooltip_button", IconName::Chat) - .tooltip(Tooltip::text("Open messages")), - ) - .description("Displays an icon button that has a tooltip when hovered.") - .usage( - r#" - IconButton::new("with_tooltip_button", Icon::MessageBubbles) - .tooltip(Tooltip::text_f("Open messages")) - "#, - ); - - let selected_with_tooltip_button = StoryItem::new( - "Selected with `tooltip`", - IconButton::new("selected_with_tooltip_button", IconName::CaseSensitive) - .toggle_state(true) - .tooltip(Tooltip::text("Toggle inlay hints")), - ) - .description("Displays a selected icon button with tooltip.") - .usage( - r#" - IconButton::new("selected_with_tooltip_button", Icon::InlayHint) - .selected(true) - .tooltip(Tooltip::text_f("Toggle inlay hints")) - "#, - ); - - let buttons = vec![ - default_button, - selected_button, - selected_with_selected_icon, - disabled_button, - with_on_click_button, - with_tooltip_button, - selected_with_tooltip_button, - ]; - - Story::container(cx) - .child(Story::title_for::(cx)) - .child(StorySection::new().children(buttons)) - .child( - StorySection::new().child(StoryItem::new( - "Square", - h_flex() - .gap_2() - .child( - IconButton::new("square-medium", IconName::Close) - .shape(IconButtonShape::Square) - .icon_size(IconSize::Medium), - ) - .child( - IconButton::new("square-small", IconName::Close) - .shape(IconButtonShape::Square) - .icon_size(IconSize::Small), - ) - .child( - IconButton::new("square-xsmall", IconName::Close) - .shape(IconButtonShape::Square) - .icon_size(IconSize::XSmall), - ) - .child( - IconButton::new("square-indicator", IconName::Close) - .shape(IconButtonShape::Square) - .icon_size(IconSize::Indicator), - ), - )), - ) - .into_element() - } -} diff --git a/crates/ui/src/components/stories/keybinding.rs b/crates/ui/src/components/stories/keybinding.rs deleted file mode 100644 index 5840a11cf702f7a47aed06791ab47f12e2418d9c..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/keybinding.rs +++ /dev/null @@ -1,136 +0,0 @@ -use gpui::NoAction; -use gpui::Render; -use itertools::Itertools; -use settings::KeybindSource; -use story::Story; - -use crate::{KeyBinding, prelude::*}; - -pub struct KeybindingStory; - -pub fn binding(key: &str) -> gpui::KeyBinding { - gpui::KeyBinding::new(key, NoAction {}, None) -} - -impl Render for KeybindingStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2); - - const SOURCE: KeybindSource = KeybindSource::Base; - - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Single Key", cx)) - .child(KeyBinding::from_keystrokes( - binding("Z").keystrokes().into(), - SOURCE, - )) - .child(Story::label("Single Key with Modifier", cx)) - .child( - div() - .flex() - .gap_3() - .child(KeyBinding::from_keystrokes( - binding("ctrl-c").keystrokes().into(), - SOURCE, - )) - .child(KeyBinding::from_keystrokes( - binding("alt-c").keystrokes().into(), - SOURCE, - )) - .child(KeyBinding::from_keystrokes( - binding("cmd-c").keystrokes().into(), - SOURCE, - )) - .child(KeyBinding::from_keystrokes( - binding("shift-c").keystrokes().into(), - SOURCE, - )), - ) - .child(Story::label("Single Key with Modifier (Permuted)", cx)) - .child( - div().flex().flex_col().children( - all_modifier_permutations - .chunks(4) - .into_iter() - .map(|chunk| { - div() - .flex() - .gap_4() - .py_3() - .children(chunk.map(|permutation| { - KeyBinding::from_keystrokes( - binding(&(permutation.join("-") + "-x")) - .keystrokes() - .into(), - SOURCE, - ) - })) - }), - ), - ) - .child(Story::label("Single Key with All Modifiers", cx)) - .child(KeyBinding::from_keystrokes( - binding("ctrl-alt-cmd-shift-z").keystrokes().into(), - SOURCE, - )) - .child(Story::label("Chord", cx)) - .child(KeyBinding::from_keystrokes( - binding("a z").keystrokes().into(), - SOURCE, - )) - .child(Story::label("Chord with Modifier", cx)) - .child(KeyBinding::from_keystrokes( - binding("ctrl-a shift-z").keystrokes().into(), - SOURCE, - )) - .child(KeyBinding::from_keystrokes( - binding("fn-s").keystrokes().into(), - SOURCE, - )) - .child(Story::label("Single Key with All Modifiers (Linux)", cx)) - .child( - KeyBinding::from_keystrokes( - binding("ctrl-alt-cmd-shift-z").keystrokes().into(), - SOURCE, - ) - .platform_style(PlatformStyle::Linux), - ) - .child(Story::label("Chord (Linux)", cx)) - .child( - KeyBinding::from_keystrokes(binding("a z").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Linux), - ) - .child(Story::label("Chord with Modifier (Linux)", cx)) - .child( - KeyBinding::from_keystrokes(binding("ctrl-a shift-z").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Linux), - ) - .child( - KeyBinding::from_keystrokes(binding("fn-s").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Linux), - ) - .child(Story::label("Single Key with All Modifiers (Windows)", cx)) - .child( - KeyBinding::from_keystrokes( - binding("ctrl-alt-cmd-shift-z").keystrokes().into(), - SOURCE, - ) - .platform_style(PlatformStyle::Windows), - ) - .child(Story::label("Chord (Windows)", cx)) - .child( - KeyBinding::from_keystrokes(binding("a z").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Windows), - ) - .child(Story::label("Chord with Modifier (Windows)", cx)) - .child( - KeyBinding::from_keystrokes(binding("ctrl-a shift-z").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Windows), - ) - .child( - KeyBinding::from_keystrokes(binding("fn-s").keystrokes().into(), SOURCE) - .platform_style(PlatformStyle::Windows), - ) - } -} diff --git a/crates/ui/src/components/stories/list.rs b/crates/ui/src/components/stories/list.rs deleted file mode 100644 index 6a0e672d31771fd2c946e2c207ae052baf77fb01..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/list.rs +++ /dev/null @@ -1,36 +0,0 @@ -use gpui::Render; -use story::Story; - -use crate::{List, ListItem}; -use crate::{ListHeader, ListSeparator, ListSubHeader, prelude::*}; - -pub struct ListStory; - -impl Render for ListStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Default", cx)) - .child( - List::new() - .child(ListItem::new("apple").child("Apple")) - .child(ListItem::new("banana").child("Banana")) - .child(ListItem::new("cherry").child("Cherry")), - ) - .child(Story::label("With sections", cx)) - .child( - List::new() - .header(ListHeader::new("Produce")) - .child(ListSubHeader::new("Fruits")) - .child(ListItem::new("apple").child("Apple")) - .child(ListItem::new("banana").child("Banana")) - .child(ListItem::new("cherry").child("Cherry")) - .child(ListSeparator) - .child(ListSubHeader::new("Root Vegetables")) - .child(ListItem::new("carrot").child("Carrot")) - .child(ListItem::new("potato").child("Potato")) - .child(ListSubHeader::new("Leafy Vegetables")) - .child(ListItem::new("kale").child("Kale")), - ) - } -} diff --git a/crates/ui/src/components/stories/list_header.rs b/crates/ui/src/components/stories/list_header.rs deleted file mode 100644 index f7fa068d5a11cb0bd772dc4c10fd19c048ae0181..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/list_header.rs +++ /dev/null @@ -1,31 +0,0 @@ -use gpui::Render; -use story::Story; - -use crate::{IconButton, prelude::*}; -use crate::{IconName, ListHeader}; - -pub struct ListHeaderStory; - -impl Render for ListHeaderStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Default", cx)) - .child(ListHeader::new("Section 1")) - .child(Story::label("With left icon", cx)) - .child(ListHeader::new("Section 2").start_slot(Icon::new(IconName::Bell))) - .child(Story::label("With left icon and meta", cx)) - .child( - ListHeader::new("Section 3") - .start_slot(Icon::new(IconName::BellOff)) - .end_slot(IconButton::new("action_1", IconName::BoltFilled)), - ) - .child(Story::label("With multiple meta", cx)) - .child( - ListHeader::new("Section 4") - .end_slot(IconButton::new("action_1", IconName::BoltFilled)) - .end_slot(IconButton::new("action_2", IconName::Warning)) - .end_slot(IconButton::new("action_3", IconName::Plus)), - ) - } -} diff --git a/crates/ui/src/components/stories/list_item.rs b/crates/ui/src/components/stories/list_item.rs deleted file mode 100644 index ee8f5e6c7280215c81f4bc9e71685a1ffec11c80..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/list_item.rs +++ /dev/null @@ -1,131 +0,0 @@ -use gpui::Render; -use story::Story; - -use crate::{Avatar, prelude::*}; -use crate::{IconName, ListItem}; - -const OVERFLOWING_TEXT: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean mauris ligula, luctus vel dignissim eu, vestibulum sed libero. Sed at convallis velit."; - -pub struct ListItemStory; - -impl Render for ListItemStory { - fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { - Story::container(cx) - .bg(cx.theme().colors().background) - .child(Story::title_for::(cx)) - .child(Story::label("Default", cx)) - .child(ListItem::new("hello_world").child("Hello, world!")) - .child(Story::label("Inset", cx)) - .child( - ListItem::new("inset_list_item") - .inset(true) - .start_slot( - Icon::new(IconName::Bell) - .size(IconSize::Small) - .color(Color::Muted), - ) - .child("Hello, world!") - .end_slot( - Icon::new(IconName::Bell) - .size(IconSize::Small) - .color(Color::Muted), - ), - ) - .child(Story::label("With start slot icon", cx)) - .child( - ListItem::new("with start slot_icon") - .child("Hello, world!") - .start_slot( - Icon::new(IconName::Bell) - .size(IconSize::Small) - .color(Color::Muted), - ), - ) - .child(Story::label("With start slot avatar", cx)) - .child( - ListItem::new("with_start slot avatar") - .child("Hello, world!") - .start_slot(Avatar::new( - "https://avatars.githubusercontent.com/u/1714999?v=4", - )), - ) - .child(Story::label("With end slot", cx)) - .child( - ListItem::new("with_left_avatar") - .child("Hello, world!") - .end_slot(Avatar::new( - "https://avatars.githubusercontent.com/u/1714999?v=4", - )), - ) - .child(Story::label("With end hover slot", cx)) - .child( - ListItem::new("with_end_hover_slot") - .child("Hello, world!") - .end_slot( - h_flex() - .gap_2() - .child(Avatar::new( - "https://avatars.githubusercontent.com/u/1789?v=4", - )) - .child(Avatar::new( - "https://avatars.githubusercontent.com/u/1789?v=4", - )) - .child(Avatar::new( - "https://avatars.githubusercontent.com/u/1789?v=4", - )) - .child(Avatar::new( - "https://avatars.githubusercontent.com/u/1789?v=4", - )) - .child(Avatar::new( - "https://avatars.githubusercontent.com/u/1789?v=4", - )), - ) - .end_hover_slot(Avatar::new( - "https://avatars.githubusercontent.com/u/1714999?v=4", - )), - ) - .child(Story::label("With `on_click`", cx)) - .child(ListItem::new("with_on_click").child("Click me").on_click( - |_event, _window, _cx| { - println!("Clicked!"); - }, - )) - .child(Story::label("With `on_secondary_mouse_down`", cx)) - .child( - ListItem::new("with_on_secondary_mouse_down") - .child("Right click me") - .on_secondary_mouse_down(|_event, _window, _cx| { - println!("Right mouse down!"); - }), - ) - .child(Story::label( - "With overflowing content in the `end_slot`", - cx, - )) - .child( - ListItem::new("with_overflowing_content_in_end_slot") - .child("An excerpt") - .end_slot(Label::new(OVERFLOWING_TEXT).color(Color::Muted)), - ) - .child(Story::label( - "`inset` with overflowing content in the `end_slot`", - cx, - )) - .child( - ListItem::new("inset_with_overflowing_content_in_end_slot") - .inset(true) - .child("An excerpt") - .end_slot(Label::new(OVERFLOWING_TEXT).color(Color::Muted)), - ) - .child(Story::label( - "`inset` with overflowing content in `children` and `end_slot`", - cx, - )) - .child( - ListItem::new("inset_with_overflowing_content_in_children_and_end_slot") - .inset(true) - .child(Label::new(OVERFLOWING_TEXT)) - .end_slot(Label::new(OVERFLOWING_TEXT).color(Color::Muted)), - ) - } -} diff --git a/crates/ui/src/components/stories/tab.rs b/crates/ui/src/components/stories/tab.rs deleted file mode 100644 index e6c80c54e9752ff7ebee68a70f3af6d7023d0c74..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/tab.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::cmp::Ordering; - -use gpui::Render; -use story::Story; - -use crate::{IconButtonShape, TabPosition, prelude::*}; -use crate::{Indicator, Tab}; - -pub struct TabStory; - -impl Render for TabStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Default", cx)) - .child(h_flex().child(Tab::new("tab_1").child("Tab 1"))) - .child(Story::label("With indicator", cx)) - .child( - h_flex().child( - Tab::new("tab_1") - .start_slot(Indicator::dot().color(Color::Warning)) - .child("Tab 1"), - ), - ) - .child(Story::label("With close button", cx)) - .child( - h_flex().child( - Tab::new("tab_1") - .end_slot( - IconButton::new("close_button", IconName::Close) - .visible_on_hover("") - .shape(IconButtonShape::Square) - .icon_color(Color::Muted) - .size(ButtonSize::None) - .icon_size(IconSize::XSmall), - ) - .child("Tab 1"), - ), - ) - .child(Story::label("List of tabs", cx)) - .child( - h_flex() - .child(Tab::new("tab_1").child("Tab 1")) - .child(Tab::new("tab_2").child("Tab 2")), - ) - .child(Story::label("List of tabs with first tab selected", cx)) - .child( - h_flex() - .child( - Tab::new("tab_1") - .toggle_state(true) - .position(TabPosition::First) - .child("Tab 1"), - ) - .child( - Tab::new("tab_2") - .position(TabPosition::Middle(Ordering::Greater)) - .child("Tab 2"), - ) - .child( - Tab::new("tab_3") - .position(TabPosition::Middle(Ordering::Greater)) - .child("Tab 3"), - ) - .child(Tab::new("tab_4").position(TabPosition::Last).child("Tab 4")), - ) - .child(Story::label("List of tabs with last tab selected", cx)) - .child( - h_flex() - .child( - Tab::new("tab_1") - .position(TabPosition::First) - .child("Tab 1"), - ) - .child( - Tab::new("tab_2") - .position(TabPosition::Middle(Ordering::Less)) - .child("Tab 2"), - ) - .child( - Tab::new("tab_3") - .position(TabPosition::Middle(Ordering::Less)) - .child("Tab 3"), - ) - .child( - Tab::new("tab_4") - .position(TabPosition::Last) - .toggle_state(true) - .child("Tab 4"), - ), - ) - .child(Story::label("List of tabs with second tab selected", cx)) - .child( - h_flex() - .child( - Tab::new("tab_1") - .position(TabPosition::First) - .child("Tab 1"), - ) - .child( - Tab::new("tab_2") - .position(TabPosition::Middle(Ordering::Equal)) - .toggle_state(true) - .child("Tab 2"), - ) - .child( - Tab::new("tab_3") - .position(TabPosition::Middle(Ordering::Greater)) - .child("Tab 3"), - ) - .child(Tab::new("tab_4").position(TabPosition::Last).child("Tab 4")), - ) - } -} diff --git a/crates/ui/src/components/stories/tab_bar.rs b/crates/ui/src/components/stories/tab_bar.rs deleted file mode 100644 index fbb6c8c248af49a40c0246b9b249961b0198d880..0000000000000000000000000000000000000000 --- a/crates/ui/src/components/stories/tab_bar.rs +++ /dev/null @@ -1,59 +0,0 @@ -use gpui::Render; -use story::Story; - -use crate::{Tab, TabBar, TabPosition, prelude::*}; - -pub struct TabBarStory; - -impl Render for TabBarStory { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let tab_count = 20; - let selected_tab_index = 3; - - let tabs = (0..tab_count) - .map(|index| { - Tab::new(index) - .toggle_state(index == selected_tab_index) - .position(if index == 0 { - TabPosition::First - } else if index == tab_count - 1 { - TabPosition::Last - } else { - TabPosition::Middle(index.cmp(&selected_tab_index)) - }) - .child(Label::new(format!("Tab {}", index + 1)).color( - if index == selected_tab_index { - Color::Default - } else { - Color::Muted - }, - )) - }) - .collect::>(); - - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label("Default", cx)) - .child( - h_flex().child( - TabBar::new("tab_bar_1") - .start_child( - IconButton::new("navigate_backward", IconName::ArrowLeft) - .icon_size(IconSize::Small), - ) - .start_child( - IconButton::new("navigate_forward", IconName::ArrowRight) - .icon_size(IconSize::Small), - ) - .end_child( - IconButton::new("new", IconName::Plus).icon_size(IconSize::Small), - ) - .end_child( - IconButton::new("split_pane", IconName::Split) - .icon_size(IconSize::Small), - ) - .children(tabs), - ), - ) - } -}