-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Responsive Toaster Notification Feature
Responsiveness: Utilizing the vw units, the toaster's position scales based on the viewport width, ensuring it is always optimally placed for a variety of screen sizes. Configurable Duration: Allows users to set the duration for which the toaster notification is visible. Closable Option: Provides the option to either allow or prevent users from manually closing the notification. Styling & Themes: Integrated with the existing theme and leveraged the severity-based color coding from the Alert component to ensure consistency in design and user experience. Positioning: Positioned fixed at the bottom right by default, ensuring minimal obstruction to the user's workflow. Severity Levels: Supports different severity levels such as 'error', 'warning', 'info', and 'success' to provide contextually appropriate feedback.
- Loading branch information
1 parent
42f6dfb
commit d102691
Showing
3 changed files
with
79 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React, { useEffect, useState } from 'react' | ||
import Alert, { AlertProps } from '../Alert' | ||
|
||
export type ToasterProps = { | ||
duration?: number | null | ||
closable?: boolean | ||
} & Omit<AlertProps, 'header'> // Omit the 'header' prop from AlertProps | ||
|
||
const Toaster = ({ duration, closable = true, ...props }: ToasterProps) => { | ||
const [isVisible, setIsVisible] = useState(true) | ||
|
||
useEffect(() => { | ||
if (typeof duration === 'number') { | ||
const timer = setTimeout(() => { | ||
setIsVisible(false) | ||
}, duration) | ||
|
||
return () => { | ||
clearTimeout(timer) | ||
} | ||
} | ||
}, [duration]) | ||
|
||
if (!isVisible) { | ||
return null | ||
} | ||
|
||
return <Alert {...props} closable={closable} /> // Explicitly set the 'header' prop to null | ||
} | ||
|
||
export default Toaster |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react' | ||
import { StoryFn, Meta } from '@storybook/react' | ||
import Toaster, { ToasterProps } from './index' | ||
|
||
export default { | ||
title: 'Toaster', | ||
component: Toaster, | ||
args: { | ||
children: 'This is a toaster message', | ||
severity: 'info', | ||
showIcon: true, | ||
closable: true | ||
} | ||
} as Meta | ||
|
||
export const Default: StoryFn<ToasterProps> = (args) => <Toaster {...args} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import styled, { css, DefaultTheme } from 'styled-components' | ||
import { AlertProps } from '../Alert' | ||
|
||
const severityShape = { | ||
error: (theme: DefaultTheme) => css` | ||
background-color: ${theme.colors.base.error}1f; | ||
`, | ||
warning: (theme: DefaultTheme) => css` | ||
background-color: ${theme.colors.base.warning}1f; | ||
`, | ||
info: (theme: DefaultTheme) => css` | ||
background-color: ${theme.colors.base.info}1f; | ||
`, | ||
success: (theme: DefaultTheme) => css` | ||
background-color: ${theme.colors.base.success}1f; | ||
` | ||
} | ||
|
||
export const ToasterWrapper = styled.div<Pick<AlertProps, 'severity'>>` | ||
position: fixed; | ||
bottom: 2vw; | ||
right: 2vw; | ||
z-index: 1000; | ||
${({ theme, severity = 'info' }) => css` | ||
animation-fill-mode: forwards; | ||
border-radius: ${theme.border.radius}; | ||
position: relative; | ||
transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; | ||
${!!severity && severityShape[severity](theme)} | ||
`} | ||
` |