diff --git a/Cargo.lock b/Cargo.lock index 88340c716bc0fc3ec54bf4f54d2f7ebb6235b6d8..0a4801524eae5937fd476fd2cd6dac129cae228e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9263,6 +9263,8 @@ name = "story" version = "0.1.0" dependencies = [ "gpui2", + "itertools 0.10.5", + "smallvec", ] [[package]] @@ -9277,6 +9279,7 @@ dependencies = [ "editor2", "fuzzy2", "gpui2", + "indoc", "itertools 0.11.0", "language2", "log", diff --git a/crates/story/Cargo.toml b/crates/story/Cargo.toml index 384447af8fe51472a7da9b614e23b364bb664d25..9c195f77f05f591474e739834a8b8965c3822fb4 100644 --- a/crates/story/Cargo.toml +++ b/crates/story/Cargo.toml @@ -8,3 +8,5 @@ publish = false [dependencies] gpui = { package = "gpui2", path = "../gpui2" } +smallvec.workspace = true +itertools = {package = "itertools", version = "0.10"} diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs index d95c879ce0068c00fd24ffb64179d4e3d46a5c7a..3419af95b099807609b52b40b9775b17457975a0 100644 --- a/crates/story/src/story.rs +++ b/crates/story/src/story.rs @@ -1,22 +1,199 @@ -use gpui::prelude::*; -use gpui::{div, hsla, Div, SharedString}; +use gpui::{ + div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, Stateful, + WindowContext, +}; +use itertools::Itertools; +use smallvec::SmallVec; + +use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time::{SystemTime, UNIX_EPOCH}; + +static COUNTER: AtomicUsize = AtomicUsize::new(0); + +pub fn reasonably_unique_id() -> String { + let now = SystemTime::now(); + let timestamp = now.duration_since(UNIX_EPOCH).unwrap(); + + let cnt = COUNTER.fetch_add(1, Ordering::Relaxed); + + let id = format!("{}_{}", timestamp.as_nanos(), cnt); + + id +} + +pub struct StoryColor { + pub primary: Hsla, + pub secondary: Hsla, + pub border: Hsla, + pub background: Hsla, + pub card_background: Hsla, + pub divider: Hsla, + pub link: Hsla, +} + +impl StoryColor { + pub fn new() -> Self { + Self { + primary: hsla(216. / 360., 11. / 100., 0. / 100., 1.), + secondary: hsla(216. / 360., 11. / 100., 16. / 100., 1.), + border: hsla(216. / 360., 11. / 100., 91. / 100., 1.), + background: hsla(0. / 360., 0. / 100., 100. / 100., 1.), + card_background: hsla(0. / 360., 0. / 100., 96. / 100., 1.), + divider: hsla(216. / 360., 11. / 100., 86. / 100., 1.), + link: hsla(206. / 360., 100. / 100., 50. / 100., 1.), + } + } +} + +pub fn story_color() -> StoryColor { + StoryColor::new() +} + +#[derive(IntoElement)] +pub struct StoryContainer { + title: SharedString, + relative_path: &'static str, + children: SmallVec<[AnyElement; 2]>, +} + +impl StoryContainer { + pub fn new(title: impl Into, relative_path: &'static str) -> Self { + Self { + title: title.into(), + relative_path, + children: SmallVec::new(), + } + } +} + +impl ParentElement for StoryContainer { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } +} + +impl RenderOnce for StoryContainer { + type Rendered = Stateful
; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + div() + .size_full() + .flex() + .flex_col() + .id("story_container") + .bg(story_color().background) + .child( + div() + .flex() + .flex_none() + .w_full() + .justify_between() + .p_2() + .bg(story_color().background) + .border_b() + .border_color(story_color().border) + .child(Story::title(self.title)) + .child( + div() + .text_xs() + .text_color(story_color().primary) + .child(Story::open_story_link(self.relative_path)), + ), + ) + .child( + div() + .w_full() + .h_px() + .flex_1() + .id("story_body") + .overflow_hidden_x() + .overflow_y_scroll() + .flex() + .flex_col() + .pb_4() + .children(self.children), + ) + } +} pub struct Story {} impl Story { pub fn container() -> Div { - div().size_full().flex().flex_col().pt_2().px_4().bg(hsla( - 0. / 360., - 0. / 100., - 100. / 100., - 1., - )) + div().size_full().overflow_hidden().child( + div() + .id("story_container") + .overflow_y_scroll() + .w_full() + .min_h_full() + .flex() + .flex_col() + .bg(story_color().background), + ) + } + + // TODO: Move all stories to container2, then rename + pub fn container2(relative_path: &'static str) -> Div { + div().size_full().child( + div() + .size_full() + .id("story_container") + .overflow_y_scroll() + .flex() + .flex_col() + .flex_none() + .child( + div() + .flex() + .justify_between() + .p_2() + .border_b() + .border_color(story_color().border) + .child(Story::title_for::()) + .child( + div() + .text_xs() + .text_color(story_color().primary) + .child(Story::open_story_link(relative_path)), + ), + ) + .child( + div() + .w_full() + .min_h_full() + .flex() + .flex_col() + .bg(story_color().background), + ), + ) + } + + pub fn open_story_link(relative_path: &'static str) -> impl Element { + let path = PathBuf::from_iter([relative_path]); + + div() + .flex() + .gap_2() + .text_xs() + .text_color(story_color().primary) + .id(SharedString::from(format!("id_{}", relative_path))) + .on_click({ + let path = path.clone(); + + move |_event, _cx| { + let path = format!("{}:0:0", path.to_string_lossy()); + + std::process::Command::new("zed").arg(path).spawn().ok(); + } + }) + .children(vec![div().child(Story::link("Open in Zed →"))]) } pub fn title(title: impl Into) -> impl Element { div() - .text_xl() - .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .text_xs() + .text_color(story_color().primary) .child(title.into()) } @@ -24,12 +201,185 @@ impl Story { Self::title(std::any::type_name::()) } + pub fn section() -> Div { + div() + .p_4() + .m_4() + .border() + .border_color(story_color().border) + } + + pub fn section_title() -> Div { + div().text_lg().text_color(story_color().primary) + } + + pub fn group() -> Div { + div().my_2().bg(story_color().background) + } + + pub fn code_block(code: impl Into) -> Div { + div() + .size_full() + .p_2() + .max_w(rems(36.)) + .bg(gpui::black()) + .rounded_md() + .text_sm() + .text_color(gpui::white()) + .overflow_hidden() + .child(code.into()) + } + + pub fn divider() -> Div { + div().my_2().h(px(1.)).bg(story_color().divider) + } + + pub fn link(link: impl Into) -> impl Element { + div() + .id(ElementId::from(SharedString::from(reasonably_unique_id()))) + .text_xs() + .text_color(story_color().link) + .cursor(gpui::CursorStyle::PointingHand) + .child(link.into()) + } + + pub fn description(description: impl Into) -> impl Element { + div() + .text_sm() + .text_color(story_color().secondary) + .min_w_96() + .child(description.into()) + } + pub fn label(label: impl Into) -> impl Element { div() - .mt_4() - .mb_2() .text_xs() - .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .text_color(story_color().primary) .child(label.into()) } + + /// Note: Not ui::v_stack() as the story crate doesn't depend on the ui crate. + pub fn v_stack() -> Div { + div().flex().flex_col().gap_1() + } +} + +#[derive(IntoElement)] +pub struct StoryItem { + label: SharedString, + item: AnyElement, + description: Option, + usage: Option, +} + +impl StoryItem { + pub fn new(label: impl Into, item: impl IntoElement) -> Self { + Self { + label: label.into(), + item: item.into_any_element(), + description: None, + usage: None, + } + } + + pub fn description(mut self, description: impl Into) -> Self { + self.description = Some(description.into()); + self + } + + pub fn usage(mut self, code: impl Into) -> Self { + self.usage = Some(code.into()); + self + } +} + +impl RenderOnce for StoryItem { + type Rendered = Div; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + div() + .my_2() + .flex() + .gap_4() + .w_full() + .child( + Story::v_stack() + .px_2() + .w_1_2() + .min_h_px() + .child(Story::label(self.label)) + .child( + div() + .rounded_md() + .bg(story_color().card_background) + .border() + .border_color(story_color().border) + .py_1() + .px_2() + .overflow_hidden() + .child(self.item), + ) + .when_some(self.description, |this, description| { + this.child(Story::description(description)) + }), + ) + .child( + Story::v_stack() + .px_2() + .flex_none() + .w_1_2() + .min_h_px() + .when_some(self.usage, |this, usage| { + this.child(Story::label("Example Usage")) + .child(Story::code_block(usage)) + }), + ) + } +} + +#[derive(IntoElement)] +pub struct StorySection { + description: Option, + children: SmallVec<[AnyElement; 2]>, +} + +impl StorySection { + pub fn new() -> Self { + Self { + description: None, + children: SmallVec::new(), + } + } + + pub fn description(mut self, description: impl Into) -> Self { + self.description = Some(description.into()); + self + } +} + +impl RenderOnce for StorySection { + type Rendered = Div; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with( + self.children.into_iter(), + || Story::divider().into_any_element(), + )); + + Story::section() + // Section title + .py_2() + // Section description + .when_some(self.description.clone(), |section, description| { + section.child(Story::description(description)) + }) + .child(div().flex().flex_col().gap_2().children(children)) + .child(Story::divider()) + } +} + +impl ParentElement for StorySection { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } } diff --git a/crates/storybook2/Cargo.toml b/crates/storybook2/Cargo.toml index d0467df47111ade82c17047dfc7f5a6752ea1ff5..db79c9faca9052c383e8809b4ae064bf9a847609 100644 --- a/crates/storybook2/Cargo.toml +++ b/crates/storybook2/Cargo.toml @@ -18,6 +18,7 @@ dialoguer = { version = "0.11.0", features = ["fuzzy-select"] } editor = { package = "editor2", path = "../editor2" } fuzzy = { package = "fuzzy2", path = "../fuzzy2" } gpui = { package = "gpui2", path = "../gpui2" } +indoc.workspace = true itertools = "0.11.0" language = { package = "language2", path = "../language2" } log.workspace = true diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index ccd13cb4d80b1e739cef0671a3bfd54b78264fea..99d722988d086d932c6bd734992720273f02e2e3 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,8 +1,9 @@ use gpui::{ - blue, div, green, red, white, Div, HighlightStyle, InteractiveText, ParentElement, Render, - Styled, StyledText, View, VisualContext, WindowContext, + div, green, red, Component, HighlightStyle, InteractiveText, IntoElement, ParentElement, + Render, Styled, StyledText, View, VisualContext, WindowContext, }; -use ui::v_stack; +use indoc::indoc; +use story::*; pub struct TextStory; @@ -13,62 +14,164 @@ impl TextStory { } impl Render for TextStory { - type Element = Div; + type Element = Component; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { - v_stack() - .bg(blue()) - .child( - div() - .flex() - .child(div().max_w_96().bg(white()).child(concat!( - "max-width: 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))), - ) - .child(div().h_5()) - .child(div().flex().flex_col().w_96().bg(white()).child(concat!( - "flex-col. width: 96; The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))) - .child(div().h_5()) - .child( - div() - .flex() - .child(div().min_w_96().bg(white()).child(concat!( - "min-width: 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", -)))) - .child(div().h_5()) - .child(div().flex().w_96().bg(white()).child(div().overflow_hidden().child(concat!( - "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - )))) - // NOTE: When rendering text in a horizonal flex container, - // Taffy will not pass width constraints down from the parent. - // To fix this, render text in a praent with overflow: hidden, which - .child(div().h_5()) - .child(div().flex().w_96().bg(red()).child(concat!( - "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))).child( - InteractiveText::new( - "interactive", - StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ - (6..11, HighlightStyle { - background_color: Some(green()), - ..Default::default() + StoryContainer::new("Text Story", "crates/storybook2/src/stories/text.rs") + .children( + vec![ + + StorySection::new() + .child( + StoryItem::new("Default", div().bg(gpui::blue()).child("Hello World!")) + .usage(indoc! {r##" + div() + .child("Hello World!") + "## }), - ]), ) - .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { - println!("Clicked range {range_ix}"); - }) - ) + .child( + StoryItem::new("Wrapping Text", + div().max_w_96() + .child( + concat!( + "The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + ) + ) + ) + .description("Set a width or max-width to enable text wrapping.") + .usage(indoc! {r##" + div() + .max_w_96() + .child("Some text that you want to wrap.") + "## + }) + ) + .child( + StoryItem::new("tbd", + div().flex().w_96().child(div().overflow_hidden().child(concat!( + "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + ))) + ) + ) + .child( + StoryItem::new("Text in Horizontal Flex", + div().flex().w_96().bg(red()).child(concat!( + "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + )) + ) + .usage(indoc! {r##" + // NOTE: When rendering text in a horizonal flex container, + // Taffy will not pass width constraints down from the parent. + // To fix this, render text in a parent with overflow: hidden + + div() + .max_w_96() + .child("Some text that you want to wrap.") + "## + }) + ) + .child( + StoryItem::new("Interactive Text", + InteractiveText::new( + "interactive", + StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ + (6..11, HighlightStyle { + background_color: Some(green()), + ..Default::default() + }), + ]), + ) + .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { + println!("Clicked range {range_ix}"); + }) + ) + .usage(indoc! {r##" + InteractiveText::new( + "interactive", + StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ + (6..11, HighlightStyle { + background_color: Some(green()), + ..Default::default() + }), + ]), + ) + .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { + println!("Clicked range {range_ix}"); + }) + "## + }) + ) + ] + ).into_element() } } + +// TODO: Check all were updated to new style and remove + +// impl Render for TextStory { +// type Element = Div; + +// fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { +// v_stack() +// .bg(blue()) +// .child( +// div() +// .flex() +// .child(div().max_w_96().bg(white()).child(concat!( +// "max-width: 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))), +// ) +// .child(div().h_5()) +// .child(div().flex().flex_col().w_96().bg(white()).child(concat!( +// "flex-col. width: 96; The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))) +// .child(div().h_5()) +// .child( +// div() +// .flex() +// .child(div().min_w_96().bg(white()).child(concat!( +// "min-width: 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// )))) +// .child(div().h_5()) +// .child(div().flex().w_96().bg(white()).child(div().overflow_hidden().child(concat!( +// "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// )))) +// // NOTE: When rendering text in a horizonal flex container, +// // Taffy will not pass width constraints down from the parent. +// // To fix this, render text in a parent with overflow: hidden +// .child(div().h_5()) +// .child(div().flex().w_96().bg(red()).child(concat!( +// "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))).child( +// InteractiveText::new( +// "interactive", +// StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ +// (6..11, HighlightStyle { +// background_color: Some(green()), +// ..Default::default() +// }), +// ]), +// ) +// .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { +// println!("Clicked range {range_ix}"); +// }) +// ) +// } +// } diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 9cc2dd51f7c73388679bee01d480ecbac328cec8..523e93cf5267e310d691ee4ca19db1cc67cfbb4b 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -19,6 +19,7 @@ use ui::prelude::*; use crate::assets::Assets; use crate::story_selector::{ComponentStory, StorySelector}; +pub use indoc::indoc; // gpui::actions! { // storybook, diff --git a/crates/ui2/src/components/stories/icon_button.rs b/crates/ui2/src/components/stories/icon_button.rs index 583f453d188b9df5aaaf71b5bb1897814c0a6f51..0d219efbc2fe72ac4e7695e2f86bf305d26c5537 100644 --- a/crates/ui2/src/components/stories/icon_button.rs +++ b/crates/ui2/src/components/stories/icon_button.rs @@ -1,5 +1,5 @@ -use gpui::{Div, Render}; -use story::Story; +use gpui::{Component, Render}; +use story::{StoryContainer, StoryItem, StorySection}; use crate::{prelude::*, Tooltip}; use crate::{Icon, IconButton}; @@ -7,57 +7,167 @@ use crate::{Icon, IconButton}; pub struct IconButtonStory; impl Render for IconButtonStory { - type Element = Div; + type Element = Component; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - Story::container() - .child(Story::title_for::()) - .child(Story::label("Default")) - .child(div().w_8().child(IconButton::new("icon_a", Icon::Hash))) - .child(Story::label("Selected")) - .child( - div() - .w_8() - .child(IconButton::new("icon_a", Icon::Hash).selected(true)), - ) - .child(Story::label("Selected with `selected_icon`")) - .child( - div().w_8().child( - IconButton::new("icon_a", Icon::AudioOn) - .selected(true) - .selected_icon(Icon::AudioOff), - ), - ) - .child(Story::label("Disabled")) - .child( - div() - .w_8() - .child(IconButton::new("icon_a", Icon::Hash).disabled(true)), - ) - .child(Story::label("With `on_click`")) - .child( - div() - .w_8() - .child( - IconButton::new("with_on_click", Icon::Ai).on_click(|_event, _cx| { - println!("Clicked!"); - }), - ), - ) - .child(Story::label("With `tooltip`")) - .child( - div().w_8().child( - IconButton::new("with_tooltip", Icon::MessageBubbles) - .tooltip(|cx| Tooltip::text("Open messages", cx)), - ), - ) - .child(Story::label("Selected with `tooltip`")) - .child( - div().w_8().child( - IconButton::new("selected_with_tooltip", Icon::InlayHint) - .selected(true) - .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), - ), - ) + let default_button = StoryItem::new( + "Default", + IconButton::new("default_icon_button", Icon::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", Icon::Hash).selected(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", Icon::AudioOn) + .selected(true) + .selected_icon(Icon::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", Icon::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", Icon::Ai).on_click(|_event, _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", Icon::MessageBubbles) + .tooltip(|cx| Tooltip::text("Open messages", cx)), + ) + .description("Displays an icon button that has a tooltip when hovered.") + .usage( + r#" + IconButton::new("with_tooltip_button", Icon::MessageBubbles) + .tooltip(|cx| Tooltip::text("Open messages", cx)) + "#, + ); + + let selected_with_tooltip_button = StoryItem::new( + "Selected with `tooltip`", + IconButton::new("selected_with_tooltip_button", Icon::InlayHint) + .selected(true) + .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), + ) + .description("Displays a selected icon button with tooltip.") + .usage( + r#" + IconButton::new("selected_with_tooltip_button", Icon::InlayHint) + .selected(true) + .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)) + "#, + ); + + let buttons = vec![ + default_button, + selected_button, + selected_with_selected_icon, + disabled_button, + with_on_click_button, + with_tooltip_button, + selected_with_tooltip_button, + ]; + + StoryContainer::new( + "Icon Button", + "crates/ui2/src/components/stories/icon_button.rs", + ) + .children(vec![StorySection::new().children(buttons)]) + .into_element() + + // Story::container() + // .child(Story::title_for::()) + // .child(Story::label("Default")) + // .child(div().w_8().child(IconButton::new("icon_a", Icon::Hash))) + // .child(Story::label("Selected")) + // .child( + // div() + // .w_8() + // .child(IconButton::new("icon_a", Icon::Hash).selected(true)), + // ) + // .child(Story::label("Selected with `selected_icon`")) + // .child( + // div().w_8().child( + // IconButton::new("icon_a", Icon::AudioOn) + // .selected(true) + // .selected_icon(Icon::AudioOff), + // ), + // ) + // .child(Story::label("Disabled")) + // .child( + // div() + // .w_8() + // .child(IconButton::new("icon_a", Icon::Hash).disabled(true)), + // ) + // .child(Story::label("With `on_click`")) + // .child( + // div() + // .w_8() + // .child( + // IconButton::new("with_on_click", Icon::Ai).on_click(|_event, _cx| { + // println!("Clicked!"); + // }), + // ), + // ) + // .child(Story::label("With `tooltip`")) + // .child( + // div().w_8().child( + // IconButton::new("with_tooltip", Icon::MessageBubbles) + // .tooltip(|cx| Tooltip::text("Open messages", cx)), + // ), + // ) + // .child(Story::label("Selected with `tooltip`")) + // .child( + // div().w_8().child( + // IconButton::new("selected_with_tooltip", Icon::InlayHint) + // .selected(true) + // .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), + // ), + // ) } }