Unify Story/StoryContainers (#17114)

Unify the various Story containers, and use gpui default colors over the
custom `StoryColors`.

Release Notes:

- N/A
This commit is contained in:
Nate Butler 2024-08-29 17:27:01 -04:00 committed by GitHub
parent 449e744c14
commit 3d175f685f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 356 additions and 510 deletions

View File

@ -1,5 +1,5 @@
use gpui::prelude::*; use gpui::prelude::*;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use ui::prelude::*; use ui::prelude::*;
use crate::notifications::collab_notification::CollabNotification; use crate::notifications::collab_notification::CollabNotification;
@ -10,41 +10,39 @@ impl Render for CollabNotificationStory {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let window_container = |width, height| div().w(px(width)).h(px(height)); let window_container = |width, height| div().w(px(width)).h(px(height));
StoryContainer::new( Story::container()
"CollabNotification Story", .child(Story::title_for::<CollabNotification>())
"crates/collab_ui/src/notifications/stories/collab_notification.rs", .child(
) StorySection::new().child(StoryItem::new(
.child( "Incoming Call Notification",
StorySection::new().child(StoryItem::new( window_container(400., 72.).child(
"Incoming Call Notification", CollabNotification::new(
window_container(400., 72.).child( "https://avatars.githubusercontent.com/u/1486634?v=4",
CollabNotification::new( Button::new("accept", "Accept"),
"https://avatars.githubusercontent.com/u/1486634?v=4", Button::new("decline", "Decline"),
Button::new("accept", "Accept"), )
Button::new("decline", "Decline"), .child(
) v_flex()
.child( .overflow_hidden()
v_flex() .child(Label::new("maxdeviant is sharing a project in Zed")),
.overflow_hidden() ),
.child(Label::new("maxdeviant is sharing a project in Zed")),
), ),
), )),
)), )
) .child(
.child( StorySection::new().child(StoryItem::new(
StorySection::new().child(StoryItem::new( "Project Shared Notification",
"Project Shared Notification", window_container(400., 72.).child(
window_container(400., 72.).child( CollabNotification::new(
CollabNotification::new( "https://avatars.githubusercontent.com/u/1714999?v=4",
"https://avatars.githubusercontent.com/u/1714999?v=4", Button::new("open", "Open"),
Button::new("open", "Open"), Button::new("dismiss", "Dismiss"),
Button::new("dismiss", "Dismiss"), )
) .child(Label::new("iamnbutler"))
.child(Label::new("iamnbutler")) .child(Label::new("is sharing a project in Zed:"))
.child(Label::new("is sharing a project in Zed:")) .child(Label::new("zed")),
.child(Label::new("zed")), ),
), )),
)), )
)
} }
} }

View File

