Wait https://github.com/zed-industries/zed/pull/33008, https://github.com/zed-industries/zed/pull/34804 to merge. https://github.com/user-attachments/assets/3c21ebc9-44a0-4311-bb0f-5f63fe8d4bb3 - Improved `focus_ring` to render like an outline. - Added to support press `Enter`, `Space` key to trigger Checkbox, Button, Radio. ## Break Changes - The `FocusableExt` has been changed to only for crate internal. - The `FocusableCycle` has been removed, now GPUI has it own tab stop implementation.
240 lines
8.8 KiB
Rust
240 lines
8.8 KiB
Rust
use gpui::{
|
|
App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,
|
|
Styled, Window,
|
|
};
|
|
use gpui_component::{
|
|
alert::Alert,
|
|
button::{Button, ButtonGroup},
|
|
dock::PanelControl,
|
|
text::TextView,
|
|
v_flex, IconName, Selectable as _, Sizable as _, Size,
|
|
};
|
|
|
|
use crate::section;
|
|
|
|
pub struct AlertStory {
|
|
size: Size,
|
|
banner_visible: bool,
|
|
focus_handle: gpui::FocusHandle,
|
|
}
|
|
|
|
impl AlertStory {
|
|
fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
|
|
Self {
|
|
size: Size::default(),
|
|
banner_visible: true,
|
|
focus_handle: cx.focus_handle(),
|
|
}
|
|
}
|
|
|
|
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
|
cx.new(|cx| Self::new(window, cx))
|
|
}
|
|
|
|
fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Self>) {
|
|
self.size = size;
|
|
cx.notify();
|
|
}
|
|
}
|
|
|
|
impl super::Story for AlertStory {
|
|
fn title() -> &'static str {
|
|
"Alert"
|
|
}
|
|
|
|
fn description() -> &'static str {
|
|
"Displays a callout for user attention."
|
|
}
|
|
|
|
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
|
|
Self::view(window, cx)
|
|
}
|
|
|
|
fn zoomable() -> Option<PanelControl> {
|
|
None
|
|
}
|
|
}
|
|
|
|
impl Focusable for AlertStory {
|
|
fn focus_handle(&self, _: &App) -> FocusHandle {
|
|
self.focus_handle.clone()
|
|
}
|
|
}
|
|
|
|
impl Render for AlertStory {
|
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
|
v_flex()
|
|
.gap_4()
|
|
.child(
|
|
ButtonGroup::new("toggle-size")
|
|
.outline()
|
|
.compact()
|
|
.child(
|
|
Button::new("xsmall")
|
|
.label("XSmall")
|
|
.selected(self.size == Size::XSmall),
|
|
)
|
|
.child(
|
|
Button::new("small")
|
|
.label("Small")
|
|
.selected(self.size == Size::Small),
|
|
)
|
|
.child(
|
|
Button::new("medium")
|
|
.label("Medium")
|
|
.selected(self.size == Size::Medium),
|
|
)
|
|
.child(
|
|
Button::new("large")
|
|
.label("Large")
|
|
.selected(self.size == Size::Large),
|
|
)
|
|
.on_click(cx.listener(|this, selecteds: &Vec<usize>, window, cx| {
|
|
let size = match selecteds[0] {
|
|
0 => Size::XSmall,
|
|
1 => Size::Small,
|
|
2 => Size::Medium,
|
|
3 => Size::Large,
|
|
_ => unreachable!(),
|
|
};
|
|
this.set_size(size, window, cx);
|
|
})),
|
|
)
|
|
.child(
|
|
section("Default").w_2_3().child(
|
|
Alert::new(
|
|
"alert-default",
|
|
TextView::markdown(
|
|
"md",
|
|
"This is an alert with icon, title and description (in Markdown).\n\
|
|
- This is a **list** item.\n\
|
|
- This is another list item.",
|
|
window,
|
|
cx,
|
|
),
|
|
)
|
|
.with_size(self.size)
|
|
.title("Success! Your changes have been saved"),
|
|
),
|
|
)
|
|
.child(
|
|
section("With variant").w_2_3().child(
|
|
v_flex()
|
|
.w_full()
|
|
.gap_3()
|
|
.child(
|
|
Alert::info("info1", "This is an info alert.")
|
|
.with_size(self.size)
|
|
.title("Info message")
|
|
.on_close(cx.listener(|_, _, _, _| {
|
|
println!("Info alert closed");
|
|
})),
|
|
)
|
|
.child(
|
|
Alert::success(
|
|
"success-1",
|
|
"You have successfully submitted your form.\n\
|
|
Thank you for your submission!",
|
|
)
|
|
.with_size(self.size)
|
|
.title("Submit Successful"),
|
|
)
|
|
.child(
|
|
Alert::warning(
|
|
"warning-1",
|
|
"This is a warning alert with icon, but no title.\n\
|
|
This is second line of text to test is the line-height is correct.",
|
|
)
|
|
.with_size(self.size),
|
|
)
|
|
.child(
|
|
Alert::error(
|
|
"error-1",
|
|
TextView::markdown(
|
|
"error-message",
|
|
"Please verify your billing information and try again.\n\
|
|
- Check your card details\n\
|
|
- Ensure sufficient funds\n\
|
|
- Verify billing address",
|
|
window,
|
|
cx,
|
|
),
|
|
)
|
|
.with_size(self.size)
|
|
.title("Unable to process your payment."),
|
|
),
|
|
),
|
|
)
|
|
.child(
|
|
section("Banner").w_2_3().child(
|
|
v_flex()
|
|
.w_full()
|
|
.gap_2()
|
|
.child(
|
|
Alert::new(
|
|
"banner-1",
|
|
"This is a banner alert, it will take \
|
|
the full width of the container.",
|
|
)
|
|
.banner()
|
|
.on_close(cx.listener(|this, _, _, cx| {
|
|
this.banner_visible = !this.banner_visible;
|
|
cx.notify();
|
|
}))
|
|
.visible(self.banner_visible)
|
|
.with_size(self.size),
|
|
)
|
|
.child(
|
|
Alert::info(
|
|
"banner-info",
|
|
"This is a banner alert, it will take the full width of the\
|
|
container.",
|
|
)
|
|
.banner()
|
|
.with_size(self.size),
|
|
)
|
|
.child(
|
|
Alert::success(
|
|
"banner-success",
|
|
"This is a banner alert, it will take the full width of the\
|
|
container.",
|
|
)
|
|
.banner()
|
|
.with_size(self.size),
|
|
)
|
|
.child(
|
|
Alert::warning(
|
|
"banner-warning",
|
|
"This is a banner alert, it will take the full width of the\
|
|
container.",
|
|
)
|
|
.banner()
|
|
.with_size(self.size),
|
|
)
|
|
.child(
|
|
Alert::error(
|
|
"banner-error",
|
|
"This is a banner alert, it will take the full width of the\
|
|
container.",
|
|
)
|
|
.banner()
|
|
.with_size(self.size),
|
|
),
|
|
),
|
|
)
|
|
.child(
|
|
section("Custom Icon").w_2_3().child(
|
|
Alert::new(
|
|
"other-1",
|
|
"Custom icon with info alert with long \
|
|
long long long long long long long long \
|
|
long long long long long long long long long \
|
|
long long messageeeeeeeee.",
|
|
)
|
|
.title("Custom Icon")
|
|
.with_size(self.size)
|
|
.icon(IconName::Calendar),
|
|
),
|
|
)
|
|
}
|
|
}
|