diff --git a/crates/story/src/scrollable_story.rs b/crates/story/src/scrollable_story.rs index 2b667638..d08c367f 100644 --- a/crates/story/src/scrollable_story.rs +++ b/crates/story/src/scrollable_story.rs @@ -2,9 +2,8 @@ use std::cell::Cell; use std::rc::Rc; use gpui::{ - div, px, size, Entity, InteractiveElement, ParentElement, Pixels, Render, ScrollHandle, - SharedString, Size, StatefulInteractiveElement as _, Styled, View, ViewContext, VisualContext, - WindowContext, + div, px, size, Entity, InteractiveElement, IntoElement, ParentElement, Pixels, Render, + ScrollHandle, SharedString, Size, Styled, View, ViewContext, VisualContext, WindowContext, }; use ui::button::Button; use ui::divider::Divider; @@ -89,6 +88,61 @@ impl ScrollableStory { self.message = SharedString::from(msg.to_string()); cx.notify(); } + + fn render_buttons(&mut self, cx: &mut ViewContext) -> impl IntoElement { + h_flex() + .gap_2() + .justify_between() + .child( + h_flex() + .gap_2() + .child(Button::new("test-0").label("Size 0").on_click(cx.listener( + |view, _, cx| { + view.change_test_cases(0, cx); + }, + ))) + .child(Button::new("test-1").label("Size 1").on_click(cx.listener( + |view, _, cx| { + view.change_test_cases(1, cx); + }, + ))) + .child(Button::new("test-2").label("Size 2").on_click(cx.listener( + |view, _, cx| { + view.change_test_cases(2, cx); + }, + ))) + .child(Button::new("test-3").label("Size 3").on_click(cx.listener( + |view, _, cx| { + view.change_test_cases(3, cx); + }, + ))) + .child(Divider::vertical().px_2()) + .child( + Button::new("test-axis-both") + .label("Both Scrollbar") + .on_click( + cx.listener(|view, _, cx| { + view.change_axis(ScrollbarAxis::Both, cx) + }), + ), + ) + .child( + Button::new("test-axis-vertical") + .label("Vertical") + .on_click(cx.listener(|view, _, cx| { + view.change_axis(ScrollbarAxis::Vertical, cx) + })), + ) + .child( + Button::new("test-axis-horizontal") + .label("Horizontal") + .on_click(cx.listener(|view, _, cx| { + view.change_axis(ScrollbarAxis::Horizontal, cx) + })), + ), + ) + .child(Label::new(self.message.clone())) + } } impl super::Story for ScrollableStory { @@ -97,7 +151,8 @@ impl super::Story for ScrollableStory { } fn description() -> &'static str { - "Add vertical or horizontal, or both scrollbars to a container, and use `virtual_list` to render a large number of items." + "Add vertical or horizontal, or both scrollbars to a container, \ + and use `virtual_list` to render a large number of items." } fn new_view(cx: &mut WindowContext) -> View { @@ -118,58 +173,7 @@ impl Render for ScrollableStory { v_flex() .size_full() .gap_4() - .child( - h_flex() - .gap_2() - .justify_between() - .child( - h_flex() - .gap_2() - .child(Button::new("test-0").label("Size 0").on_click(cx.listener( - |view, _, cx| { - view.change_test_cases(0, cx); - }, - ))) - .child(Button::new("test-1").label("Size 1").on_click(cx.listener( - |view, _, cx| { - view.change_test_cases(1, cx); - }, - ))) - .child(Button::new("test-2").label("Size 2").on_click(cx.listener( - |view, _, cx| { - view.change_test_cases(2, cx); - }, - ))) - .child(Button::new("test-3").label("Size 3").on_click(cx.listener( - |view, _, cx| { - view.change_test_cases(3, cx); - }, - ))) - .child(Divider::vertical().px_2()) - .child( - Button::new("test-axis-both") - .label("Both Scrollbar") - .on_click(cx.listener(|view, _, cx| { - view.change_axis(ScrollbarAxis::Both, cx) - })), - ) - .child( - Button::new("test-axis-vertical") - .label("Vertical") - .on_click(cx.listener(|view, _, cx| { - view.change_axis(ScrollbarAxis::Vertical, cx) - })), - ) - .child( - Button::new("test-axis-horizontal") - .label("Horizontal") - .on_click(cx.listener(|view, _, cx| { - view.change_axis(ScrollbarAxis::Horizontal, cx) - })), - ), - ) - .child(Label::new(self.message.clone())), - ) + .child(self.render_buttons(cx)) .child( div().w_full().child( div().relative().w_full().h(px(350.)).child( @@ -257,17 +261,16 @@ impl Render for ScrollableStory { .border_1() .border_color(cx.theme().border) .w_full() - .flex_1() .overflow_hidden() + .max_h(px(400.)) .child( v_flex() - .id("test-1") - .scrollable(cx.view().entity_id(), ScrollbarAxis::Vertical) - .focusable() .p_3() .w(self.test_width) + .id("test-1") + .scrollable(cx.view().entity_id(), ScrollbarAxis::Vertical) .gap_1() - .child("Hello world") + .child("Scrollable Example") .children(self.items.iter().take(500).map(|item| { div() .h(ITEM_HEIGHT) diff --git a/crates/story/src/switch_story.rs b/crates/story/src/switch_story.rs index 4f90ce40..7a4643fa 100644 --- a/crates/story/src/switch_story.rs +++ b/crates/story/src/switch_story.rs @@ -1,18 +1,25 @@ use gpui::{ - Div, IntoElement, ParentElement, Render, SharedString, Styled, View, ViewContext, + div, px, Div, IntoElement, ParentElement, Render, SharedString, Styled, View, ViewContext, VisualContext as _, WindowContext, }; use ui::{ - h_flex, label::Label, switch::Switch, theme::ActiveTheme, v_flex, Disableable as _, Side, - Sizable, StyledExt, + checkbox::Checkbox, h_flex, label::Label, radio::Radio, switch::Switch, theme::ActiveTheme, + v_flex, Disableable as _, Side, Sizable, StyledExt, }; +use crate::section; + pub struct SwitchStory { focus_handle: gpui::FocusHandle, switch1: bool, switch2: bool, switch3: bool, + check1: bool, + check2: bool, + check3: bool, + radio_check1: bool, + radio_check2: bool, } impl super::Story for SwitchStory { @@ -21,7 +28,7 @@ impl super::Story for SwitchStory { } fn description() -> &'static str { - "A control that allows the user to toggle between two states." + "Switch, Radio, Checkbox components testing and examples" } fn new_view(cx: &mut WindowContext) -> View { @@ -40,6 +47,11 @@ impl SwitchStory { switch1: true, switch2: false, switch3: true, + check1: false, + check2: false, + check3: true, + radio_check1: false, + radio_check2: true, } } } @@ -71,19 +83,21 @@ impl Render for SwitchStory { .border_color(theme.border) } - v_flex().gap_6() - .child( + v_flex().gap_6().child( v_flex() .items_start() .justify_center() .gap_4() .child( card(cx) - .child( - title("Marketing emails").child( - Label::new("Receive emails about new products, features, and more.").text_color(theme.muted_foreground) + .child( + title("Marketing emails").child( + Label::new( + "Receive emails about new products, features, and more.", + ) + .text_color(theme.muted_foreground), + ), ) - ) .child( Switch::new("switch1") .checked(self.switch1) @@ -97,11 +111,15 @@ impl Render for SwitchStory { ) .child( card(cx) - .child( - title("Security emails").child( - Label::new("Receive emails about your account security. When turn off, you never receive email again.").text_color(theme.muted_foreground) + .child( + title("Security emails").child( + Label::new( + "Receive emails about your account security. \ + When turn off, you never receive email again.", + ) + .text_color(theme.muted_foreground), + ), ) - ) .child( Switch::new("switch2") .checked(self.switch2) @@ -112,34 +130,136 @@ impl Render for SwitchStory { ), ) .child( - card(cx).v_flex() - .items_start().child(title("Disabled Switches")).child( - h_flex().items_center() - .gap_6() - .child(Switch::new("switch3").disabled(true).on_click(|v, _| { - println!("Switch value changed: {:?}", v); - })) + card(cx) + .v_flex() + .items_start() + .child(title("Disabled Switches")) .child( - Switch::new("switch3_1").label("Airplane Mode") - .checked(true) - .disabled(true) - .on_click(|ev, _| { - println!("Switch value changed: {:?}", ev); - }), - )) + h_flex() + .items_center() + .gap_6() + .child(Switch::new("switch3").disabled(true).on_click(|v, _| { + println!("Switch value changed: {:?}", v); + })) + .child( + Switch::new("switch3_1") + .label("Airplane Mode") + .checked(true) + .disabled(true) + .on_click(|ev, _| { + println!("Switch value changed: {:?}", ev); + }), + ), + ), ) .child( - card(cx).v_flex() - .items_start().child(title("Small Switches")).child( - h_flex().items_center() - .gap_6() - .child(Switch::new("switch3").checked(self.switch3).label("Small Size").small().on_click(cx.listener(move |view, checked, cx| { - view.switch3 = *checked; - cx.notify(); - })), - ) + card(cx) + .v_flex() + .items_start() + .child(title("Small Switches")) + .child( + h_flex().items_center().gap_6().child( + Switch::new("switch3") + .checked(self.switch3) + .label("Small Size") + .small() + .on_click(cx.listener(move |view, checked, cx| { + view.switch3 = *checked; + cx.notify(); + })), + ), + ), + ) + .child( + section("Checkbox", cx).child( + h_flex() + .w_full() + .items_start() + .gap_6() + .child(Checkbox::new("check1").checked(self.check1).on_click( + cx.listener(|v, _, _| { + v.check1 = !v.check1; + }), + )) + .child( + Checkbox::new("check2") + .checked(self.check2) + .label("Subscribe to newsletter") + .on_click(cx.listener(|v, _, _| { + v.check2 = !v.check2; + })), + ) + .child( + Checkbox::new("check3") + .checked(self.check3) + .label("Remember me") + .on_click(cx.listener(|v, _, _| { + v.check3 = !v.check3; + })), + ) + .child(div().w(px(300.)).child( + Checkbox::new("longlong-checkbox").label( + "The long long label text, \ + it should ellipsis when the text is too long.", + ), + )), + ), + ) + .child( + section("Disabled Checkbox", cx).child( + h_flex() + .w_full() + .items_center() + .gap_6() + .child( + Checkbox::new("check3") + .label("Disabled Checked") + .checked(true) + .disabled(true), + ) + .child( + Checkbox::new("check3_1") + .label("Disabled Unchecked") + .checked(false) + .disabled(true), + ), + ), + ) + .child( + section("Radio", cx).child( + h_flex() + .w_full() + .gap_4() + .items_start() + .child(Radio::new("radio1").checked(self.radio_check1).on_click( + cx.listener(|this, v, _cx| { + this.radio_check1 = *v; + }), + )) + .child( + Radio::new("radio2") + .label("Radio") + .checked(self.radio_check2) + .on_click(cx.listener(|this, v, _cx| { + this.radio_check2 = *v; + })), + ) + .child( + Radio::new("radio3") + .label("Disabled Radio") + .checked(true) + .disabled(true), + ) + .child( + div().w(px(200.)).child( + Radio::new("radio3") + .label("A long long long text radio label") + .checked(true) + .disabled(true), + ), + ), + ), ), - ) ) } } diff --git a/crates/story/src/text_story.rs b/crates/story/src/text_story.rs index 295e2042..85fd14f7 100644 --- a/crates/story/src/text_story.rs +++ b/crates/story/src/text_story.rs @@ -5,25 +5,18 @@ use gpui::{ use ui::{ button::{Button, ButtonVariant, ButtonVariants as _}, - checkbox::Checkbox, clipboard::Clipboard, h_flex, label::Label, link::Link, - radio::Radio, tag::Tag, - v_flex, Disableable as _, IconName, Sizable, StyledExt, + v_flex, IconName, Sizable, StyledExt, }; use crate::section; pub struct TextStory { focus_handle: gpui::FocusHandle, - check1: bool, - check2: bool, - check3: bool, - radio_check1: bool, - radio_check2: bool, masked: bool, } @@ -45,11 +38,6 @@ impl TextStory { pub(crate) fn new(cx: &mut WindowContext) -> Self { Self { focus_handle: cx.focus_handle(), - check1: false, - check2: false, - check3: true, - radio_check1: false, - radio_check2: true, masked: false, } } @@ -84,30 +72,66 @@ impl Render for TextStory { .child(Label::new("Text align right").text_right()), ) .child(Label::new("Color Label").text_color(ui::red_500())) - .child( - Label::new("Font Size Label") - .text_size(px(20.)) - .font_semibold() - .line_height(rems(1.8)), - ) + .child(Label::new("Font Size Label").text_size(px(20.)).font_semibold().line_height(rems(1.8))) .child( div().w(px(200.)).child( Label::new("Label should support text wrap in default, if the text is too long, it should wrap to the next line.") .line_height(rems(1.8)), ), - ) - + ), ) .child( - section("Link", cx).child( - h_flex().items_start().gap_3() - .child(Link::new("link1").href("https://github.com").child("GitHub")) - .child(Link::new("link2").href("https://github.com").text_color(ui::red_500()).text_decoration_color(ui::red_500()).child("Red Link")) - .child(Link::new("link3").child(h_flex().gap_1().child(IconName::GitHub).child("GitHub")).on_click(cx.listener(|_, _, cx| { - cx.open_url("https://google.com") - }))) - .child(div().w(px(250.)).child(Link::new("link4").child("https://github.com/longbridge/gpui-component").href("https://github.com/longbridge/gpui-component"))) - ) + h_flex() + .gap_3() + .child( + section("Link", cx).child( + h_flex() + .items_start() + .gap_3() + .child(Link::new("link1").href("https://github.com").child("GitHub")) + .child( + Link::new("link2") + .href("https://github.com") + .text_color(ui::red_500()) + .text_decoration_color(ui::red_500()) + .child("Red Link"), + ) + .child( + Link::new("link3") + .child(h_flex().gap_1().child(IconName::GitHub).child("GitHub")) + .on_click(cx.listener(|_, _, cx| cx.open_url("https://google.com"))), + ) + .child( + div().w(px(250.)).child( + Link::new("link4") + .child("https://github.com/longbridge/gpui-component") + .href("https://github.com/longbridge/gpui-component"), + ), + ), + ), + ) + .child( + section("Clipboard", cx).child( + h_flex() + .w_full() + .gap_4() + .child( + Clipboard::new("clipboard1") + .content(|_| Label::new("Click icon to copy")) + .value_fn({ + let view = cx.view().clone(); + move |cx| SharedString::from(format!("masked :{}", view.read(cx).masked)) + }) + .on_copied(|value, _| println!("Copied value: {}", value)), + ) + .child( + Clipboard::new("clipboard2") + .content(|_| Link::new("link1").href("https://github.com").child("GitHub")) + .value("https://github.com") + .on_copied(|value, _| println!("Copied value: {}", value)), + ), + ), + ), ) .child( section("Maksed Label", cx).child( @@ -115,160 +139,38 @@ impl Render for TextStory { .w_full() .gap_4() .child( - h_flex() - .child(Label::new("9,182,1 USD").text_2xl().masked(self.masked)) - .child( - Button::new("btn-mask") - .with_variant(ButtonVariant::Ghost) - .icon(if self.masked { - IconName::EyeOff - } else { - IconName::Eye - }) - .on_click(cx.listener(|this, _, _| { - this.masked = !this.masked; - })), - ), + h_flex().child(Label::new("9,182,1 USD").text_2xl().masked(self.masked)).child( + Button::new("btn-mask") + .with_variant(ButtonVariant::Ghost) + .icon(if self.masked { IconName::EyeOff } else { IconName::Eye }) + .on_click(cx.listener(|this, _, _| { + this.masked = !this.masked; + })), + ), ) .child(Label::new("500 USD").text_xl().masked(self.masked)), ), ) - .child( - section("Checkbox", cx).child( - h_flex() - .w_full() - .items_start() - .gap_6() - .child( - Checkbox::new("check1") - .checked(self.check1) - .on_click(cx.listener(|v, _, _| { - v.check1 = !v.check1; - })), - ) - .child( - Checkbox::new("check2") - .checked(self.check2) - .label("Subscribe to newsletter") - .on_click(cx.listener(|v, _, _| { - v.check2 = !v.check2; - })), - ) - .child( - Checkbox::new("check3") - .checked(self.check3) - .label("Remember me") - .on_click(cx.listener(|v, _, _| { - v.check3 = !v.check3; - })), - ) - .child( - div().w(px(300.)).child( - Checkbox::new("longlong-checkbox") - .label("The long long label text, it should ellipsis when the text is too long.") - ), - ) - ), - ) - .child( - section("Disabled Checkbox", cx).child( - h_flex() - .w_full() - .items_center() - .gap_6() - .child( - Checkbox::new("check3") - .label("Disabled Checked") - .checked(true) - .disabled(true), - ) - .child( - Checkbox::new("check3_1") - .label("Disabled Unchecked") - .checked(false) - .disabled(true), - ) - ), - ) - .child( - section("Radio", cx).child( - h_flex() - .w_full() - .gap_4() - .items_start() - .child( - Radio::new("radio1") - .checked(self.radio_check1) - .on_click(cx.listener(|this, v, _cx| { - this.radio_check1 = *v; - })), - ) - .child( - Radio::new("radio2") - .label("Radio") - .checked(self.radio_check2) - .on_click(cx.listener(|this, v, _cx| { - this.radio_check2 = *v; - })), - ) - .child( - Radio::new("radio3") - .label("Disabled Radio") - .checked(true) - .disabled(true), - ) - .child( - div().w(px(200.)).child( - Radio::new("radio3") - .label("A long long long text radio label") - .checked(true) - .disabled(true), - ), - ) - ), - ) - .child( - section("Clipboard", cx).child( - h_flex() - .w_full() - .gap_4() - .child( - Clipboard::new("clipboard1") - .content(|_| Label::new("Click icon to copy")) - .value_fn({ - let view = cx.view().clone(); - move |cx| { - SharedString::from(format!("Check1 :{}", view.read(cx).check1)) - } - }) - .on_copied(|value, _| println!("Copied value: {}", value)), - ) - .child( - Clipboard::new("clipboard2") - .content(|_| Link::new("link1").href("https://github.com").child("GitHub")) - .value("https://github.com") - .on_copied(|value, _| println!("Copied value: {}", value)), - ) - ), - ) .child( section("Tag", cx) .child( - h_flex().gap_2() + h_flex() + .gap_2() .child(Tag::primary().small().child("Tag")) .child(Tag::secondary().small().child("Secondary")) .child(Tag::outline().small().child("Outline")) .child(Tag::danger().small().child("danger")) - .child(Tag::custom(ui::yellow_500(), ui::yellow_800(), ui::yellow_500()).small().child("Custom")) + .child(Tag::custom(ui::yellow_500(), ui::yellow_800(), ui::yellow_500()).small().child("Custom")), ) .child( - h_flex().gap_2() + h_flex() + .gap_2() .child(Tag::primary().child("Tag")) .child(Tag::secondary().child("Secondary")) .child(Tag::outline().child("Outline")) .child(Tag::danger().child("danger")) - .child(Tag::custom(ui::yellow_500(), ui::yellow_800(), ui::yellow_500()).child("Custom")) - ) + .child(Tag::custom(ui::yellow_500(), ui::yellow_800(), ui::yellow_500()).child("Custom")), + ), ) } }