@ -1,123 +1,16 @@
use gpui::{ use gpui::{
div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, WindowContext, div, prelude::*, px, rems, AnyElement, DefaultColor, DefaultColors, Div, SharedString,
WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use smallvec::SmallVec; 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., 1., 1.),
card_background: hsla(0. / 360., 0. / 100., 96. / 100., 1.),
divider: hsla(216. / 360., 11. / 100., 86. / 100., 1.),
link: hsla(206. / 360., 1., 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 extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
self.children.extend(elements)
}
}
impl RenderOnce for StoryContainer {
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
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_1()
.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_x_hidden()
.overflow_y_scroll()
.flex()
.flex_col()
.pb_4()
.children(self.children),
)
}
}
pub struct Story {} pub struct Story {}
impl Story { impl Story {
pub fn container() -> gpui::Stateful<Div> { pub fn container() -> gpui::Stateful<Div> {
let colors = DefaultColors::light();
div() div()
.id("story_container") .id("story_container")
.overflow_y_scroll() .overflow_y_scroll()
@ -125,70 +18,16 @@ impl Story {
.min_h_full() .min_h_full()
.flex() .flex()
.flex_col() .flex_col()
.bg(story_color().background) .text_color(DefaultColor::Text.hsla(&colors))
} .bg(DefaultColor::Background.hsla(&colors))
// 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_1()
.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 { pub fn title(title: impl Into<SharedString>) -> impl Element {
let colors = DefaultColors::light();
div() div()
.text_xs() .text_xs()
.text_color(story_color().primary) .text_color(DefaultColor::Text.hsla(&colors))
.child(title.into()) .child(title.into())
} }
@ -197,59 +36,66 @@ impl Story {
} }
pub fn section() -> Div { pub fn section() -> Div {
let colors = DefaultColors::light();
div() div()
.p_4() .p_4()
.m_4() .m_4()
.border_1() .border_1()
.border_color(story_color().border) .border_color(DefaultColor::Separator.hsla(&colors))
} }
pub fn section_title() -> Div { pub fn section_title() -> Div {
div().text_lg().text_color(story_color().primary) let colors = DefaultColors::light();
div().text_lg().text_color(DefaultColor::Text.hsla(&colors))
} }
pub fn group() -> Div { pub fn group() -> Div {
div().my_2().bg(story_color().background) let colors = DefaultColors::light();
div().my_2().bg(DefaultColor::Container.hsla(&colors))
} }
pub fn code_block(code: impl Into<SharedString>) -> Div { pub fn code_block(code: impl Into<SharedString>) -> Div {
let colors = DefaultColors::light();
div() div()
.size_full() .size_full()
.p_2() .p_2()
.max_w(rems(36.)) .max_w(rems(36.))
.bg(gpui::black()) .bg(DefaultColor::Container.hsla(&colors))
.rounded_md() .rounded_md()
.text_sm() .text_sm()
.text_color(gpui::white()) .text_color(DefaultColor::Text.hsla(&colors))
.overflow_hidden() .overflow_hidden()
.child(code.into()) .child(code.into())
} }
pub fn divider() -> Div { pub fn divider() -> Div {
div().my_2().h(px(1.)).bg(story_color().divider) let colors = DefaultColors::light();
}
pub fn link(link: impl Into<SharedString>) -> impl Element {
div() div()
.id(ElementId::from(SharedString::from(reasonably_unique_id()))) .my_2()
.text_xs() .h(px(1.))
.text_color(story_color().link) .bg(DefaultColor::Separator.hsla(&colors))
.cursor(gpui::CursorStyle::PointingHand)
.child(link.into())
} }
pub fn description(description: impl Into<SharedString>) -> impl Element { pub fn description(description: impl Into<SharedString>) -> impl Element {
let colors = DefaultColors::light();
div() div()
.text_sm() .text_sm()
.text_color(story_color().secondary) .text_color(DefaultColor::Text.hsla(&colors))
.min_w_96() .min_w_96()
.child(description.into()) .child(description.into())
} }
pub fn label(label: impl Into<SharedString>) -> impl Element { pub fn label(label: impl Into<SharedString>) -> impl Element {
let colors = DefaultColors::light();
div() div()
.text_xs() .text_xs()
.text_color(story_color().primary) .text_color(DefaultColor::Text.hsla(&colors))
.child(label.into()) .child(label.into())
} }
@ -290,6 +136,8 @@ impl StoryItem {
impl RenderOnce for StoryItem { impl RenderOnce for StoryItem {
fn render(self, _cx: &mut WindowContext) -> impl IntoElement { fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
let colors = DefaultColors::light();
div() div()
.my_2() .my_2()
.flex() .flex()
@ -304,9 +152,9 @@ impl RenderOnce for StoryItem {
.child( .child(
div() div()
.rounded_md() .rounded_md()
.bg(story_color().card_background) .bg(DefaultColor::Background.hsla(&colors))
.border_1() .border_1()
.border_color(story_color().border) .border_color(DefaultColor::Border.hsla(&colors))
.py_1() .py_1()
.px_2() .px_2()
.overflow_hidden() .overflow_hidden()

View File

@ -15,98 +15,106 @@ impl TextStory {
impl Render for TextStory { impl Render for TextStory {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement { fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
StoryContainer::new("Text Story", "crates/storybook/src/stories/text.rs") Story::container()
.children( .child(Story::title("Text"))
vec![ .children(vec![
StorySection::new()
StorySection::new() .child(
.child( StoryItem::new("Default", div().bg(gpui::blue()).child("Hello World!"))
StoryItem::new("Default", div().bg(gpui::blue()).child("Hello World!")) .usage(indoc! {r##"
div()
.child("Hello World!")
"##
}),
)
.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##" .usage(indoc! {r##"
div() div()
.child("Hello World!") .max_w_96()
.child("Some text that you want to wrap.")
"## "##
}), }),
) )
.child( .child(
StoryItem::new("Wrapping Text", StoryItem::new(
div().max_w_96() "tbd",
.child( div().flex().w_96().child(
concat!( div().overflow_hidden().child(concat!(
"The quick brown fox jumps over the lazy dog. ", "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. ", "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.", "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.") .child(
.usage(indoc! {r##" StoryItem::new(
div() "Text in Horizontal Flex",
.max_w_96() div().flex().w_96().bg(red()).child(concat!(
.child("Some text that you want to wrap.") "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( )
StoryItem::new("tbd", .usage(indoc! {r##"
div().flex().w_96().child(div().overflow_hidden().child(concat!( // NOTE: When rendering text in a horizontal flex container,
"flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", // Taffy will not pass width constraints down from the parent.
"Meanwhile, the lazy dog decided it was time for a change. ", // To fix this, render text in a parent with overflow: hidden
"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 horizontal flex container,
// Taffy will not pass width constraints down from the parent.
// To fix this, render text in a parent with overflow: hidden
div() div()
.max_w_96() .max_w_96()
.child("Some text that you want to wrap.") .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##" .child(
InteractiveText::new( StoryItem::new(
"interactive", "Interactive Text",
StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ InteractiveText::new(
(6..11, HighlightStyle { "interactive",
background_color: Some(green()), StyledText::new("Hello world, how is it going?").with_highlights(
..Default::default() &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}");
}),
) )
.on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { .usage(indoc! {r##"
println!("Clicked range {range_ix}"); 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()
).into_element() }),
]),
)
.on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| {
println!("Clicked range {range_ix}");
})
"##
}),
),
])
.into_element()
} }
} }

View File

@ -1,5 +1,5 @@
use gpui::Render; use gpui::Render;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use ui::prelude::*; use ui::prelude::*;
@ -9,13 +9,11 @@ pub struct ApplicationMenuStory;
impl Render for ApplicationMenuStory { impl Render for ApplicationMenuStory {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
StoryContainer::new( Story::container()
"ApplicationMenu Story", .child(Story::title_for::<ApplicationMenu>())
"crates/title_bar/src/stories/application_menu.rs", .child(StorySection::new().child(StoryItem::new(
) "Application Menu",
.child(StorySection::new().child(StoryItem::new( h_flex().child(ApplicationMenu::new()),
"Application Menu", )))
h_flex().child(ApplicationMenu::new()),
)))
} }
} }

View File

@ -1,5 +1,5 @@
use gpui::Render; use gpui::Render;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use crate::{prelude::*, AudioStatus, Availability, AvatarAvailabilityIndicator}; use crate::{prelude::*, AudioStatus, Availability, AvatarAvailabilityIndicator};
use crate::{Avatar, AvatarAudioStatusIndicator}; use crate::{Avatar, AvatarAudioStatusIndicator};
@ -8,7 +8,8 @@ pub struct AvatarStory;
impl Render for AvatarStory { impl Render for AvatarStory {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
StoryContainer::new("Avatar", "crates/ui/src/components/stories/avatar.rs") Story::container()
.child(Story::title_for::<Avatar>())
.child( .child(
StorySection::new() StorySection::new()
.child(StoryItem::new( .child(StoryItem::new(

View File

@ -1,5 +1,5 @@
use gpui::Render; use gpui::Render;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use crate::{prelude::*, IconButtonShape, Tooltip}; use crate::{prelude::*, IconButtonShape, Tooltip};
use crate::{IconButton, IconName}; use crate::{IconButton, IconName};
@ -111,38 +111,36 @@ impl Render for IconButtonStory {
selected_with_tooltip_button, selected_with_tooltip_button,
]; ];
StoryContainer::new( Story::container()
"Icon Button", .child(Story::title_for::<IconButton>())
"crates/ui/src/components/stories/icon_button.rs", .child(StorySection::new().children(buttons))
) .child(
.child(StorySection::new().children(buttons)) StorySection::new().child(StoryItem::new(
.child( "Square",
StorySection::new().child(StoryItem::new( h_flex()
"Square", .gap_2()
h_flex() .child(
.gap_2() IconButton::new("square-medium", IconName::Close)
.child( .shape(IconButtonShape::Square)
IconButton::new("square-medium", IconName::Close) .icon_size(IconSize::Medium),
.shape(IconButtonShape::Square) )
.icon_size(IconSize::Medium), .child(
) IconButton::new("square-small", IconName::Close)
.child( .shape(IconButtonShape::Square)
IconButton::new("square-small", IconName::Close) .icon_size(IconSize::Small),
.shape(IconButtonShape::Square) )
.icon_size(IconSize::Small), .child(
) IconButton::new("square-xsmall", IconName::Close)
.child( .shape(IconButtonShape::Square)
IconButton::new("square-xsmall", IconName::Close) .icon_size(IconSize::XSmall),
.shape(IconButtonShape::Square) )
.icon_size(IconSize::XSmall), .child(
) IconButton::new("square-indicator", IconName::Close)
.child( .shape(IconButtonShape::Square)
IconButton::new("square-indicator", IconName::Close) .icon_size(IconSize::Indicator),
.shape(IconButtonShape::Square) ),
.icon_size(IconSize::Indicator), )),
), )
)), .into_element()
)
.into_element()
} }
} }

View File

@ -1,7 +1,7 @@
use gpui::NoAction; use gpui::NoAction;
use gpui::Render; use gpui::Render;
use itertools::Itertools; use itertools::Itertools;
use story::{Story, StoryContainer}; use story::Story;
use crate::{prelude::*, KeyBinding}; use crate::{prelude::*, KeyBinding};
@ -15,28 +15,23 @@ impl Render for KeybindingStory {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2); let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2);
StoryContainer::new( Story::container()
"KeyBinding", .child(Story::title_for::<KeyBinding>())
"crates/ui/src/components/stories/keybinding.rs", .child(Story::label("Single Key"))
) .child(KeyBinding::new(binding("Z")))
.child(Story::label("Single Key")) .child(Story::label("Single Key with Modifier"))
.child(KeyBinding::new(binding("Z"))) .child(
.child(Story::label("Single Key with Modifier")) div()
.child( .flex()
div() .gap_3()
.flex() .child(KeyBinding::new(binding("ctrl-c")))
.gap_3() .child(KeyBinding::new(binding("alt-c")))
.child(KeyBinding::new(binding("ctrl-c"))) .child(KeyBinding::new(binding("cmd-c")))
.child(KeyBinding::new(binding("alt-c"))) .child(KeyBinding::new(binding("shift-c"))),
.child(KeyBinding::new(binding("cmd-c"))) )
.child(KeyBinding::new(binding("shift-c"))), .child(Story::label("Single Key with Modifier (Permuted)"))
) .child(
.child(Story::label("Single Key with Modifier (Permuted)")) div().flex().flex_col().children(
.child(
div()
.flex()
.flex_col()
.children(
all_modifier_permutations all_modifier_permutations
.chunks(4) .chunks(4)
.into_iter() .into_iter()
@ -50,31 +45,35 @@ impl Render for KeybindingStory {
})) }))
}), }),
), ),
) )
.child(Story::label("Single Key with All Modifiers")) .child(Story::label("Single Key with All Modifiers"))
.child(KeyBinding::new(binding("ctrl-alt-cmd-shift-z"))) .child(KeyBinding::new(binding("ctrl-alt-cmd-shift-z")))
.child(Story::label("Chord")) .child(Story::label("Chord"))
.child(KeyBinding::new(binding("a z"))) .child(KeyBinding::new(binding("a z")))
.child(Story::label("Chord with Modifier")) .child(Story::label("Chord with Modifier"))
.child(KeyBinding::new(binding("ctrl-a shift-z"))) .child(KeyBinding::new(binding("ctrl-a shift-z")))
.child(KeyBinding::new(binding("fn-s"))) .child(KeyBinding::new(binding("fn-s")))
.child(Story::label("Single Key with All Modifiers (Linux)")) .child(Story::label("Single Key with All Modifiers (Linux)"))
.child( .child(
KeyBinding::new(binding("ctrl-alt-cmd-shift-z")).platform_style(PlatformStyle::Linux), KeyBinding::new(binding("ctrl-alt-cmd-shift-z"))
) .platform_style(PlatformStyle::Linux),
.child(Story::label("Chord (Linux)")) )
.child(KeyBinding::new(binding("a z")).platform_style(PlatformStyle::Linux)) .child(Story::label("Chord (Linux)"))
.child(Story::label("Chord with Modifier (Linux)")) .child(KeyBinding::new(binding("a z")).platform_style(PlatformStyle::Linux))
.child(KeyBinding::new(binding("ctrl-a shift-z")).platform_style(PlatformStyle::Linux)) .child(Story::label("Chord with Modifier (Linux)"))
.child(KeyBinding::new(binding("fn-s")).platform_style(PlatformStyle::Linux)) .child(KeyBinding::new(binding("ctrl-a shift-z")).platform_style(PlatformStyle::Linux))
.child(Story::label("Single Key with All Modifiers (Windows)")) .child(KeyBinding::new(binding("fn-s")).platform_style(PlatformStyle::Linux))
.child( .child(Story::label("Single Key with All Modifiers (Windows)"))
KeyBinding::new(binding("ctrl-alt-cmd-shift-z")).platform_style(PlatformStyle::Windows), .child(
) KeyBinding::new(binding("ctrl-alt-cmd-shift-z"))
.child(Story::label("Chord (Windows)")) .platform_style(PlatformStyle::Windows),
.child(KeyBinding::new(binding("a z")).platform_style(PlatformStyle::Windows)) )
.child(Story::label("Chord with Modifier (Windows)")) .child(Story::label("Chord (Windows)"))
.child(KeyBinding::new(binding("ctrl-a shift-z")).platform_style(PlatformStyle::Windows)) .child(KeyBinding::new(binding("a z")).platform_style(PlatformStyle::Windows))
.child(KeyBinding::new(binding("fn-s")).platform_style(PlatformStyle::Windows)) .child(Story::label("Chord with Modifier (Windows)"))
.child(
KeyBinding::new(binding("ctrl-a shift-z")).platform_style(PlatformStyle::Windows),
)
.child(KeyBinding::new(binding("fn-s")).platform_style(PlatformStyle::Windows))
} }
} }

View File

@ -1,5 +1,5 @@
use gpui::Render; use gpui::Render;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use crate::{prelude::*, ToggleButton}; use crate::{prelude::*, ToggleButton};
@ -7,89 +7,87 @@ pub struct ToggleButtonStory;
impl Render for ToggleButtonStory { impl Render for ToggleButtonStory {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
StoryContainer::new( Story::container()
"Toggle Button", .child(Story::title_for::<ToggleButton>())
"crates/ui/src/components/stories/toggle_button.rs", .child(
) StorySection::new().child(
.child( StoryItem::new(
StorySection::new().child( "Default",
StoryItem::new( ToggleButton::new("default_toggle_button", "Hello"),
"Default", )
ToggleButton::new("default_toggle_button", "Hello"), .description("Displays a toggle button.")
) .usage(""),
.description("Displays a toggle button.") ),
.usage(""), )
), .child(
) StorySection::new().child(
.child( StoryItem::new(
StorySection::new().child( "Toggle button group",
StoryItem::new( h_flex()
"Toggle button group", .child(
h_flex() ToggleButton::new(1, "Apple")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(1, "Apple") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .first(),
.size(ButtonSize::Large) )
.first(), .child(
) ToggleButton::new(2, "Banana")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(2, "Banana") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .middle(),
.size(ButtonSize::Large) )
.middle(), .child(
) ToggleButton::new(3, "Cherry")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(3, "Cherry") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .middle(),
.size(ButtonSize::Large) )
.middle(), .child(
) ToggleButton::new(4, "Dragonfruit")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(4, "Dragonfruit") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .last(),
.size(ButtonSize::Large) ),
.last(), )
), .description("Displays a group of toggle buttons.")
) .usage(""),
.description("Displays a group of toggle buttons.") ),
.usage(""), )
), .child(
) StorySection::new().child(
.child( StoryItem::new(
StorySection::new().child( "Toggle button group with selection",
StoryItem::new( h_flex()
"Toggle button group with selection", .child(
h_flex() ToggleButton::new(1, "Apple")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(1, "Apple") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .first(),
.size(ButtonSize::Large) )
.first(), .child(
) ToggleButton::new(2, "Banana")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(2, "Banana") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .selected(true)
.size(ButtonSize::Large) .middle(),
.selected(true) )
.middle(), .child(
) ToggleButton::new(3, "Cherry")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(3, "Cherry") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .middle(),
.size(ButtonSize::Large) )
.middle(), .child(
) ToggleButton::new(4, "Dragonfruit")
.child( .style(ButtonStyle::Filled)
ToggleButton::new(4, "Dragonfruit") .size(ButtonSize::Large)
.style(ButtonStyle::Filled) .last(),
.size(ButtonSize::Large) ),
.last(), )
), .description("Displays a group of toggle buttons.")
) .usage(""),
.description("Displays a group of toggle buttons.") ),
.usage(""), )
), .into_element()
)
.into_element()
} }
} }

