diff --git a/pages/test.tsx b/pages/test.tsx
index b40ad354a..e94bba73d 100644
--- a/pages/test.tsx
+++ b/pages/test.tsx
@@ -1,19 +1,35 @@
-import { useEffect, useState } from 'react'
-import {
- ButtonCommon, Layout
-} from 'src/components/common'
+import { Layout, MessageCommon } from 'src/components/common'
+import { MessageItemProps } from 'src/components/common/MessageCommon/MessageItem/MessageItem'
+
+const data: MessageItemProps[] = [
+ {
+ id: 1,
+ content: 'Create account successfully',
+ type: 'error',
+ },
+ {
+ id: 2,
+ content: 'Create account successfully',
+ type: 'success',
+ },
+ {
+ id: 3,
+ content: 'Create account successfully',
+ type: 'warning',
+ },
+ {
+ id: 4,
+ content: 'Create account successfully',
+ type: 'info',
+ },
+]
export default function Test() {
- const [isLoading, setisLoading] = useState(false)
- useEffect(() => {
- setTimeout(() => {
- setisLoading(true)
- }, 3000)
- }, [])
return (
<>
- Back to home
- Back to home
- Back to home
+
+ {/* Create account successfully
+ Create account successfully
+ Create account successfully */}
>
)
}
diff --git a/src/components/common/Banner/Banner.tsx b/src/components/common/Banner/Banner.tsx
index dc95c2146..8a98fe3a6 100644
--- a/src/components/common/Banner/Banner.tsx
+++ b/src/components/common/Banner/Banner.tsx
@@ -41,4 +41,5 @@ const Banner = memo(({ data }: Props) => {
)
})
+Banner.displayName = 'Banner'
export default Banner
diff --git a/src/components/common/MessageCommon/MessageCommon.module.scss b/src/components/common/MessageCommon/MessageCommon.module.scss
new file mode 100644
index 000000000..99137e828
--- /dev/null
+++ b/src/components/common/MessageCommon/MessageCommon.module.scss
@@ -0,0 +1,7 @@
+.messageCommon {
+ @apply fixed;
+ top: 2.4rem;
+ left: 50%;
+ z-index: 20000;
+ transform: translateX(-50%);
+}
diff --git a/src/components/common/MessageCommon/MessageCommon.tsx b/src/components/common/MessageCommon/MessageCommon.tsx
new file mode 100644
index 000000000..8ffd62e35
--- /dev/null
+++ b/src/components/common/MessageCommon/MessageCommon.tsx
@@ -0,0 +1,26 @@
+import React, { memo } from 'react'
+import s from './MessageCommon.module.scss'
+import MessageItem, { MessageItemProps } from './MessageItem/MessageItem'
+
+interface Props {
+ messages: MessageItemProps[]
+ onRemove?: (id?: number) => void
+}
+
+const MessageCommon = memo(({ messages, onRemove }: Props) => {
+ return (
+
+ {messages.map((item) => (
+
+ ))}
+
+ )
+})
+
+MessageCommon.displayName = 'MessageCommon'
+export default MessageCommon
diff --git a/src/components/common/MessageCommon/MessageItem/MessageItem.module.scss b/src/components/common/MessageCommon/MessageItem/MessageItem.module.scss
new file mode 100644
index 000000000..da9896d05
--- /dev/null
+++ b/src/components/common/MessageCommon/MessageItem/MessageItem.module.scss
@@ -0,0 +1,64 @@
+@import "../../../../styles/utilities";
+
+.messageItem {
+ @apply shadow-sm flex justify-center items-center cursor-default;
+ width: fit-content;
+ padding: 0.8rem 2.4rem;
+ margin-bottom: .8rem;
+ border-radius: 0.8rem;
+ transition: all .5s;
+ animation: showMessage .5s;
+
+ &.hide {
+ display: none;
+ }
+ .icon {
+ @apply flex justify-center items-center;
+ margin-right: 0.8rem;
+ svg {
+ width: 2rem;
+ height: 2rem;
+ }
+ }
+ &.info {
+ @apply bg-info-light;
+ color: var(--info-dark);
+ .icon svg path {
+ fill: var(--info);
+ }
+ }
+ &.success {
+ @apply bg-positive-light;
+ color: var(--positive-dark);
+ .icon svg path {
+ fill: var(--positive);
+ }
+ }
+ &.error {
+ @apply bg-negative-light;
+ color: var(--negative-dark);
+ .icon svg path {
+ fill: var(--negative);
+ }
+ }
+ &.warning {
+ @apply bg-warning-light;
+ color: var(--warning-dark);
+ .icon svg path {
+ fill: var(--warning);
+ }
+ }
+}
+
+
+@keyframes showMessage {
+ 0% {
+ transform: translateY(-6rem);
+ opacity: .5;
+ }
+
+ 100% {
+ transform: none;
+ opacity: 1;
+ }
+}
diff --git a/src/components/common/MessageCommon/MessageItem/MessageItem.tsx b/src/components/common/MessageCommon/MessageItem/MessageItem.tsx
new file mode 100644
index 000000000..38d7ed180
--- /dev/null
+++ b/src/components/common/MessageCommon/MessageItem/MessageItem.tsx
@@ -0,0 +1,71 @@
+import classNames from 'classnames'
+import React, { memo, useEffect, useMemo, useState } from 'react'
+import { IconCheck, IconError, IconInfo } from 'src/components/icons'
+import s from './MessageItem.module.scss'
+
+export interface MessageItemProps {
+ id?: number
+ content?: React.ReactNode
+ type?: 'info' | 'success' | 'error' | 'warning'
+ timeout?: number
+ onRemove?: (id?: number) => void
+}
+
+const MessageItem = memo(
+ ({ id, content, type = 'success', timeout = 3000, onRemove }: MessageItemProps) => {
+ const [isHide, setIsHide] = useState()
+ const [isMouseOver, setIsMouseOver] = useState(false)
+
+ const iconElement = useMemo(() => {
+ switch (type) {
+ case 'info':
+ return
+ case 'success':
+ return
+ case 'error':
+ return
+ case 'warning':
+ return
+ default:
+ return
+ }
+ }, [type])
+
+ useEffect(() => {
+ setIsHide(false)
+ setTimeout(() => {
+ setIsHide(true)
+ }, timeout)
+ }, [timeout, isMouseOver])
+
+ useEffect(() => {
+ if (isHide && !isMouseOver && onRemove) {
+ onRemove(id)
+ }
+ }, [isHide, isMouseOver, onRemove, id])
+
+ const onMouseOver = () => {
+ setIsMouseOver(true)
+ }
+
+ const onMouseLeave = () => {
+ setIsMouseOver(false)
+ }
+
+ return (
+
+ {iconElement}
+ {content}
+
+ )
+ }
+)
+
+MessageItem.displayName = 'MessageItem'
+export default MessageItem
diff --git a/src/components/common/index.ts b/src/components/common/index.ts
index 0edc064cc..eaa33176c 100644
--- a/src/components/common/index.ts
+++ b/src/components/common/index.ts
@@ -1,4 +1,3 @@
-import { InputFiledInForm } from 'src/components/common/InputFiledInForm/InputFiledInForm';
export { default as ButtonCommon } from './ButtonCommon/ButtonCommon'
export { default as Layout } from './Layout/Layout'
export { default as CarouselCommon } from './CarouselCommon/CarouselCommon'
@@ -51,3 +50,6 @@ export { default as RecommendedRecipes} from './RecommendedRecipes/RecommendedRe
export { default as LayoutCheckout} from './LayoutCheckout/LayoutCheckout'
export { default as InputPasswordFiledInForm} from './InputPasswordFiledInForm/InputPasswordFiledInForm'
export { default as InputFiledInForm} from './InputFiledInForm/InputFiledInForm'
+export { default as MessageCommon} from './MessageCommon/MessageCommon'
+
+