History

Prevent toast content overflow in collapsed stack

- Use the larger of shared stack height and per-toast height to avoid clipping - Make toast content columns flexible with `min-w-0` and `break-words` - Keep action buttons from shrinking so long text wraps instead of overflowing

Julius Marminge committed 8 months ago

Commit 95fcc891 parent eb598531 file · +23 −11Browse files

Unified · Split

apps/web/src/components/ui/toast.tsx+23−11
@@ -206,7 +206,10 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) { · 205 unmodified lines
206206 "data-[position*=top]:after:top-full",
207207 "data-[position*=bottom]:after:bottom-full",
208208 // Define some variables
209− "[--toast-calc-height:var(--toast-frontmost-height,var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]",
209+ // Base UI exposes a shared front-most height for the collapsed stack.
210+ // If that shared measurement is briefly stale, long content can render
211+ // outside the card until hover expands the toast and swaps to its own height.
212+ "[--toast-calc-height:max(var(--toast-frontmost-height,var(--toast-height)),var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]",
210213 // Define offset-y variable
211214 "data-[position*=top]:[--toast-calc-offset-y:calc(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap)+var(--toast-swipe-movement-y))]",
212215 "data-[position*=bottom]:[--toast-calc-offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--toast-gap)*-1+var(--toast-swipe-movement-y))]",
@@ -258,7 +261,7 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) { · 45 unmodified lines
258261 "not-data-expanded:pointer-events-none not-data-expanded:opacity-0",
259262 )}
260263 >
261− <div className="flex gap-2">
264+ <div className="flex min-w-0 flex-1 gap-2">
262265 {Icon && (
263266 <div
264267 className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
@@ -268,16 +271,22 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) { · 3 unmodified lines
268271 </div>
269272 )}
270273
271− <div className="flex flex-col gap-0.5">
272− <Toast.Title className="font-medium" data-slot="toast-title" />
274+ <div className="flex min-w-0 flex-1 flex-col gap-0.5">
275+ <Toast.Title
276+ className="min-w-0 break-words font-medium"
277+ data-slot="toast-title"
278+ />
273279 <Toast.Description
274− className="text-muted-foreground"
280+ className="min-w-0 break-words text-muted-foreground"
275281 data-slot="toast-description"
276282 />
277283 </div>
278284 </div>
279285 {toast.actionProps && (
280− <Toast.Action className={buttonVariants({ size: "xs" })} data-slot="toast-action">
286+ <Toast.Action
287+ className={cn(buttonVariants({ size: "xs" }), "shrink-0")}
288+ data-slot="toast-action"
289+ >
281290 {toast.actionProps.children}
282291 </Toast.Action>
283292 )}
@@ -341,7 +350,7 @@ function AnchoredToasts() { · 57 unmodified lines
341350 </Toast.Content>
342351 ) : (
343352 <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm">
344− <div className="flex gap-2">
353+ <div className="flex min-w-0 flex-1 gap-2">
345354 {Icon && (
346355 <div
347356 className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
@@ -351,17 +360,20 @@ function AnchoredToasts() { · 3 unmodified lines
351360 </div>
352361 )}
353362
354− <div className="flex flex-col gap-0.5">
355− <Toast.Title className="font-medium" data-slot="toast-title" />
363+ <div className="flex min-w-0 flex-1 flex-col gap-0.5">
364+ <Toast.Title
365+ className="min-w-0 break-words font-medium"
366+ data-slot="toast-title"
367+ />
356368 <Toast.Description
357− className="text-muted-foreground"
369+ className="min-w-0 break-words text-muted-foreground"
358370 data-slot="toast-description"
359371 />
360372 </div>
361373 </div>
362374 {toast.actionProps && (
363375 <Toast.Action
364− className={buttonVariants({ size: "xs" })}
376+ className={cn(buttonVariants({ size: "xs" }), "shrink-0")}
365377 data-slot="toast-action"
366378 >
367379 {toast.actionProps.children}