Skip to content

Commit

Permalink
chore: adding the swiping interaction for toast removal
Browse files Browse the repository at this point in the history
  • Loading branch information
macci001 committed Dec 26, 2024
1 parent df7d9c4 commit f92ff39
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 17 deletions.
1 change: 0 additions & 1 deletion apps/docs/app/examples/toast/position/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export default function App() {
<div className="flex flex-wrap gap-x-2">
<Button
className="w-fit m-2"
variant={"bordered"}
onPress={() =>
addToast({
title: "Toast title",
Expand Down
22 changes: 22 additions & 0 deletions apps/docs/app/examples/toast/with-timeout/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";
import {addToast, Button, ToastProvider} from "@nextui-org/react";

export default function App() {
return (
<>
<ToastProvider />
<Button
className="w-fit m-2"
onPress={() => {
addToast({
title: "Toast Title",
description: "Toast Description",
timeout: 3000,
});
}}
>
Show Toast
</Button>
</>
);
}
2 changes: 2 additions & 0 deletions apps/docs/content/components/toast/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import customIcon from "./custom-icon";
import hiddenIcon from "./hidden-icon";
import withAction from "./with-action";
import customStyles from "./custom-styles";
import withTimeout from "./with-timeout";

export const toastContent = {
color,
Expand All @@ -14,4 +15,5 @@ export const toastContent = {
hiddenIcon,
withAction,
customStyles,
withTimeout,
};
21 changes: 21 additions & 0 deletions apps/docs/content/components/toast/with-timeout.raw.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {addToast, Button, ToastProvider} from "@nextui-org/react";

export default function App() {
return (
<>
<ToastProvider />
<Button
className="w-fit m-2"
onPress={() => {
addToast({
title: "Toast Title",
description: "Toast Description",
timeout: 3000,
});
}}
>
Show Toast
</Button>
</>
);
}
9 changes: 9 additions & 0 deletions apps/docs/content/components/toast/with-timeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import App from "./with-timeout.raw.jsx?raw";

const react = {
"/App.jsx": App,
};

export default {
...react,
};
24 changes: 24 additions & 0 deletions apps/docs/content/docs/components/toast.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ Toast supports an `endContent` prop for additional actions.
files={toastContent.withAction}
/>

### With Timeout

Toast supports an `endContent` prop for additional actions.

<CodeDemo
asIframe
title="With Timeout"
previewHeight="350px"
iframeSrc="/examples/toast/with-timeout"
files={toastContent.withTimeout}
/>

### Toast Position

<CodeDemo
Expand Down Expand Up @@ -220,6 +232,18 @@ Toast has the following slots:
description: "The alert end content",
default: "-"
},
{
attribute: "timeout",
type: "number | undefined",
description: "Time in milliseconds after which the toast will be closed",
default: "undefined"
},
{
attribute: "priority",
type: "number | undefined",
description: "Priority at which the toast will be displayed",
default: "undefined",
},
{
attribute: "hideIcon",
type: "boolean",
Expand Down
18 changes: 15 additions & 3 deletions packages/components/toast/src/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@nextui-org/shared-icons";
import {motion, AnimatePresence} from "framer-motion";
import {Progress} from "@nextui-org/progress";
import {cloneElement, isValidElement} from "react";
import {cloneElement, isValidElement, useState} from "react";

import {UseToastProps, useToast} from "./use-toast";

Expand All @@ -33,6 +33,8 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
color,
hideIcon,
position,
toast,
state,
getToastProps,
getContentProps,
getTitleProps,
Expand Down Expand Up @@ -60,14 +62,24 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
const customIcon = icon && isValidElement(icon) ? cloneElement(icon, getIconProps()) : null;
const IconComponent = iconMap[color] || iconMap.primary;

const [isOut, setIsOut] = useState(false);

return (
<AnimatePresence>
<motion.div
animate="visible"
animate={isOut ? {x: "100vw"} : "visible"}
drag="x"
dragConstraints={{left: 0, right: 0}}
exit="exit"
initial="hidden"
transition={{duration: 0.3}}
transition={{duration: 0.5}}
variants={toastVariants}
onDragEnd={(_, info) => {
if (info.offset.x > 50) {
state.close(toast.key);
setIsOut(true);
}
}}
>
<Component ref={domRef} {...getToastProps()}>
<main {...getContentProps()}>
Expand Down
15 changes: 9 additions & 6 deletions packages/components/toast/src/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
const [props, variantProps] = mapPropsVariants(originalProps, toastTheme.variantKeys);

const [closeProgressBarValue, setCloseProgressBarValue] = useState(0);
const [isToastClicked, setIsToastClicked] = useState(false);
const [isToastHovered, setIsToastHovered] = useState(false);

useEffect(() => {
const interval = setInterval(async () => {
if (isToastClicked) {
if (isToastHovered) {
return;
}
setCloseProgressBarValue(closeProgressBarValue + 10);
Expand All @@ -66,6 +66,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
endContent,
hideIcon = false,
position = "right-bottom",
state,
...otherProps
} = props;

Expand Down Expand Up @@ -101,18 +102,18 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
(props = {}) => ({
ref: domRef,
className: slots.base({class: clsx(baseStyles, classNames?.base)}),
onMouseDown: () => {
onMouseEnter: () => {
if (!toast.timer) {
return;
}
setIsToastClicked(true);
setIsToastHovered(true);
toast.timer.pause();
},
onMouseUp: () => {
onMouseLeave: () => {
if (!toast.timer) {
return;
}
setIsToastClicked(false);
setIsToastHovered(false);
toast.timer.resume();
},
"data-has-title": dataAttr(!isEmpty(title)),
Expand Down Expand Up @@ -193,6 +194,8 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
color: variantProps["color"],
hideIcon,
position,
state,
toast: props.toast,
getToastProps,
getTitleProps,
getContentProps,
Expand Down
22 changes: 15 additions & 7 deletions packages/core/theme/src/components/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ const toast = tv({
slots: {
base: [
"flex gap-x-4 items-center",
"group",
"cursor-pointer",
"relative",
"z-500",
"box-border",
"outline-none",
"p-2 px-4 mx-1",
"p-4 px-6 mx-1",
"my-1",
"sm:mx-4",
"sm:my-4",
Expand All @@ -19,8 +21,8 @@ const toast = tv({
"text-white",
"shadow-inner",
],
title: ["font-medium", "ms-4"],
description: ["font-light", "ms-4"],
title: ["font-medium", "ms-4", "text-sm"],
description: ["font-light", "ms-4", "text-xs"],
icon: ["w-6 h-6 fill-current"],
content: ["flex flex-grow flex-row gap-x-1 items-center"],
progressBar: [
Expand All @@ -35,23 +37,29 @@ const toast = tv({
],
progressTrack: ["bg-default-200"],
closeButton: [
"w-4 h-4 min-w-4 p-0.5 absolute -right-1 -top-1 flex items-center justify-center bg-default-100 hover:bg-default-200 text-default-400 hover:text-default-600 border border-1 border-default-400",
"opacity-0 group-hover:opacity-100 transition-opacity ease-in duration-300 w-4 h-4 min-w-4 p-0.5 absolute -right-1 -top-1 items-center justify-center bg-default-100 hover:bg-default-200 text-default-400 hover:text-default-600 border border-1 border-default-400",
],
},
variants: {
size: {
sm: {
icon: "w-4 h-4",
title: "text-sm font-medium",
description: "text-xs font-light",
},
md: {
icon: "w-6 h-6",
title: "text-sm font-semibold",
description: "text-xs font-light",
},
lg: {
icon: "w-8 h-8",
title: "text-md font-semibold",
description: "text-sm font-light",
},
},
variant: {
flat: "bg-default",
flat: "bg-default-50",
faded: "bg-default border border-1 border-default-400",
solid: "bg-default shadow-inner",
bordered: "bg-white dark:bg-black border border-1 border-default-400",
Expand Down Expand Up @@ -93,9 +101,9 @@ const toast = tv({
},
},
defaultVariants: {
size: "sm",
size: "md",
variant: "flat",
radius: "none",
radius: "md",
},
compoundVariants: [
// flat and color
Expand Down

0 comments on commit f92ff39

Please sign in to comment.