add toast and alert overlays to the shell

This commit is contained in:
2026-11-10 16:43:48 +07:00
parent 37d95d3c75
commit 4de0029b03
8 changed files with 190 additions and 56 deletions
+33 -51
View File
@@ -7,7 +7,7 @@ use gpui::{
SharedString, Styled as _, UniformListScrollHandle, WeakEntity, Window, WindowBounds,
WindowOptions, actions, div, list, px, size, uniform_list,
};
use gpui_native_core::alert::{Alert, AlertSeverity, Alerts, AlertsView};
use gpui_native_core::alert::{Alert, AlertSeverity};
use gpui_native_core::avatar::Avatar;
use gpui_native_core::badge::{Badge, BadgeVariant};
use gpui_native_core::button::{Button, ButtonVariant};
@@ -36,7 +36,7 @@ use gpui_native_core::slider::Slider;
use gpui_native_core::spinner::{Spinner, SpinnerVariant};
use gpui_native_core::status_dot::{StatusDot, StatusDotVariant};
use gpui_native_core::switch::Switch;
use gpui_native_core::toast::{Toast, ToastAction, Toasts, ToastsView};
use gpui_native_core::toast::{Toast, ToastAction};
use gpui_native_core::toggle::Toggle;
use gpui_native_core::tooltip::Tooltip;
use gpui_native_data::list::{List, ListItem};
@@ -217,8 +217,6 @@ fn gallery_commands() -> Vec<Command> {
struct Gallery {
layout_state: Entity<LayoutState>,
dock_state: Entity<DockState>,
alerts: Entity<Alerts>,
toasts: Entity<Toasts>,
palette: Option<Entity<CommandPaletteState>>,
palette_runs: Vec<SharedString>,
dialog_open: bool,
@@ -395,8 +393,6 @@ impl Gallery {
fn register_panels(
dock: &mut DockState,
layout_state: Entity<LayoutState>,
alerts: Entity<Alerts>,
toasts: Entity<Toasts>,
palette: Entity<CommandPaletteState>,
gallery: WeakEntity<Self>,
cx: &mut Context<DockState>,
@@ -513,20 +509,20 @@ impl Gallery {
.into()
}));
dock.register_panel(PanelDescriptor::new("alert", "Alert", {
let alerts = alerts.clone();
let layout_state = layout_state.clone();
move |_, cx| {
cx.new(|_| AlertDemo {
alerts: alerts.clone(),
layout_state: layout_state.clone(),
dismissed: false,
})
.into()
}
}));
dock.register_panel(PanelDescriptor::new("toast", "Toast", {
let toasts = toasts.clone();
let layout_state = layout_state.clone();
move |_, cx| {
cx.new(|_| ToastDemo {
toasts: toasts.clone(),
layout_state: layout_state.clone(),
})
.into()
}
@@ -649,8 +645,6 @@ impl Render for Gallery {
.child(dialog)
.child(alert_dialog)
.when_some(self.palette.clone(), |root, palette| root.child(palette))
.child(AlertsView::new("gallery-alerts", self.alerts.clone()))
.child(ToastsView::new("gallery-toasts", self.toasts.clone()))
}
}
@@ -2287,16 +2281,16 @@ impl Render for TabsDemo {
}
struct AlertDemo {
alerts: Entity<Alerts>,
layout_state: Entity<LayoutState>,
dismissed: bool,
}
impl Render for AlertDemo {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let view = cx.entity();
let alerts_info = self.alerts.clone();
let alerts_warning = self.alerts.clone();
let alerts_clear = self.alerts.clone();
let alerts_info = self.layout_state.clone();
let alerts_warning = self.layout_state.clone();
let alerts_clear = self.layout_state.clone();
let colors = cx.theme().colors;
ScrollArea::new("alert-demo").size_full().p_4().child(
@@ -2339,8 +2333,8 @@ impl Render for AlertDemo {
.label("Push info")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
alerts_info.update(cx, |alerts, cx| {
alerts.push(
alerts_info.update(cx, |state, cx| {
state.push_alert(
Alert::new("alert-demo-pushed-info")
.title("Backed up")
.message("Everything is in sync.")
@@ -2355,8 +2349,8 @@ impl Render for AlertDemo {
.label("Push warning")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
alerts_warning.update(cx, |alerts, cx| {
alerts.push(
alerts_warning.update(cx, |state, cx| {
state.push_alert(
Alert::new("alert-demo-pushed-warning")
.title("Storage almost full")
.message("1.2 GB remaining on this device.")
@@ -2371,7 +2365,7 @@ impl Render for AlertDemo {
.label("Clear all")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
alerts_clear.update(cx, |alerts, cx| alerts.clear(cx));
alerts_clear.update(cx, |state, cx| state.clear_alerts(cx));
}),
),
)),
@@ -2380,14 +2374,14 @@ impl Render for AlertDemo {
}
struct ToastDemo {
toasts: Entity<Toasts>,
layout_state: Entity<LayoutState>,
}
impl Render for ToastDemo {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let toasts_undo = self.toasts.clone();
let toasts_saved = self.toasts.clone();
let toasts_connection = self.toasts.clone();
let toasts_undo = self.layout_state.clone();
let toasts_saved = self.layout_state.clone();
let toasts_connection = self.layout_state.clone();
let colors = cx.theme().colors;
ScrollArea::new("toast-demo")
@@ -2404,8 +2398,8 @@ impl Render for ToastDemo {
.label("Deleted (with undo)")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
toasts_undo.update(cx, |toasts, cx| {
toasts.push(
toasts_undo.update(cx, |state, cx| {
state.push_toast(
Toast::new("Draft deleted").action(ToastAction::new(
"Undo",
|cx| {
@@ -2423,8 +2417,8 @@ impl Render for ToastDemo {
.label("Saved (with icon)")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
toasts_saved.update(cx, |toasts, cx| {
toasts.push(
toasts_saved.update(cx, |state, cx| {
state.push_toast(
Toast::new("Workspace saved").icon(IconRole::Check),
cx,
);
@@ -2436,8 +2430,8 @@ impl Render for ToastDemo {
.label("Connection lost (sticky)")
.variant(ButtonVariant::Secondary)
.on_click(move |_, _, cx| {
toasts_connection.update(cx, |toasts, cx| {
toasts.push(
toasts_connection.update(cx, |state, cx| {
state.push_toast(
Toast::new("Connection lost")
.icon(IconRole::Warning)
.duration(Duration::ZERO),
@@ -4025,24 +4019,14 @@ fn main() {
cx.refresh_windows();
})
.detach();
let toasts = cx.new(|_| Toasts::default());
let alerts = cx.new(|_| Alerts::default());
let gallery = cx.new(|cx| {
// Toast pushes and dismissals repaint the stack.
cx.observe(&toasts, |_, _, cx| cx.notify()).detach();
// Alert pushes and dismissals repaint it.
cx.observe(&alerts, |_, _, cx| cx.notify()).detach();
Gallery {
layout_state: layout_state.clone(),
dock_state: dock_state.clone(),
alerts: alerts.clone(),
toasts: toasts.clone(),
palette: None,
palette_runs: Vec::new(),
dialog_open: false,
alert_open: false,
sidebar_transparent: true,
}
let gallery = cx.new(|_| Gallery {
layout_state: layout_state.clone(),
dock_state: dock_state.clone(),
palette: None,
palette_runs: Vec::new(),
dialog_open: false,
alert_open: false,
sidebar_transparent: true,
});
let palette = cx.new(|cx| {
let matcher = |query: &str, commands: &[Command]| {
@@ -4076,8 +4060,6 @@ fn main() {
Gallery::register_panels(
dock,
layout_state.clone(),
alerts.clone(),
toasts.clone(),
palette.clone(),
gallery.downgrade(),
cx,