story: Add Indicator, Skeleton story. (#1038)

This commit is contained in:
Jason Lee 2025-07-03 18:54:23 +08:00 committed by GitHub
parent d70d649a67
commit 6886ae746e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 220 additions and 81 deletions

View file

@ -0,0 +1,86 @@
use gpui::{
px, App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,
Window,
};
use gpui_component::{
blue_500, green_500, indicator::Indicator, sky_500, v_flex, IconName, Sizable,
};
use crate::section;
pub struct IndicatorStory {
focus_handle: gpui::FocusHandle,
value: f32,
}
impl super::Story for IndicatorStory {
fn title() -> &'static str {
"Indicator"
}
fn description() -> &'static str {
"Displays an indicator showing the completion progress of a task."
}
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
Self::view(window, cx)
}
}
impl IndicatorStory {
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self::new(window, cx))
}
fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
value: 50.,
}
}
pub fn set_value(&mut self, value: f32) {
self.value = value;
}
}
impl Focusable for IndicatorStory {
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for IndicatorStory {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
v_flex()
.items_center()
.gap_y_3()
.child(section("Indicator").gap_x_2().child(Indicator::new()))
.child(
section("Indicator with color")
.gap_x_2()
.child(Indicator::new().color(blue_500()))
.child(Indicator::new().color(green_500())),
)
.child(
section("Indicator with size")
.gap_x_2()
.child(Indicator::new().with_size(px(64.)))
.child(Indicator::new().large())
.child(Indicator::new())
.child(Indicator::new().small())
.child(Indicator::new().xsmall()),
)
.child(
section("Indicator with Icon")
.gap_x_2()
.child(Indicator::new().icon(IconName::LoaderCircle))
.child(
Indicator::new()
.icon(IconName::LoaderCircle)
.large()
.color(sky_500()),
),
)
}
}

View file

@ -16,6 +16,7 @@ mod dropdown_story;
mod form_story;
mod icon_story;
mod image_story;
mod indicator_story;
mod input_story;
mod kbd_story;
mod label_story;
@ -31,6 +32,7 @@ mod radio_story;
mod resizable_story;
mod scrollable_story;
mod sidebar_story;
mod skeleton_story;
mod slider_story;
mod switch_story;
mod table_story;
@ -69,6 +71,7 @@ pub use dropdown_story::DropdownStory;
pub use form_story::FormStory;
pub use icon_story::IconStory;
pub use image_story::ImageStory;
pub use indicator_story::IndicatorStory;
pub use input_story::InputStory;
pub use kbd_story::KbdStory;
pub use label_story::LabelStory;
@ -85,6 +88,7 @@ pub use resizable_story::ResizableStory;
pub use scrollable_story::ScrollableStory;
use serde::{Deserialize, Serialize};
pub use sidebar_story::SidebarStory;
pub use skeleton_story::SkeletonStory;
pub use slider_story::SliderStory;
pub use switch_story::SwitchStory;
pub use table_story::TableStory;

View file

