Yann
test
f23825d
raw
history blame
2.79 kB
import { keyframes } from "@emotion/react"
import styled from "@emotion/styled"
import * as Portal from "@radix-ui/react-portal"
import Error from "mdi-react/AlertCircleIcon"
import Warning from "mdi-react/AlertIcon"
import CheckCircle from "mdi-react/CheckCircleIcon"
import Info from "mdi-react/InformationIcon"
import { FC, useEffect, useState } from "react"
import { Theme } from "../common/theme/Theme"
import { useTheme } from "../main/hooks/useTheme"
import { ToastSeverity } from "../main/hooks/useToast"
export interface ToastProps {
message: string
severity: ToastSeverity
onExited: () => void
}
const contentShow = keyframes`
from {
opacity: 0;
transform: translate(0, 0.5rem) scale(0.96);
}
to {
opacity: 1;
transform: translate(0, 0) scale(1);
}
`
const contentHide = keyframes`
from {
opacity: 1;
transform: translate(0, 0) scale(1);
}
to {
opacity: 0;
transform: translate(0, 0.5rem) scale(0.96);
}
`
const Root = styled(Portal.Root)`
position: fixed;
bottom: 2rem;
left: 0;
right: 0;
display: flex;
`
const Content = styled.div`
margin: 0 auto;
background: ${({ theme }) => theme.secondaryBackgroundColor};
padding: 1rem;
border-radius: 0.5rem;
font-size: 0.8rem;
box-shadow: 0 0.5rem 3rem ${({ theme }) => theme.shadowColor};
display: flex;
align-items: center;
animation: ${({ show }: { show: boolean }) =>
show ? contentShow : contentHide}
500ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
`
const SeverityIcon: FC<{ severity: ToastSeverity }> = ({ severity }) => {
const theme = useTheme()
const fill = colorForSeverity(severity, theme)
switch (severity) {
case "error":
return <Error style={{ fill }} />
case "info":
return <Info style={{ fill }} />
case "success":
return <CheckCircle style={{ fill }} />
case "warning":
return <Warning style={{ fill }} />
}
}
const exitDuration = 5000
export const Toast: FC<ToastProps> = ({ message, severity, onExited }) => {
const [show, setShow] = useState(true)
useEffect(() => {
const timeout = setTimeout(() => setShow(false), exitDuration - 500)
const timeout2 = setTimeout(onExited, exitDuration)
return () => {
clearTimeout(timeout)
clearTimeout(timeout2)
}
})
return (
<Root>
<Content show={show}>
<SeverityIcon severity={severity} />
<div style={{ width: "0.5rem" }} />
{message}
</Content>
</Root>
)
}
const colorForSeverity = (severity: ToastSeverity, theme: Theme) => {
switch (severity) {
case "error":
return theme.redColor
case "info":
return theme.textColor
case "success":
return theme.greenColor
case "warning":
return theme.yellowColor
}
}