From 138e5be925516ac783951aff173969a1dbee3531 Mon Sep 17 00:00:00 2001 From: Oz Date: Sun, 3 May 2026 00:38:31 +0000 Subject: [PATCH] fix: keep workspace toast stack scrollable Co-Authored-By: Oz Co-Authored-By: Zach Lloyd --- app/src/view_components/dismissible_toast.rs | 33 +++++++++++++++++--- app/src/workspace/view.rs | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/src/view_components/dismissible_toast.rs b/app/src/view_components/dismissible_toast.rs index 9faba52c6..549da0777 100644 --- a/app/src/view_components/dismissible_toast.rs +++ b/app/src/view_components/dismissible_toast.rs @@ -11,14 +11,16 @@ use warpui::keymap::Keystroke; use warpui::r#async::Timer; use warpui::{ elements::{ - Border, ChildAnchor, ConstrainedBox, Container, CornerRadius, CrossAxisAlignment, - DispatchEventResult, EventHandler, Flex, Hoverable, Icon, MainAxisAlignment, MainAxisSize, + Border, ChildAnchor, ClippedScrollStateHandle, ClippedScrollable, ConstrainedBox, + Container, CornerRadius, CrossAxisAlignment, DispatchEventResult, EventHandler, + Fill as ElementFill, Flex, Hoverable, Icon, MainAxisAlignment, MainAxisSize, MouseStateHandle, OffsetPositioning, ParentElement, PositionedElementAnchor, - PositionedElementOffsetBounds, Radius, SavePosition, Shrinkable, Stack, + PositionedElementOffsetBounds, Radius, SavePosition, ScrollbarWidth, Shrinkable, Stack, }, fonts::Weight, r#async::SpawnedFutureHandle, ui_components::components::{Coords, UiComponent, UiComponentStyles}, + units::Pixels, AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext, }; use warpui::{Action, ViewHandle}; @@ -57,6 +59,7 @@ struct ToastData { /// be rendered according to the order they were generated. pub struct DismissibleToastStack { timeout: Duration, + scroll_state: ClippedScrollStateHandle, /// A vector of individual toasts. Manual dismissals dismiss the specific toast that was /// clicked, while timeouts pass the toast's UUID to the dismiss method. /// Since the user may close any arbitrary toast, we use a vector, and assign UUIDs to @@ -69,6 +72,7 @@ impl DismissibleToastStack { pub fn new(timeout: Duration) -> Self { Self { timeout, + scroll_state: Default::default(), toasts: Vec::new(), } } @@ -95,6 +99,7 @@ impl DismissibleToastStack { abort_handle: Some(abort_handle), uuid, }); + self.scroll_state.scroll_to(Pixels::zero()); ctx.notify(); } @@ -115,6 +120,7 @@ impl DismissibleToastStack { abort_handle: None, uuid: Uuid::new_v4(), }); + self.scroll_state.scroll_to(Pixels::zero()); ctx.notify(); } @@ -189,8 +195,27 @@ impl View for DismissibleToastStack { .finish(), ); } + if self.toasts.is_empty() { + return rendered_toasts.finish(); + } - rendered_toasts.finish() + let appearance = Appearance::as_ref(app); + let theme = appearance.theme(); + let scrollable_contents = Container::new(rendered_toasts.finish()) + .with_padding_top(4.) + .with_padding_right(4.) + .finish(); + + ClippedScrollable::vertical( + self.scroll_state.clone(), + scrollable_contents, + ScrollbarWidth::Auto, + theme.nonactive_ui_detail().into(), + theme.active_ui_detail().into(), + ElementFill::None, + ) + .with_overlayed_scrollbar() + .finish() } } diff --git a/app/src/workspace/view.rs b/app/src/workspace/view.rs index 3b2b93c56..fd9b49467 100644 --- a/app/src/workspace/view.rs +++ b/app/src/workspace/view.rs @@ -19053,7 +19053,7 @@ impl Workspace { OffsetPositioning::offset_from_save_position_element( TAB_CONTENT_POSITION_ID, vec2f(0., 16.), - PositionedElementOffsetBounds::WindowByPosition, + PositionedElementOffsetBounds::WindowBySize, PositionedElementAnchor::TopMiddle, ChildAnchor::TopMiddle, )