diff --git a/apps/web/package.json b/apps/web/package.json
index d9185ef82..136aa9fda 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -50,7 +50,7 @@
"react-markdown": "9.0.1",
"react-player": "2.16.0",
"react-syntax-highlighter": "15.6.1",
- "react-toastify": "^10.0.6",
+ "react-toastify": "^11.0.1",
"react-use-websocket": "^4.11.1",
"recharts": "^2.14.1",
"rehype-mathjax": "6.0.0",
diff --git a/apps/web/src/components/main-layout.tsx b/apps/web/src/components/main-layout.tsx
index ae1f4f4e7..745e50c43 100644
--- a/apps/web/src/components/main-layout.tsx
+++ b/apps/web/src/components/main-layout.tsx
@@ -40,7 +40,7 @@ export const MainLayout = ({
if (hasJustRegistered) {
customToast(t('auth.dashboardUnlocked'), {
mode: variant === 'dark' ? 'dark' : 'light',
- color: 'secondary',
+ color: 'primary',
time: 5000,
closeButton: true,
imgSrc: SignInIconLight,
diff --git a/apps/web/src/routes/_content/courses/$courseId/index.tsx b/apps/web/src/routes/_content/courses/$courseId/index.tsx
index afd5b27b4..561daf623 100644
--- a/apps/web/src/routes/_content/courses/$courseId/index.tsx
+++ b/apps/web/src/routes/_content/courses/$courseId/index.tsx
@@ -655,7 +655,7 @@ function CourseDetails() {
: async () => {
if (!isLoggedIn && !hasSeenRegisterToast) {
customToast(t('auth.trackProgress'), {
- color: 'secondary',
+ color: 'primary',
mode: 'light',
imgSrc: SignInIconLight,
onClick: () => {
@@ -674,7 +674,7 @@ function CourseDetails() {
userCourseProgress[0].completedChaptersCount === 0))
) {
customToast(t('courses.details.courseAddedToDashboard'), {
- color: 'secondary',
+ color: 'primary',
mode: 'light',
imgSrc: SignInIconLight,
closeButton: true,
diff --git a/packages/ui/src/atoms/toast.tsx b/packages/ui/src/atoms/toast.tsx
index c182d40c3..e85e7ff67 100644
--- a/packages/ui/src/atoms/toast.tsx
+++ b/packages/ui/src/atoms/toast.tsx
@@ -4,18 +4,21 @@ import { IoCloseOutline } from 'react-icons/io5';
import type { IconType } from 'react-icons/lib';
import { toast } from 'react-toastify';
-const toastVariants = cva('md:!w-[299px]', {
+const toastVariants = cva('md:!w-[299px] focus:ring-1 focus:ring-newGray-2', {
variants: {
mode: {
light: '',
dark: 'dark',
},
color: {
- primary: '!bg-darkOrange-2 dark:!bg-darkOrange-8',
- secondary: '!bg-darkOrange-0 dark:!bg-darkOrange-10',
- warning: '!bg-red-1 dark:!bg-red-7',
- success: '!bg-brightGreen-1 dark:!bg-brightGreen-9',
- neutral: '!bg-newBlack-3 dark:!bg-newGray-6',
+ primary:
+ '!bg-darkOrange-0 dark:!bg-darkOrange-10 hover:!bg-darkOrange-1 hover:dark:!bg-darkOrange-9 focus:!bg-darkOrange-1 focus:dark:!bg-darkOrange-9',
+ warning:
+ '!bg-red-1 dark:!bg-red-9 hover:!bg-red-2 hover:dark:!bg-red-8 focus:!bg-red-2 focus:dark:!bg-red-8',
+ success:
+ '!bg-brightGreen-1 dark:!bg-brightGreen-9 hover:!bg-brightGreen-2 hover:dark:!bg-brightGreen-8 focus:!bg-brightGreen-2 focus:dark:!bg-brightGreen-8',
+ neutral:
+ '!bg-newGray-6 dark:!bg-newBlack-3 hover:!bg-newGray-5 hover:dark:!bg-newBlack-4 focus:!bg-newGray-5 focus:dark:!bg-newBlack-4',
},
},
defaultVariants: {
@@ -43,11 +46,10 @@ const iconVariants = cva('shrink-0', {
dark: 'dark',
},
color: {
- primary: '!text-darkOrange-5',
- secondary: '!text-darkOrange-3 dark:!text-darkOrange-5',
- warning: '!text-red-5 dark:!text-red-3',
- success: '!text-brightGreen-4',
- neutral: '!text-newGray-3 dark:!text-newGray-4',
+ primary: '!text-darkOrange-4 dark:!text-darkOrange-6',
+ warning: '!text-red-5',
+ success: '!text-brightGreen-4 dark:!text-brightGreen-6',
+ neutral: '!text-newGray-3 dark:!text-newGray-2',
},
},
defaultVariants: {
@@ -64,10 +66,9 @@ const progressBarVariants = cva('', {
},
color: {
primary: '!bg-darkOrange-4 dark:!bg-darkOrange-6',
- secondary: '!bg-darkOrange-2 dark:!bg-darkOrange-7',
- warning: '!bg-red-2 dark:!bg-red-4',
- success: '!bg-brightGreen-3 dark:!bg-brightGreen-5',
- neutral: '!bg-newGray-4 dark:!bg-newGray-3',
+ warning: '!bg-red-5',
+ success: '!bg-brightGreen-4 dark:!bg-brightGreen-6',
+ neutral: '!bg-newGray-3 dark:!bg-newGray-2',
},
},
defaultVariants: {
@@ -83,10 +84,9 @@ const toastCloseButtonVariants = cva('shrink-0', {
dark: 'dark hover:!brightness-110',
},
color: {
- primary: '!text-darkOrange-6',
- secondary: '!text-darkOrange-4 dark:!text-darkOrange-6',
- warning: '!text-red-4',
- success: '!text-brightGreen-5 dark:!text-brightGreen-6',
+ primary: '!text-darkOrange-4 dark:!text-darkOrange-6',
+ warning: '!text-red-5',
+ success: '!text-brightGreen-4 dark:!text-brightGreen-6',
neutral: '!text-newGray-3 dark:!text-newGray-2',
},
},
@@ -98,7 +98,7 @@ const toastCloseButtonVariants = cva('shrink-0', {
interface ToastProps {
mode?: 'light' | 'dark';
- color?: 'primary' | 'secondary' | 'warning' | 'success' | 'neutral';
+ color?: 'primary' | 'warning' | 'success' | 'neutral';
}
export const customToast = (
@@ -116,51 +116,85 @@ export const customToast = (
) => {
const { closeOnClick = true } = options;
- return toast(message, {
- autoClose: options.time || 5000,
- className: toastVariants({
- mode: options.mode,
- color: options.color,
- }),
- bodyClassName: textVariants({
- mode: options.mode,
- }),
- progressClassName: progressBarVariants({
- mode: options.mode,
- color: options.color,
+ return toast(
+ ToastContent({
+ message: message,
+ className: textVariants({
+ mode: options.mode,
+ }),
+ onClick: options.onClick,
}),
- icon: options.imgSrc
- ? () => (
-
- )
- : options.icon && (
-
- ),
- closeButton: options.onClick
- ? false
- : options.closeButton
- ? ({
- closeToast,
- }: {
- closeToast: MouseEventHandler;
- }) => (
- (
+
+ )
+ : options.icon && (
+
- )
- : false,
- onClick: options.onClick,
- closeOnClick: closeOnClick,
- });
+ ),
+ closeButton: options.onClick
+ ? false
+ : options.closeButton
+ ? ({
+ closeToast,
+ }: {
+ closeToast: MouseEventHandler;
+ }) => (
+
+ )
+ : false,
+ onClick: options.onClick,
+ closeOnClick: closeOnClick,
+ },
+ );
};
-export const ToastCloseButton = ({
+const ToastContent = ({
+ message,
+ className,
+ onClick,
+}: {
+ message: string;
+ className: string;
+ onClick?: () => void;
+}) => (
+ {
+ if (onClick && (e.key === 'Enter' || e.key === ' ')) {
+ e.preventDefault();
+ onClick();
+ }
+ }}
+ role={onClick ? 'button' : undefined}
+ tabIndex={onClick ? 0 : undefined}
+ >
+ {message}
+
+);
+
+const ToastCloseButton = ({
closeToast,
mode,
color,
@@ -181,7 +215,7 @@ export const ToastCloseButton = ({
);
-export const ToastIconWithClasses = ({
+const ToastIconWithClasses = ({
icon: Icon,
mode,
color,
diff --git a/packages/ui/src/styles/global.css b/packages/ui/src/styles/global.css
index b21acbb6c..75d8280ab 100644
--- a/packages/ui/src/styles/global.css
+++ b/packages/ui/src/styles/global.css
@@ -677,10 +677,6 @@
transform: translate3d(0, var(--y), 0) scale(var(--s));
transition: transform 0.3s;
}
-.Toastify__toast--stacked[data-collapsed] .Toastify__toast-body,
-.Toastify__toast--stacked[data-collapsed] .Toastify__close-button {
- transition: opacity 0.1s;
-}
.Toastify__toast--stacked[data-collapsed='false'] {
overflow: visible;
}
@@ -723,21 +719,6 @@
.Toastify__toast--close-on-click {
cursor: pointer;
}
-.Toastify__toast-body {
- margin: auto 0;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto;
- padding: 6px;
- display: -ms-flexbox;
- display: flex;
- -ms-flex-align: center;
- align-items: center;
-}
-.Toastify__toast-body > div:last-child {
- word-break: break-word;
- -ms-flex: 1;
- flex: 1;
-}
.Toastify__toast-icon {
-webkit-margin-end: 12px;
margin-inline-end: 12px;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 45a9f83ac..39e01de64 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -259,8 +259,8 @@ importers:
specifier: 15.6.1
version: 15.6.1(react@18.3.1)
react-toastify:
- specifier: ^10.0.6
- version: 10.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ specifier: ^11.0.1
+ version: 11.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-use-websocket:
specifier: ^4.11.1
version: 4.11.1
@@ -405,7 +405,7 @@ importers:
version: 9.1.0(eslint@8.57.1)
eslint-import-resolver-custom-alias:
specifier: ^1.3.2
- version: 1.3.2(eslint-plugin-import@2.29.1)
+ version: 1.3.2(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1))
eslint-import-resolver-typescript:
specifier: ^3.7.0
version: 3.7.0(eslint-plugin-import@2.29.1)(eslint@8.57.1)
@@ -6891,6 +6891,12 @@ packages:
react: '>=18'
react-dom: '>=18'
+ react-toastify@11.0.1:
+ resolution: {integrity: sha512-ZALj1xpjOVlPPDKvdksGLemF9mM6FRltsykvv+JQpW9mildnBiy6nGz0685vo4+W8WitParsUfGk9qACArkZPA==}
+ peerDependencies:
+ react: ^18 || ^19
+ react-dom: ^18 || ^19
+
react-transition-group@4.4.5:
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
peerDependencies:
@@ -12389,7 +12395,7 @@ snapshots:
eslint: 8.57.1
eslint-plugin-turbo: 2.3.3(eslint@8.57.1)
- eslint-import-resolver-custom-alias@1.3.2(eslint-plugin-import@2.29.1):
+ eslint-import-resolver-custom-alias@1.3.2(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1)):
dependencies:
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1)
glob-parent: 6.0.2
@@ -12419,7 +12425,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -12449,7 +12455,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.4.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -14955,6 +14961,12 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
+ react-toastify@11.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ clsx: 2.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.26.0