mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
🎨 styles: message common
:%s
This commit is contained in:
@@ -1,19 +1,35 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { Layout, MessageCommon } from 'src/components/common'
|
||||||
import {
|
import { MessageItemProps } from 'src/components/common/MessageCommon/MessageItem/MessageItem'
|
||||||
ButtonCommon, Layout
|
|
||||||
} from 'src/components/common'
|
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() {
|
export default function Test() {
|
||||||
const [isLoading, setisLoading] = useState(false)
|
|
||||||
useEffect(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
setisLoading(true)
|
|
||||||
}, 3000)
|
|
||||||
}, [])
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonCommon loading={isLoading}>Back to home</ButtonCommon>
|
<MessageCommon messages={data} />
|
||||||
<ButtonCommon type='light' loading={isLoading}>Back to home</ButtonCommon>
|
{/* <MessageCommon type='error'>Create account successfully</MessageCommon>
|
||||||
<ButtonCommon type='ghost' loading={isLoading}>Back to home</ButtonCommon>
|
<MessageCommon type='info'>Create account successfully</MessageCommon>
|
||||||
|
<MessageCommon type='warning'>Create account successfully</MessageCommon> */}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -41,4 +41,5 @@ const Banner = memo(({ data }: Props) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Banner.displayName = 'Banner'
|
||||||
export default Banner
|
export default Banner
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
.messageCommon {
|
||||||
|
@apply fixed;
|
||||||
|
top: 2.4rem;
|
||||||
|
left: 50%;
|
||||||
|
z-index: 20000;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
26
src/components/common/MessageCommon/MessageCommon.tsx
Normal file
26
src/components/common/MessageCommon/MessageCommon.tsx
Normal file
@@ -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 (
|
||||||
|
<div className={s.messageCommon}>
|
||||||
|
{messages.map((item) => (
|
||||||
|
<MessageItem
|
||||||
|
key={item.id}
|
||||||
|
id={item.id}
|
||||||
|
content={item.content}
|
||||||
|
onRemove={onRemove}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
MessageCommon.displayName = 'MessageCommon'
|
||||||
|
export default MessageCommon
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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<boolean>()
|
||||||
|
const [isMouseOver, setIsMouseOver] = useState(false)
|
||||||
|
|
||||||
|
const iconElement = useMemo(() => {
|
||||||
|
switch (type) {
|
||||||
|
case 'info':
|
||||||
|
return <IconInfo />
|
||||||
|
case 'success':
|
||||||
|
return <IconCheck />
|
||||||
|
case 'error':
|
||||||
|
return <IconError />
|
||||||
|
case 'warning':
|
||||||
|
return <IconError />
|
||||||
|
default:
|
||||||
|
return <IconInfo />
|
||||||
|
}
|
||||||
|
}, [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 (
|
||||||
|
<div
|
||||||
|
className={classNames(s.messageItem, s[type], {
|
||||||
|
[s.hide]: isHide && !isMouseOver,
|
||||||
|
})}
|
||||||
|
onMouseOver={onMouseOver}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
>
|
||||||
|
<span className={s.icon}>{iconElement}</span>
|
||||||
|
<span className={s.content}>{content}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
MessageItem.displayName = 'MessageItem'
|
||||||
|
export default MessageItem
|
@@ -1,4 +1,3 @@
|
|||||||
import { InputFiledInForm } from 'src/components/common/InputFiledInForm/InputFiledInForm';
|
|
||||||
export { default as ButtonCommon } from './ButtonCommon/ButtonCommon'
|
export { default as ButtonCommon } from './ButtonCommon/ButtonCommon'
|
||||||
export { default as Layout } from './Layout/Layout'
|
export { default as Layout } from './Layout/Layout'
|
||||||
export { default as CarouselCommon } from './CarouselCommon/CarouselCommon'
|
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 LayoutCheckout} from './LayoutCheckout/LayoutCheckout'
|
||||||
export { default as InputPasswordFiledInForm} from './InputPasswordFiledInForm/InputPasswordFiledInForm'
|
export { default as InputPasswordFiledInForm} from './InputPasswordFiledInForm/InputPasswordFiledInForm'
|
||||||
export { default as InputFiledInForm} from './InputFiledInForm/InputFiledInForm'
|
export { default as InputFiledInForm} from './InputFiledInForm/InputFiledInForm'
|
||||||
|
export { default as MessageCommon} from './MessageCommon/MessageCommon'
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user