Detailed changes
@@ -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",
@@ -8,3 +8,5 @@ publish = false
[dependencies]
gpui = { package = "gpui2", path = "../gpui2" }
+smallvec.workspace = true
+itertools = {package = "itertools", version = "0.10"}
@@ -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<SharedString>, 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<Div>;
+
+ 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<T>(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::<T>())
+ .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<SharedString>) -> 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::<T>())
}
+ 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<SharedString>) -> 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<SharedString>) -> 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<SharedString>) -> impl Element {
+ div()
+ .text_sm()
+ .text_color(story_color().secondary)
+ .min_w_96()
+ .child(description.into())
+ }
+
pub fn label(label: impl Into<SharedString>) -> 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<SharedString>,
+ usage: Option<SharedString>,
+}
+
+impl StoryItem {
+ pub fn new(label: impl Into<SharedString>, 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<SharedString>) -> Self {
+ self.description = Some(description.into());
+ self
+ }
+
+ pub fn usage(mut self, code: impl Into<SharedString>) -> 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<SharedString>,
+ children: SmallVec<[AnyElement; 2]>,
+}
+
+impl StorySection {
+ pub fn new() -> Self {
+ Self {
+ description: None,
+ children: SmallVec::new(),
+ }
+ }
+
+ pub fn description(mut self, description: impl Into<SharedString>) -> 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
+ }
}
@@ -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
@@ -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<StoryContainer>;
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> 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>) -> 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}");
+// })
+// )
+// }
+// }
@@ -19,6 +19,7 @@ use ui::prelude::*;
use crate::assets::Assets;
use crate::story_selector::{ComponentStory, StorySelector};
+pub use indoc::indoc;
// gpui::actions! {
// storybook,
@@ -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<StoryContainer>;
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
- Story::container()
- .child(Story::title_for::<IconButton>())
- .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::<IconButton>())
+ // .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)),
+ // ),
+ // )
}
}