From 0c5fab46b4bea55149d297c4604aae32b98a1a92 Mon Sep 17 00:00:00 2001 From: Emil Kowalski <36730035+emilkowalski@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:59:04 +0100 Subject: [PATCH] feat: improve lift animation, better swiping UX (#507) --- src/index.tsx | 11 ++++++++++- src/styles.css | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index d0be94e..0e28e4c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -77,6 +77,7 @@ const Toast = (props: ToastProps) => { const [removed, setRemoved] = React.useState(false); const [swiping, setSwiping] = React.useState(false); const [swipeOut, setSwipeOut] = React.useState(false); + const [isSwiped, setIsSwiped] = React.useState(false); const [offsetBeforeRemove, setOffsetBeforeRemove] = React.useState(0); const [initialHeight, setInitialHeight] = React.useState(0); const remainingTime = React.useRef(toast.duration || durationFromToaster || TOAST_LIFETIME); @@ -132,7 +133,7 @@ const Toast = (props: ToastProps) => { const toastNode = toastRef.current; if (toastNode) { const height = toastNode.getBoundingClientRect().height; - // Add toast height tot heights array after the toast is mounted + // Add toast height to heights array after the toast is mounted setInitialHeight(height); setHeights((h) => [{ toastId: toast.id, height, position: toast.position }, ...h]); return () => setHeights((h) => h.filter((height) => height.toastId !== toast.id)); @@ -259,6 +260,7 @@ const Toast = (props: ToastProps) => { data-styled={!Boolean(toast.jsx || toast.unstyled || unstyled)} data-mounted={mounted} data-promise={Boolean(toast.promise)} + data-swiped={isSwiped} data-removed={removed} data-visible={isVisible} data-y-position={y} @@ -306,6 +308,7 @@ const Toast = (props: ToastProps) => { toast.onDismiss?.(toast); deleteToast(); setSwipeOut(true); + setIsSwiped(false); return; } @@ -317,6 +320,11 @@ const Toast = (props: ToastProps) => { const yPosition = event.clientY - pointerStartRef.current.y; const isHighlighted = window.getSelection()?.toString().length > 0; + const swipeAmount = Number(toastRef.current?.style.getPropertyValue('--swipe-amount').replace('px', '') || 0); + + if (swipeAmount > 0) { + setIsSwiped(true); + } if (isHighlighted) return; @@ -656,6 +664,7 @@ const Toaster = forwardRef(function Toaster(props, re data-sonner-toaster data-theme={actualTheme} data-y-position={y} + data-expanded={expanded} data-x-position={x} style={ { diff --git a/src/styles.css b/src/styles.css index 1b7ca2c..9a30a23 100644 --- a/src/styles.css +++ b/src/styles.css @@ -51,7 +51,7 @@ transition: transform 400ms ease; } -:where([data-sonner-toaster]:hover) { +:where([data-sonner-toaster][data-expanded='true']) { transform: translateY(-10px); } @@ -337,6 +337,9 @@ [data-sonner-toast][data-swiping='true'] { transform: var(--y) translateY(var(--swipe-amount, 0px)); transition: none; +} + +[data-sonner-toast][data-swiped='true'] { user-select: none; }