code/kitchen-sink/plans/toast-2.md
Revamp @tamagui/toast to v2, inspired by Sonner's excellent UX. Must be fully cross-platform using Tamagui's animation system - NO CSS cheats.
Top position toasts outside frame ✅ FIXED
bottom: 0 to dynamic {...(isTop ? { top: 0 } : { bottom: 0 })}Action buttons overlapping ✅ FIXED
Hover stack → leave → rest fly away, one stays ✅ FIXED
lastPauseTimeRef guard (Sonner pattern) - only calculate elapsed time if timer was started after last pauseExit animations fly too far ✅ FIXED
Focus outline shows on click ✅ FIXED
focusStyle to focusVisibleStyleExpanded state showed ALL toasts ✅ FIXED
pointerEvents: 'none' for hidden toasts1 - (index * 0.05)visibleToasts - index (front highest)scale = 1 - (index * 0.05)
// index 0: 1.0, index 1: 0.95, index 2: 0.90
// For bottom position
stackY = isFront ? 0 : -peekAmount * index
// For top position
stackY = isFront ? 0 : peekAmount * index
offset = (heightIndex * gap) + toastsHeightBefore
// For bottom: -offset
// For top: +offset
function resisted(delta: number, maxResist = 25): number {
if (delta >= 0) return delta
const pastBoundary = Math.abs(delta)
const resistedDistance = Math.sqrt(pastBoundary) * 2
return -Math.min(resistedDistance, maxResist)
}
VELOCITY_THRESHOLD = 0.11 // px/ms
shouldDismiss = passedThreshold || velocity > VELOCITY_THRESHOLD
// Invisible hit area above/below toast when expanded
const gapFillerHeight = expanded ? gap + 1 : 0
<View
position="absolute"
left={0}
right={0}
height={gapFillerHeight}
pointerEvents="auto"
{...(isTop ? { top: '100%' } : { bottom: '100%' })}
/>
// Fade out toasts as they approach visibility limit
let computedOpacity = 1
if (!expanded) {
if (index >= visibleToasts) {
computedOpacity = 0 // completely hidden beyond limit
} else if (index === visibleToasts - 1) {
computedOpacity = 0.5 // last visible toast fades
}
}
/code/ui/toast/src/Toaster.tsx
/code/ui/toast/src/ToastItem.tsx
/code/ui/toast/src/useDragGesture.ts
/code/kitchen-sink/tests/ToastMultiple.test.tsx
/code/kitchen-sink/tests/ToastHover.test.tsx - NEW
/code/kitchen-sink/tests/ToastVisual.test.tsx - NEW
/code/kitchen-sink/tests/ToastInterrupt.test.tsx - NEW
Total: 25 tests passing
All tests pass with CSS animation driver.