Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/web/src/components/WebSocketConnectionSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,9 @@ export function SlowRpcAckToastCoordinator() {
timeout: 0,
title: "Some requests are slow",
type: "warning" as const,
data: {
showCloseButton: true,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close button leaves stale ref, preventing toast re-show

Medium Severity

When the user clicks the close button, toastManager.close(toast.id) dismisses the toast, but toastIdRef.current in SlowRpcAckToastCoordinator is never cleared. On subsequent slowRequests changes, the coordinator takes the toastManager.update(toastIdRef.current, ...) branch, which silently no-ops on a closed toast. The slow-request warning never reappears until requests drop to zero and rise again — effectively suppressing the notification permanently after one dismissal.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 17d9bd1. Configure here.

};

if (toastIdRef.current) {
Expand Down
36 changes: 35 additions & 1 deletion apps/web/src/components/ui/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
InfoIcon,
LoaderCircleIcon,
TriangleAlertIcon,
XIcon,
} from "lucide-react";

import { cn } from "~/lib/utils";
Expand All @@ -31,6 +32,7 @@ export type ThreadToastData = {
tooltipStyle?: boolean;
dismissAfterVisibleMs?: number;
hideCopyButton?: boolean;
showCloseButton?: boolean;
};

const toastManager = Toast.createToastManager<ThreadToastData>();
Expand Down Expand Up @@ -302,9 +304,23 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) {
dismissAfterVisibleMs={toast.data?.dismissAfterVisibleMs}
toastId={toast.id}
/>
{toast.data?.showCloseButton ? (
<button
aria-label="Dismiss notification"
className={cn(
buttonVariants({ size: "icon-xs", variant: "ghost" }),
"absolute top-2 right-2 z-10 size-5 rounded-sm p-0 text-muted-foreground hover:text-foreground",
)}
onClick={() => toastManager.close(toast.id)}
type="button"
>
<XIcon className="size-3" />
</button>
) : null}
<Toast.Content
className={cn(
"pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm transition-opacity duration-250 data-expanded:opacity-100",
toast.data?.showCloseButton ? "pr-8" : null,
hideCollapsedContent &&
"not-data-expanded:pointer-events-none not-data-expanded:opacity-0",
)}
Expand Down Expand Up @@ -397,12 +413,30 @@ function AnchoredToasts() {
data-slot="toast-popup"
toast={toast}
>
{toast.data?.showCloseButton ? (
<button
aria-label="Dismiss notification"
className={cn(
buttonVariants({ size: "icon-xs", variant: "ghost" }),
"absolute top-2 right-2 z-10 size-5 rounded-sm p-0 text-muted-foreground hover:text-foreground",
)}
onClick={() => anchoredToastManager.close(toast.id)}
type="button"
>
<XIcon className="size-3" />
</button>
) : null}
{tooltipStyle ? (
<Toast.Content className="pointer-events-auto px-2 py-1">
<Toast.Title data-slot="toast-title" />
</Toast.Content>
Comment on lines 429 to 432
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low ui/toast.tsx:429

When tooltipStyle and showCloseButton are both true, the close button overlaps Toast.Title because the tooltip branch lacks the pr-8 padding present in the non-tooltip branch. Add right padding to the tooltip Toast.Content when showCloseButton is enabled.

                  {tooltipStyle ? (
-                    <Toast.Content className="pointer-events-auto px-2 py-1">
+                    <Toast.Content
+                      className={cn(
+                        "pointer-events-auto px-2 py-1",
+                        toast.data?.showCloseButton ? "pr-8" : null,
+                      )}
+                    >
                       <Toast.Title data-slot="toast-title" />
                     </Toast.Content>
                   ) : (
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/components/ui/toast.tsx around lines 429-432:

When `tooltipStyle` and `showCloseButton` are both `true`, the close button overlaps `Toast.Title` because the tooltip branch lacks the `pr-8` padding present in the non-tooltip branch. Add right padding to the tooltip `Toast.Content` when `showCloseButton` is enabled.

Evidence trail:
apps/web/src/components/ui/toast.tsx lines 417-437 at REVIEWED_COMMIT:
- Lines 417-427: Close button rendered when `toast.data?.showCloseButton` is true, positioned `absolute top-2 right-2 z-10`
- Lines 429-431: Tooltip branch has `className="pointer-events-auto px-2 py-1"` with no conditional padding for close button
- Lines 432-437: Non-tooltip branch has `toast.data?.showCloseButton ? "pr-8" : null` conditional padding

) : (
<Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm">
<Toast.Content
className={cn(
"pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm",
toast.data?.showCloseButton ? "pr-8" : null,
)}
>
<div className="flex min-w-0 flex-1 gap-2">
{Icon && (
<div
Expand Down
Loading