diff --git a/packages/ui-elements/src/components/ToastBar/ProgressBar.js b/packages/ui-elements/src/components/ToastBar/ProgressBar.js new file mode 100644 index 0000000000..0700c40273 --- /dev/null +++ b/packages/ui-elements/src/components/ToastBar/ProgressBar.js @@ -0,0 +1,31 @@ +import React, { useEffect, useState } from 'react'; +import { Box } from '../Box'; +import useTheme from '../../hooks/useTheme'; +import { getProgressBarStyles } from './ToastBar.styles'; + +const ProgressBar = ({ color, time }) => { + const [progress, setProgress] = useState(0); + const { theme } = useTheme(); + const { mode } = useTheme(); + const styles = getProgressBarStyles(theme, mode, progress, color); + + useEffect(() => { + const intervalTime = 10; + + const interval = setInterval(() => { + setProgress((prev) => { + if (prev < 100) { + return prev + 1; + } + clearInterval(interval); + return prev; + }); + }, intervalTime); + + return () => clearInterval(interval); + }, [time]); + + return ; +}; + +export default ProgressBar; diff --git a/packages/ui-elements/src/components/ToastBar/ToastBar.js b/packages/ui-elements/src/components/ToastBar/ToastBar.js index 71ea53a9d8..dc9cdcaa94 100644 --- a/packages/ui-elements/src/components/ToastBar/ToastBar.js +++ b/packages/ui-elements/src/components/ToastBar/ToastBar.js @@ -7,14 +7,17 @@ import { Icon } from '../Icon'; import { ActionButton } from '../ActionButton'; import { getToastbarStyles } from './ToastBar.styles'; import useTheme from '../../hooks/useTheme'; +import ProgressBar from './ProgressBar'; +import { darken, lighten } from '../../lib'; const ToastBar = ({ toast, onClose }) => { const { type, message, time = 2000 } = toast; const toastRef = useRef(); const { theme } = useTheme(); + const { mode } = useTheme(); const { classNames, styleOverrides } = useComponentOverrides('ToastBar'); - const styles = getToastbarStyles(theme); + const styles = getToastbarStyles(theme, mode); const { iconName, bgColor, color } = useMemo(() => { const color = type === 'error' @@ -45,17 +48,29 @@ const ToastBar = ({ toast, onClose }) => { setTimeout(onClose, time); }, [onClose, time]); + let progressBarBgColor = darken(bgColor, 0.5); + if (mode === 'dark') { + progressBarBgColor = lighten(bgColor, 0.85); + } + return ( - - - {message} - - + <> + + + + {message} + + + + + + + ); }; diff --git a/packages/ui-elements/src/components/ToastBar/ToastBar.styles.js b/packages/ui-elements/src/components/ToastBar/ToastBar.styles.js index cff7dba271..a90eea4446 100644 --- a/packages/ui-elements/src/components/ToastBar/ToastBar.styles.js +++ b/packages/ui-elements/src/components/ToastBar/ToastBar.styles.js @@ -15,14 +15,14 @@ const animation = keyframes` } `; -export const getToastbarStyles = (theme) => { +export const getToastbarStyles = (theme, mode) => { const styles = { toastbar: (color, bgColor, time) => css` display: flex; - flex-direction: row; + flex-direction: column; gap: 1em; - align-items: center; - justify-content: space-between; + align-items: flex-start; + justify-content: flex-start; width: fit-content; max-width: 20rem; color: ${color}; @@ -31,19 +31,51 @@ export const getToastbarStyles = (theme) => { padding: 0.75em 1em; z-index: ${theme.zIndex?.toastbar || 1600}; animation: ${animation} ${time}ms ease-in-out forwards; + position: relative; + overflow: hidden; + `, + content: css` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + `, + progressBarContainer: css` + position: absolute; + bottom: 0; + left: 0; + height: 5px; + width: 100%; + background-color: ${mode === 'dark' ? theme.colors.foreground : null}; + clip-path: inset(0 0 0 0 round ${theme.radius}); `, }; return styles; }; -export const getToastBarContainerStyles = (theme) => { +export const getToastBarContainerStyles = (theme, mode) => { const styles = { container: css` position: absolute; z-index: ${theme.zIndex?.toastbar || 1600}; border-radius: ${theme.radius}; animation: ${animation} ${2000}ms ease-in-out forwards; + box-shadow: ${mode === 'light' + ? '0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)' + : null}; + `, + }; + return styles; +}; + +export const getProgressBarStyles = (theme, mode, progress, color) => { + const styles = { + progressbar: css` + width: ${progress}%; + height: 100%; + background-color: ${color}; + transition: width 0.02s linear; `, }; return styles; diff --git a/packages/ui-elements/src/components/ToastBar/ToastContainer.js b/packages/ui-elements/src/components/ToastBar/ToastContainer.js index d417b6d67f..cb489e2b93 100644 --- a/packages/ui-elements/src/components/ToastBar/ToastContainer.js +++ b/packages/ui-elements/src/components/ToastBar/ToastContainer.js @@ -7,7 +7,8 @@ import { getToastBarContainerStyles } from './ToastBar.styles'; const ToastContainer = () => { const { theme } = useTheme(); - const styles = getToastBarContainerStyles(theme); + const { mode } = useTheme(); + const styles = getToastBarContainerStyles(theme, mode); const { position, toasts, setToasts } = useContext(ToastContext); const positionStyle = useMemo(() => { const positions = position.split(/\s+/);