Skip to content

Commit

Permalink
chore: fixing the animations and positions
Browse files Browse the repository at this point in the history
  • Loading branch information
macci001 committed Jan 1, 2025
1 parent beb4988 commit 03d8685
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 29 deletions.
13 changes: 11 additions & 2 deletions packages/components/toast/src/toast-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {ToastOptions, ToastQueue, useToastQueue} from "@react-stately/toast";
import {useProviderContext} from "@nextui-org/system";

import {ToastRegion} from "./toast-region";
import {ToastProps} from "./use-toast";
Expand All @@ -14,6 +15,7 @@ interface ToastProviderProps {
| "right-top"
| "left-top"
| "center-top";
disableAnimation?: boolean;
}

export const getToastQueue = () => {
Expand All @@ -26,14 +28,21 @@ export const getToastQueue = () => {
return globalToastQueue;
};

export const ToastProvider = ({position = "right-bottom"}: ToastProviderProps) => {
export const ToastProvider = ({
position = "right-bottom",
disableAnimation: disableAnimationProp = false,
}: ToastProviderProps) => {
const toastQueue = useToastQueue(getToastQueue());
const globalContext = useProviderContext();
const disableAnimation = disableAnimationProp ?? globalContext?.disableAnimation ?? false;

if (toastQueue.visibleToasts.length == 0) {
return null;
}

return <ToastRegion position={position} toastQueue={toastQueue} />;
return (
<ToastRegion disableAnimation={disableAnimation} position={position} toastQueue={toastQueue} />
);
};

export const addToast = ({...props}: ToastProps & ToastOptions) => {
Expand Down
17 changes: 10 additions & 7 deletions packages/components/toast/src/toast-region.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ interface ToastRegionProps<T> extends AriaToastRegionProps {
| "right-top"
| "left-top"
| "center-top";
disableAnimation: boolean;
}

export function ToastRegion<T extends ToastProps>({
toastQueue,
position,
disableAnimation,
...props
}: ToastRegionProps<T>) {
const ref = useRef(null);
Expand All @@ -32,12 +34,12 @@ export function ToastRegion<T extends ToastProps>({
});

const positionStyles: Record<string, string> = {
"right-bottom": "bottom-0 right-0 pr-2",
"left-bottom": "bottom-0 left-0 pl-2",
"center-bottom": "bottom-0 left-1/2 -translate-x-1/2",
"right-top": "top-0 right-0 pr-2",
"left-top": "top-0 left-0 pl-2",
"center-top": "top-0 left-1/2 -translate-x-1/2",
"right-bottom": "fixed flex flex-col bottom-0 right-0 pr-2",
"left-bottom": "fixed flex flex-col bottom-0 left-0 pl-2",
"center-bottom": "fixed flex flex-col bottom-0 left-1/2 -translate-x-1/2",
"right-top": "fixed flex flex-col top-0 right-0 pr-2",
"left-top": "fixed flex flex-col top-0 left-0 pl-2",
"center-top": "fixed flex flex-col top-0 left-1/2 -translate-x-1/2",
};
const positionStyle = position ? positionStyles[position] : positionStyles["right-bottom"];
const [heights, setHeights] = useState<number[]>([]);
Expand All @@ -46,7 +48,7 @@ export function ToastRegion<T extends ToastProps>({
<div
{...mergeProps(regionProps, hoverProps)}
ref={ref}
className={clsx("fixed flex flex-col", positionStyle)}
className={clsx(disableAnimation ? positionStyle : "")}
>
{toastQueue.visibleToasts.map((toast: QueuedToast<ToastProps>, index) => {
return (
Expand All @@ -55,6 +57,7 @@ export function ToastRegion<T extends ToastProps>({
state={toastQueue}
toast={toast}
{...toast.content}
disableAnimation={disableAnimation}
heights={heights}
index={index}
isRegionHovered={isHovered}
Expand Down
24 changes: 18 additions & 6 deletions packages/components/toast/src/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
WarningIcon,
} from "@nextui-org/shared-icons";
import {motion, AnimatePresence} from "framer-motion";
import {cloneElement, isValidElement} from "react";
import {cloneElement, isValidElement, useState} from "react";
import {clsx} from "@nextui-org/shared-utils";

import {UseToastProps, useToast} from "./use-toast";
Expand Down Expand Up @@ -114,12 +114,14 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
const positionStyles: Record<string, string> = {
"right-bottom": "bottom-0 right-0 mx-auto w-max",
"left-bottom": "bottom-0 left-0 mx-auto w-max",
"center-bottom": "bottom-0 left-0 right-0 mx-auto w-max",
"center-bottom": "bottom-0 left-0 right-0 w-max mx-auto",
"right-top": "top-0 right-0 mx-auto w-max",
"left-top": "top-0 left-0 mx-auto w-max",
"center-top": "top-0 left-0 right-0 w-max mx-auto",
};
const positionStyle = position ? positionStyles[position] : positionStyles["right-bottom"];
const multiplier = position.includes("top") ? -1 : 1;
const multiplier = position.includes("top") ? 1 : -1;
const [drag, setDrag] = useState(false);

return (
<>
Expand All @@ -130,23 +132,33 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
<motion.div
animate={{
opacity: total - index - 1 <= 2 ? 1 : 0,
y: isRegionHovered ? liftHeight * -1 - 20 : -20 + (index + 1 - total) * 8,
y: isRegionHovered ? liftHeight * multiplier : (total - 1 - index) * 8 * multiplier,
scaleX: isRegionHovered ? 1 : 1 - (total - 1 - index) * 0.1,
height: isRegionHovered ? initialHeight : frontHeight,
}}
className={clsx("absolute", positionStyle)}
className={clsx(
"fixed",
positionStyle,
drag
? "before:content-[''] before:absolute before:left-0 before:right-0 before:h-full before:-z-10"
: "",
)}
drag={position.includes("center") ? "y" : "x"}
dragConstraints={{left: 0, right: 0, top: 0, bottom: 0}}
exit={{opacity: 0, y: 100}}
initial={{opacity: 0, y: 40 * multiplier, scale: 1}}
initial={{opacity: 0, y: -40 * multiplier, scale: 1}}
transition={{duration: 0.3, ease: "easeOut"}}
variants={toastVariants}
onDragEnd={(_, info) => {
setDrag(false);
const offsetX = info.offset.x;
const offsetY = info.offset.y;

handleDragEnd(offsetX, offsetY);
}}
onDragStart={() => {
setDrag(true);
}}
>
{toastContent}
</motion.div>
Expand Down
21 changes: 9 additions & 12 deletions packages/components/toast/src/use-toast.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import type {SlotsToClasses, ToastSlots, ToastVariantProps} from "@nextui-org/theme";

import {
HTMLNextUIProps,
PropGetter,
mapPropsVariants,
useProviderContext,
} from "@nextui-org/system";
import {HTMLNextUIProps, PropGetter, mapPropsVariants} from "@nextui-org/system";
import {toast as toastTheme} from "@nextui-org/theme";
import {ReactRef, useDOMRef} from "@nextui-org/react-utils";
import {clsx, dataAttr, isEmpty, objectToDeps} from "@nextui-org/shared-utils";
Expand Down Expand Up @@ -95,19 +90,18 @@ interface Props<T> extends HTMLNextUIProps<"div">, ToastProps {
state: ToastState<T>;
heights: number[];
setHeights: (val: number[]) => void;
disableAnimation: boolean;
}

export type UseToastProps<T = ToastProps> = Props<T> &
ToastVariantProps &
Omit<AriaToastProps<T>, "div">;

export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>) {
const globalContext = useProviderContext();
const [props, variantProps] = mapPropsVariants(originalProps, toastTheme.variantKeys);

const [isToastHovered, setIsToastHovered] = useState(false);
const disableAnimation =
originalProps.disableAnimation ?? globalContext?.disableAnimation ?? false;
const disableAnimation = originalProps.disableAnimation;

const animationRef = useRef<number | null>(null);
const startTime = useRef<number | null>(null);
Expand Down Expand Up @@ -204,7 +198,10 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
const originalHeight = toastNode.style.height;

toastNode.style.height = "auto";
const newHeight = toastNode.getBoundingClientRect().height;
const computedStyle = getComputedStyle(toastNode);
const marginTop = parseFloat(computedStyle.marginTop);
const marginBottom = parseFloat(computedStyle.marginBottom);
const newHeight = toastNode.getBoundingClientRect().height + marginTop + marginBottom;

toastNode.style.height = originalHeight;

Expand All @@ -219,10 +216,10 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
setHeights(updatedHeights);
}, [mounted, total, setHeights, index]);

let liftHeight = 4;
let liftHeight = 0;

for (let idx = index + 1; idx < total; idx++) {
liftHeight += 4 + heights[idx];
liftHeight += heights[idx];
}

const frontHeight = heights[heights.length - 1];
Expand Down
2 changes: 0 additions & 2 deletions packages/core/theme/src/components/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ const toast = tv({
"outline-none",
"p-3 mx-1",
"my-1",
"sm:mx-4",
"sm:my-4",
"w-[210px] sm:w-[270px] md:w-[300px]",
"min-h-4",
"text-white",
Expand Down

0 comments on commit 03d8685

Please sign in to comment.