diff --git a/apps/web/src/assets/icons/alert-octagon.svg b/apps/web/src/assets/icons/alert-octagon.svg
new file mode 100644
index 0000000000..2292351802
--- /dev/null
+++ b/apps/web/src/assets/icons/alert-octagon.svg
@@ -0,0 +1,11 @@
+
diff --git a/apps/web/src/assets/icons/alert-triangle.svg b/apps/web/src/assets/icons/alert-triangle.svg
new file mode 100644
index 0000000000..c5b5680189
--- /dev/null
+++ b/apps/web/src/assets/icons/alert-triangle.svg
@@ -0,0 +1,11 @@
+
diff --git a/apps/web/src/assets/icons/index.ts b/apps/web/src/assets/icons/index.ts
index f60d24e7f0..4655aaa33d 100644
--- a/apps/web/src/assets/icons/index.ts
+++ b/apps/web/src/assets/icons/index.ts
@@ -1,5 +1,7 @@
export { default as AddContactIcon } from "./add-contact-s.svg";
export { default as AlertCircleIcon } from "./alert-circle.svg";
+export { default as AlertTriangleIcon } from "./alert-triangle.svg";
+export { default as AlertOctagonIcon } from "./alert-octagon.svg";
export { default as AlertIcon } from "./alert.svg";
export { default as ArrowDownLeftIcon } from "./arrow-down-left.svg";
export { default as ArrowLeftCircleIcon } from "./arrow-left-circle.svg";
diff --git a/apps/web/src/components/CustomToast/CustomToast.tsx b/apps/web/src/components/CustomToast/CustomToast.tsx
new file mode 100644
index 0000000000..260ea994bf
--- /dev/null
+++ b/apps/web/src/components/CustomToast/CustomToast.tsx
@@ -0,0 +1,77 @@
+import {
+ Alert,
+ AlertDescription,
+ AlertTitle,
+ Flex,
+ Icon,
+ IconButton,
+ type UseToastOptions,
+} from "@chakra-ui/react";
+import { type ReactNode } from "react";
+
+import {
+ AlertCircleIcon,
+ AlertOctagonIcon,
+ AlertTriangleIcon,
+ CheckCircleIcon,
+ CloseIcon,
+} from "../../assets/icons";
+import { useColor } from "../../styles/useColor";
+
+type CustomToastProps = {
+ onClose: () => void;
+} & UseToastOptions;
+
+export const CustomToast = (props: CustomToastProps): ReactNode => {
+ const color = useColor();
+
+ const { status, id, title, isClosable, onClose, description } = props;
+
+ const ids = id
+ ? {
+ root: `toast-${id}`,
+ title: `toast-${id}-title`,
+ description: `toast-${id}-description`,
+ }
+ : undefined;
+
+ const AlertIcon = () => {
+ switch (props.status) {
+ case "info":
+ return ;
+ case "success":
+ return ;
+ case "error":
+ return ;
+ case "warning":
+ return ;
+ default:
+ return null;
+ }
+ };
+
+ return (
+
+
+
+ {title && {title}}
+ {description && (
+
+ {description}
+
+ )}
+
+ {isClosable && (
+ }
+ onClick={onClose}
+ variant="empty"
+ />
+ )}
+
+ );
+};
diff --git a/apps/web/src/components/CustomToast/index.ts b/apps/web/src/components/CustomToast/index.ts
new file mode 100644
index 0000000000..b4778eaf41
--- /dev/null
+++ b/apps/web/src/components/CustomToast/index.ts
@@ -0,0 +1 @@
+export * from "./CustomToast";
diff --git a/apps/web/src/providers/UmamiTheme.tsx b/apps/web/src/providers/UmamiTheme.tsx
index cf6fbdd390..8c13543b1b 100644
--- a/apps/web/src/providers/UmamiTheme.tsx
+++ b/apps/web/src/providers/UmamiTheme.tsx
@@ -3,6 +3,7 @@ import { Global, css } from "@emotion/react";
import { type PropsWithChildren } from "react";
import "focus-visible/dist/focus-visible";
+import { CustomToast } from "../components/CustomToast/CustomToast";
import theme from "../styles/theme";
const GlobalStyles = css`
@@ -17,7 +18,14 @@ const GlobalStyles = css`
`;
export const UmamiTheme = ({ children }: PropsWithChildren) => (
-
+
{children}
diff --git a/apps/web/src/styles/theme.ts b/apps/web/src/styles/theme.ts
index b860568a0a..19fce1f1a0 100644
--- a/apps/web/src/styles/theme.ts
+++ b/apps/web/src/styles/theme.ts
@@ -291,6 +291,36 @@ const theme = extendTheme({
},
}),
},
+ Alert: {
+ baseStyle: (props: StyleFunctionProps) => {
+ let accentColor;
+
+ switch (props.status) {
+ case "success":
+ accentColor = light.green;
+ break;
+ case "warning":
+ case "error":
+ accentColor = light.redDark;
+ break;
+ default:
+ accentColor = light.grey[400];
+ }
+
+ return {
+ container: {
+ borderRadius: "6px",
+ boxShadow: "0px 0px 8px 0px rgba(45, 55, 72, 0.25)",
+ borderLeft: `4px solid ${accentColor}`,
+ color: accentColor,
+ background: light.grey["white"],
+ },
+ description: {
+ color: light.grey[900],
+ },
+ };
+ },
+ },
Link: {
baseStyle: {
color: "gray.600",