View File

@ -1,5 +1,5 @@
use gpui::Render; use gpui::Render;
use story::{StoryContainer, StoryItem, StorySection}; use story::{Story, StoryItem, StorySection};
use crate::{prelude::*, ToolStrip, Tooltip}; use crate::{prelude::*, ToolStrip, Tooltip};
@ -7,29 +7,27 @@ pub struct ToolStripStory;
impl Render for ToolStripStory { impl Render for ToolStripStory {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
StoryContainer::new( Story::container()
"Tool Strip", .child(Story::title_for::<ToolStrip>())
"crates/ui/src/components/stories/tool_strip.rs", .child(
) StorySection::new().child(StoryItem::new(
.child( "Vertical Tool Strip",
StorySection::new().child(StoryItem::new( h_flex().child(
"Vertical Tool Strip", ToolStrip::vertical("tool_strip_example")
h_flex().child( .tool(
ToolStrip::vertical("tool_strip_example") IconButton::new("example_tool", IconName::AudioOn)
.tool( .tooltip(|cx| Tooltip::text("Example tool", cx)),
IconButton::new("example_tool", IconName::AudioOn) )
.tooltip(|cx| Tooltip::text("Example tool", cx)), .tool(
) IconButton::new("example_tool_2", IconName::MicMute)
.tool( .tooltip(|cx| Tooltip::text("Example tool 2", cx)),
IconButton::new("example_tool_2", IconName::MicMute) )
.tooltip(|cx| Tooltip::text("Example tool 2", cx)), .tool(
) IconButton::new("example_tool_3", IconName::Screen)
.tool( .tooltip(|cx| Tooltip::text("Example tool 3", cx)),
IconButton::new("example_tool_3", IconName::Screen) ),
.tooltip(|cx| Tooltip::text("Example tool 3", cx)), ),
), )),
), )
)),
)
} }
} }