@ -53,6 +53,7 @@ impl Gallery {
StoryContainer::panel::<DropdownStory>(window, cx),
StoryContainer::panel::<FormStory>(window, cx),
StoryContainer::panel::<IconStory>(window, cx),
StoryContainer::panel::<IndicatorStory>(window, cx),
StoryContainer::panel::<ImageStory>(window, cx),
StoryContainer::panel::<InputStory>(window, cx),
StoryContainer::panel::<KbdStory>(window, cx),
@ -69,6 +70,7 @@ impl Gallery {
StoryContainer::panel::<ResizableStory>(window, cx),
StoryContainer::panel::<ScrollableStory>(window, cx),
StoryContainer::panel::<SidebarStory>(window, cx),
StoryContainer::panel::<SkeletonStory>(window, cx),
StoryContainer::panel::<SliderStory>(window, cx),
StoryContainer::panel::<SwitchStory>(window, cx),
StoryContainer::panel::<TableStory>(window, cx),

View file

@ -1,11 +1,7 @@
use gpui::{
px, App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,
Window,
};
use gpui_component::{
blue_500, button::Button, h_flex, indicator::Indicator, progress::Progress, skeleton::Skeleton,
v_flex, IconName, Sizable,
App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled, Window,
};
use gpui_component::{button::Button, h_flex, progress::Progress, v_flex, IconName, Sizable};
use crate::section;
@ -53,83 +49,53 @@ impl Focusable for ProgressStory {
impl Render for ProgressStory {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.items_center()
.gap_y_3()
.child(
section("Progress Bar").max_w_md().child(
v_flex()
.w_full()
.gap_3()
.justify_center()
.items_center()
.child(
h_flex()
.gap_2()
.child(Button::new("button-1").small().label("0%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(0.);
}),
))
.child(Button::new("button-2").small().label("25%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(25.);
}),
))
.child(Button::new("button-3").small().label("75%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(75.);
}),
))
.child(Button::new("button-4").small().label("100%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(100.);
}),
)),
)
.child(Progress::new().value(self.value))
.child(
h_flex()
.gap_x_2()
.child(Button::new("button-5").icon(IconName::Minus).on_click(
cx.listener(|this, _, _, _| {
this.set_value((this.value - 1.).max(0.));
}),
))
.child(Button::new("button-6").icon(IconName::Plus).on_click(
cx.listener(|this, _, _, _| {
this.set_value((this.value + 1.).min(100.));
}),
)),
),
),
)
.child(
section("Indicator")
.gap_x_2()
.child(Indicator::new().xsmall())
.child(Indicator::new().small())
.child(Indicator::new())
.child(Indicator::new().with_size(px(64.))),
)
.child(
section("Indicator with Icon").gap_x_2().child(
Indicator::new()
.with_size(px(64.))
.icon(IconName::LoaderCircle)
.color(blue_500()),
),
)
.child(
section("Skeleton")
.max_w_md()
.child(Skeleton::new().size_12().rounded_full())
v_flex().items_center().gap_y_3().child(
section("Progress Bar").max_w_md().child(
v_flex()
.w_full()
.gap_3()
.justify_center()
.items_center()
.child(
v_flex()
h_flex()
.gap_2()
.child(Skeleton::new().w(px(250.)).h_4())
.child(Skeleton::new().w(px(200.)).h_4()),
.child(Button::new("button-1").small().label("0%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(0.);
}),
))
.child(Button::new("button-2").small().label("25%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(25.);
}),
))
.child(Button::new("button-3").small().label("75%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(75.);
}),
))
.child(Button::new("button-4").small().label("100%").on_click(
cx.listener(|this, _, _, _| {
this.set_value(100.);
}),
)),
)
.child(Progress::new().value(self.value))
.child(
h_flex()
.gap_x_2()
.child(Button::new("button-5").icon(IconName::Minus).on_click(
cx.listener(|this, _, _, _| {
this.set_value((this.value - 1.).max(0.));
}),
))
.child(Button::new("button-6").icon(IconName::Plus).on_click(
cx.listener(|this, _, _, _| {
this.set_value((this.value + 1.).min(100.));
}),
)),
),
)
),
)
}
}

View file

@ -0,0 +1,81 @@
use gpui::{
px, App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,
Window,
};
use gpui_component::{skeleton::Skeleton, v_flex};
use crate::section;
pub struct SkeletonStory {
focus_handle: gpui::FocusHandle,
value: f32,
}
impl super::Story for SkeletonStory {
fn title() -> &'static str {
"Skeleton"
}
fn description() -> &'static str {
"Use to show a placeholder while content is loading."
}
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
Self::view(window, cx)
}
}
impl SkeletonStory {
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self::new(window, cx))
}
fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
value: 50.,
}
}
pub fn set_value(&mut self, value: f32) {
self.value = value;
}
}
impl Focusable for SkeletonStory {
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for SkeletonStory {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
v_flex()
.items_center()
.gap_y_3()
.child(
section("Skeleton")
.max_w_md()
.child(Skeleton::new().size_12().rounded_full())
.child(
v_flex()
.gap_2()
.child(Skeleton::new().w(px(250.)).h_4().rounded_md())
.child(Skeleton::new().w(px(200.)).h_4().rounded_md()),
),
)
.child(
section("Card").max_w_md().child(
v_flex()
.gap_2()
.child(Skeleton::new().w(px(250.)).h(px(125.)).rounded_md())
.child(
v_flex()
.gap_2()
.child(Skeleton::new().w(px(250.)).h_4().rounded_md())
.child(Skeleton::new().w(px(200.)).h_4().rounded_md()),
),
),
)
}
}