diff --git a/.changeset/hungry-maps-end.md b/.changeset/hungry-maps-end.md
new file mode 100644
index 00000000..0ad8603f
--- /dev/null
+++ b/.changeset/hungry-maps-end.md
@@ -0,0 +1,5 @@
+---
+"@animareflection/ui": minor
+---
+
+Update `Toast` components to use sonner
diff --git a/bun.lockb b/bun.lockb
index 22ccc274..929e7852 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/docs/usage.md b/docs/usage.md
index 6a6a1bd5..3560ee2d 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -59,7 +59,7 @@ Now you are ready to install the UI library. You can either install it [from the
## Remote
-Install from remote repository along with required dependencies: `bun add @animareflection/ui @ark-ui/react framer-motion react-hot-toast`
+Install from remote repository along with required dependencies: `bun add @animareflection/ui @ark-ui/react framer-motion sonner`
## Local
diff --git a/package.json b/package.json
index 0698e81e..d0dfc96b 100644
--- a/package.json
+++ b/package.json
@@ -110,8 +110,8 @@
"radash": "^11.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-hot-toast": "^2.4.1",
"react-icons": "^4.12.0",
+ "sonner": "^1.3.1",
"storybook": "^7.6.6",
"storybook-dark-mode": "^3.0.3",
"ts-node": "^10.9.2",
diff --git a/src/components/core/Toast/Toast.recipe.ts b/src/components/core/Toast/Toast.recipe.ts
index f219b81f..8afa41e0 100644
--- a/src/components/core/Toast/Toast.recipe.ts
+++ b/src/components/core/Toast/Toast.recipe.ts
@@ -3,15 +3,24 @@ import { defineSlotRecipe } from "@pandacss/dev";
export const toastRecipe = defineSlotRecipe({
className: "toast",
description: "The styles for the Toast component",
- slots: ["closeTrigger", "title", "description"],
+ slots: ["root", "closeTrigger", "title", "description"],
base: {
+ root: {
+ display: "flex",
+ flexDirection: "column",
+ borderRadius: "md",
+ borderWidth: "1px",
+ boxShadow: "sm",
+ minW: "300px",
+ px: 5,
+ py: 2,
+ },
closeTrigger: {
display: "flex",
position: "absolute",
cursor: "pointer",
- color: "fg.muted",
- top: 2,
- right: 2,
+ top: 3,
+ right: 3,
_hover: {
opacity: 0.8,
},
@@ -21,34 +30,75 @@ export const toastRecipe = defineSlotRecipe({
},
description: {
fontSize: "sm",
- color: "fg.muted",
},
},
+ defaultVariants: {
+ variant: "unstyled",
+ },
variants: {
variant: {
+ unstyled: {
+ root: {
+ bgColor: "bg.default",
+ borderColor: "border.default",
+ },
+ closeTrigger: {
+ color: "fg.muted",
+ },
+ description: {
+ color: "fg.muted",
+ },
+ title: {
+ color: "fg.default",
+ },
+ },
success: {
+ root: {
+ bgColor: { base: "green.50", _dark: "green.950" },
+ borderColor: { base: "green.200", _dark: "green.800" },
+ },
closeTrigger: {
color: "green.500",
},
description: {
color: "green.500",
},
+ title: {
+ color: { base: "green.950", _dark: "green.50" },
+ },
},
error: {
+ root: {
+ bgColor: { base: "red.50", _dark: "red.950" },
+ borderColor: { base: "red.200", _dark: "red.800" },
+ },
closeTrigger: {
color: "red.500",
},
description: {
color: "red.500",
},
+ title: {
+ color: { base: "red.950", _dark: "red.50" },
+ },
},
loading: {
+ root: {
+ bgColor: { base: "brand.primary.50", _dark: "brand.primary.950" },
+ borderColor: {
+ base: "brand.primary.200",
+ _dark: "brand.primary.800",
+ },
+ },
closeTrigger: {
color: "brand.primary.500",
},
description: {
color: "brand.primary.500",
},
+ title: {
+ color: { base: "brand.primary.950", _dark: "brand.primary.50" },
+ },
},
},
},
diff --git a/src/components/core/Toast/Toast.tsx b/src/components/core/Toast/Toast.tsx
index fa4d1238..882328c0 100644
--- a/src/components/core/Toast/Toast.tsx
+++ b/src/components/core/Toast/Toast.tsx
@@ -1,12 +1,17 @@
import { FiX } from "react-icons/fi";
import Icon from "components/core/Icon/Icon";
-import { Flex, panda } from "generated/panda/jsx";
+import {
+ PrimitiveToast,
+ PrimitiveToastClose,
+ PrimitiveToastDescription,
+ PrimitiveToastTitle,
+} from "components/primitives";
-import type { FlexProps } from "generated/panda/jsx";
+import type { PrimitiveToastProps } from "components/primitives";
import type { ToastVariantProps } from "generated/panda/recipes";
-export interface Props extends FlexProps, ToastVariantProps {
+export interface Props extends PrimitiveToastProps, ToastVariantProps {
title: string;
description?: string;
onClose?: () => void;
@@ -16,9 +21,9 @@ export interface Props extends FlexProps, ToastVariantProps {
* Core UI toast.
*/
const Toast = ({ title, description, onClose, ...rest }: Props) => (
-
+
{onClose && (
- (
-
+
)}
- {title}
- {description}
-
+ {title}
+ {description && (
+ {description}
+ )}
+
);
export default Toast;
diff --git a/src/components/core/Toast/Toaster.stories.tsx b/src/components/core/Toast/Toaster.stories.tsx
index 3df7670f..6988e508 100644
--- a/src/components/core/Toast/Toaster.stories.tsx
+++ b/src/components/core/Toast/Toaster.stories.tsx
@@ -1,11 +1,13 @@
-import { default as toast } from "react-hot-toast";
+import { toast } from "sonner";
import { toastState } from "./Toast.spec";
import { Button, Toast, Toaster } from "components/core";
import { Flex, Grid } from "generated/panda/jsx";
import type { Meta, StoryObj } from "@storybook/react";
-import type { ToastPosition } from "react-hot-toast";
+import type { ToastT } from "sonner";
+
+type Position = ToastT["position"];
type Story = StoryObj;
@@ -18,7 +20,6 @@ const notify = () =>
description="toast description"
onClose={closeToast}
/>,
- { icon: "🏝" },
);
const success = () =>
toast.success(
@@ -59,12 +60,17 @@ const promise = () => {
);
};
-const PositionTemplate = ({ position }: { position: ToastPosition }) => {
+const PositionTemplate = ({ position }: { position: Position }) => {
const showToastPosition = () =>
- toast(`Position set to ${position}`, { position });
+ toast(, { position });
return (
-