Skip to content

Commit

Permalink
Implement Responsive Toaster Notification Feature
Browse files Browse the repository at this point in the history
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
KushalNerella07 committed Oct 31, 2023
1 parent 42f6dfb commit d102691
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/packages/Toaster/index.tsx
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
16 changes: 16 additions & 0 deletions src/packages/Toaster/stories.tsx
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} />
32 changes: 32 additions & 0 deletions src/packages/Toaster/styles.ts
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)}
`}
`

0 comments on commit d102691

Please sign in to comment.