gpui-component/crates/story/src/button_story.rs

769 lines
35 KiB
Rust

use gpui::{
actions, prelude::FluentBuilder, px, App, AppContext as _, ClickEvent, Context, Entity,
Focusable, InteractiveElement, IntoElement, ParentElement as _, Render, Styled as _, Window,
};
use gpui_component::{
button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton},
checkbox::Checkbox,
green_600, green_700, green_800, green_950, h_flex, v_flex, white, ActiveTheme,
Disableable as _, Icon, IconName, Selectable as _, Sizable as _, Theme,
};
use crate::section;
actions!(button_story, [Disabled, Loading, Selected, Compact]);
pub struct ButtonStory {
focus_handle: gpui::FocusHandle,
disabled: bool,
loading: bool,
selected: bool,
compact: bool,
toggle_multiple: bool,
}
impl ButtonStory {
pub fn view(_: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self {
focus_handle: cx.focus_handle(),
disabled: false,
loading: false,
selected: false,
compact: false,
toggle_multiple: false,
})
}
fn on_click(ev: &ClickEvent, _window: &mut Window, _cx: &mut App) {
println!("Button clicked! {:?}", ev);
}
}
impl super::Story for ButtonStory {
fn title() -> &'static str {
"Button"
}
fn description() -> &'static str {
"Displays a button or a component that looks like a button."
}
fn closable() -> bool {
false
}
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
Self::view(window, cx)
}
}
impl Focusable for ButtonStory {
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for ButtonStory {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let disabled = self.disabled;
let loading = self.loading;
let selected = self.selected;
let compact = self.compact;
let toggle_multiple = self.toggle_multiple;
let custom_variant = ButtonCustomVariant::new(cx)
.color(if cx.theme().mode.is_dark() {
green_800()
} else {
green_600()
})
.foreground(if cx.theme().mode.is_dark() {
white()
} else {
white()
})
.border(if cx.theme().mode.is_dark() {
green_800()
} else {
green_700()
})
.hover(if cx.theme().mode.is_dark() {
green_800()
} else {
green_600()
})
.active(if cx.theme().mode.is_dark() {
green_950()
} else {
green_700()
});
v_flex()
.on_action(cx.listener(|this, _: &Disabled, _, _| this.disabled = !this.disabled))
.on_action(cx.listener(|this, _: &Loading, _, _| this.loading = !this.loading))
.on_action(cx.listener(|this, _: &Selected, _, _| this.selected = !this.selected))
.on_action(cx.listener(|this, _: &Compact, _, _| this.compact = !this.compact))
.gap_6()
.child(
h_flex()
.gap_3()
.child("State")
.child(
Checkbox::new("disabled-button")
.label("Disabled")
.checked(self.disabled)
.on_click(cx.listener(|view, _, _, cx| {
view.disabled = !view.disabled;
cx.notify();
})),
)
.child(
Checkbox::new("loading-button")
.label("Loading")
.checked(self.loading)
.on_click(cx.listener(|view, _, _, cx| {
view.loading = !view.loading;
cx.notify();
})),
)
.child(
Checkbox::new("selected-button")
.label("Selected")
.checked(self.selected)
.on_click(cx.listener(|view, _, _, cx| {
view.selected = !view.selected;
cx.notify();
})),
)
.child(
Checkbox::new("compact-button")
.label("Compact")
.checked(self.compact)
.on_click(cx.listener(|view, _, _, cx| {
view.compact = !view.compact;
cx.notify();
})),
)
.child(
Checkbox::new("shadow-button")
.label("Shadow")
.checked(cx.theme().shadow)
.on_click(cx.listener(|_, _, window, cx| {
let mut theme = cx.theme().clone();
theme.shadow = !theme.shadow;
cx.set_global::<Theme>(theme);
window.refresh();
})),
),
)
.child(
h_flex()
.gap_6()
.child(
section("Normal Button", cx)
.child(
Button::new("button-1")
.primary()
.label("Primary Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-2")
.label("Secondary Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-4")
.danger()
.label("Danger Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-5-ghost")
.ghost()
.label("Ghost Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-5-link")
.link()
.label("Link Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-5-text")
.text()
.label("Text Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-6-custom")
.custom(custom_variant)
.label("Custom Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
)
.child(
section("Button with Icon", cx)
.child(
Button::new("button-icon-1")
.primary()
.label("Confirm")
.icon(IconName::Check)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-2")
.label("Abort")
.icon(IconName::Close)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-3")
.label("Maximize")
.icon(Icon::new(IconName::Maximize))
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-4")
.primary()
.child(
h_flex()
.items_center()
.gap_2()
.child("Custom Child")
.child(IconName::ChevronDown)
.child(IconName::Eye),
)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-5-ghost")
.ghost()
.icon(IconName::Check)
.label("Confirm")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-6-link")
.link()
.icon(IconName::Check)
.label("Link")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-icon-6-text")
.text()
.icon(IconName::Check)
.label("Text Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
),
)
.child(
h_flex().gap_6().child(
section("Outline Button", cx)
.child(
Button::new("button-outline-1")
.primary()
.outline()
.label("Primary Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-2")
.outline()
.label("Secondary Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-4")
.danger()
.outline()
.label("Danger Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-6-custom")
.outline()
.custom(custom_variant)
.label("Custom Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-5-ghost")
.ghost()
.outline()
.label("Ghost Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-5-link")
.link()
.outline()
.label("Link Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-outline-5-text")
.text()
.outline()
.label("Text Button")
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
),
)
.child(
h_flex()
.gap_6()
.child(
section("Small Size", cx)
.child(
Button::new("button-6")
.label("Primary Button")
.icon(IconName::Check)
.primary()
.small()
.loading(true)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-7")
.label("Secondary Button")
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-8")
.label("Danger Button")
.danger()
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-8-outline")
.label("Outline Button")
.outline()
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-8-ghost")
.label("Ghost Button")
.ghost()
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-8-link")
.label("Link Button")
.link()
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
)
.child(
section("XSmall Size", cx)
.child(
Button::new("button-xs-1")
.label("Primary Button")
.primary()
.icon(IconName::Check)
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-xs-2")
.label("Secondary Button")
.xsmall()
.loading(true)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-xs-3")
.label("Danger Button")
.danger()
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-xs-3-ghost")
.label("Ghost Button")
.ghost()
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-xs-3-outline")
.label("Outline Button")
.outline()
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-xs-3-link")
.label("Link Button")
.link()
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
),
)
.child(
section("Button Group", cx)
.child(
ButtonGroup::new("button-group")
.small()
.disabled(disabled)
.child(
Button::new("button-one")
.label("One")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-two")
.label("Two")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
)
.child(
Button::new("button-three")
.label("Three")
.disabled(disabled)
.selected(selected)
.when(compact, |this| this.compact())
.on_click(Self::on_click),
),
)
.child(
h_flex()
.gap_2()
.child(
Checkbox::new("multiple-button")
.label("Multiple")
.checked(toggle_multiple)
.on_click(cx.listener(|view, _, _, cx| {
view.toggle_multiple = !view.toggle_multiple;
cx.notify();
})),
)
.child(
ButtonGroup::new("toggle-button-group")
.primary()
.compact()
.multiple(toggle_multiple)
.child(
Button::new("disabled-toggle-button")
.label("Disabled")
.selected(disabled),
)
.child(
Button::new("loading-toggle-button")
.label("Loading")
.selected(loading),
)
.child(
Button::new("selected-toggle-button")
.label("Selected")
.selected(selected),
)
.child(
Button::new("compact-toggle-button")
.label("Compact")
.selected(compact),
)
.on_click(cx.listener(|view, selected: &Vec<usize>, _, cx| {
view.disabled = selected.contains(&0);
view.loading = selected.contains(&1);
view.selected = selected.contains(&2);
view.compact = selected.contains(&3);
cx.notify();
})),
),
),
)
.child(
section("Dropdown Button", cx)
.child(
DropdownButton::new("dropdown-button1")
.small()
.button(Button::new("dropdown-button-button1").label("Click Me"))
.popup_menu(move |this, _, _| {
this.menu("Disabled", Box::new(Disabled))
.menu("Loading", Box::new(Loading))
.menu("Selected", Box::new(Selected))
.menu("Compact", Box::new(Compact))
}),
)
.child(
DropdownButton::new("dropdown-button")
.button(Button::new("dropdown-button-button").label("Click Me"))
.popup_menu(move |this, _, _| {
this.menu("Disabled", Box::new(Disabled))
.menu("Loading", Box::new(Loading))
.menu("Selected", Box::new(Selected))
.menu("Compact", Box::new(Compact))
}),
),
)
.child(
section("Icon Button", cx)
.child(
Button::new("icon-button-primary")
.icon(IconName::Search)
.loading_icon(IconName::LoaderCircle)
.primary()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-secondary")
.icon(IconName::Info)
.loading(true)
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-danger")
.icon(IconName::Close)
.danger()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-small-primary")
.icon(IconName::Search)
.small()
.primary()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-outline")
.icon(IconName::Search)
.outline()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-ghost")
.icon(IconName::ArrowLeft)
.loading_icon(IconName::LoaderCircle)
.ghost()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
),
)
.child(
section("Icon Button", cx)
.child(
Button::new("icon-button-4")
.icon(IconName::Info)
.small()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-5")
.icon(IconName::Close)
.small()
.danger()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-6")
.icon(IconName::Search)
.small()
.primary()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-7")
.icon(IconName::Info)
.xsmall()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-8")
.icon(IconName::Close)
.xsmall()
.danger()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
)
.child(
Button::new("icon-button-9")
.icon(IconName::Heart)
.size(px(24.))
.ghost()
.disabled(disabled)
.selected(selected)
.loading(loading)
.when(compact, |this| this.compact()),
),
)
}
}