@@ -5,17 +5,24 @@ import * as colors from "@material-ui/core/colors"
55import Collapse from "@material-ui/core/Collapse"
66import Fade from "@material-ui/core/Fade"
77import classNames from "classnames"
8+ import {
9+ CheckCircle as SuccessIcon ,
10+ Close as CloseIcon ,
11+ Error as ErrorIcon ,
12+ Info as InfoIcon ,
13+ Warning as WarningIcon ,
14+ } from "@material-ui/icons"
15+ import Typography from "@material-ui/core/Typography"
16+ import IconButton from "@material-ui/core/IconButton"
817
918const useStyles = makeStyles ( {
1019 root : {
1120 position : "fixed" ,
1221 display : "flex" ,
1322 flexDirection : "column" ,
14- bottom : 0 ,
15- left : 0 ,
16- right : 0 ,
23+ bottom : 16 ,
24+ right : 16 ,
1725 alignItems : "flex-start" ,
18- pointerEvents : "none" ,
1926 } ,
2027 msgBox : {
2128 display : "flex" ,
@@ -32,6 +39,35 @@ const useStyles = makeStyles({
3239 backgroundColor : colors . red [ 700 ] ,
3340 } ,
3441 } ,
42+ notificationPaper : {
43+ display : "flex" ,
44+ borderRadius : 10 ,
45+ padding : 12 ,
46+ boxShadow : `0 2.8px 2.2px rgba(0, 0, 0, 0.034),
47+ 0 6.7px 5.3px rgba(0, 0, 0, 0.048);` ,
48+ backgroundColor : "#FFF" ,
49+ margin : 6 ,
50+ } ,
51+ icon : {
52+ borderLeft : `3px solid ${ colors . blue [ 700 ] } ` ,
53+ color : colors . blue [ 700 ] ,
54+ "&.warning" : {
55+ borderLeft : `3px solid ${ colors . orange [ 700 ] } ` ,
56+ color : colors . orange [ 700 ] ,
57+ } ,
58+ "&.error" : {
59+ borderLeft : `3px solid ${ colors . red [ 700 ] } ` ,
60+ color : colors . red [ 700 ] ,
61+ } ,
62+ "&.info" : {
63+ borderLeft : `3px solid ${ colors . blue [ 700 ] } ` ,
64+ color : colors . blue [ 700 ] ,
65+ } ,
66+ "&.success" : {
67+ borderLeft : `3px solid ${ colors . green [ 700 ] } ` ,
68+ color : colors . green [ 700 ] ,
69+ } ,
70+ } ,
3571} )
3672
3773const REFRESH_INTERVAL = 100
@@ -70,6 +106,13 @@ export const ToastProvider = ({ children }) => {
70106 life : msg . life - REFRESH_INTERVAL ,
71107 } ) )
72108 . filter ( ( msg ) => msg . life > 0 )
109+ } else if ( action . type === "remove" ) {
110+ return state
111+ . map ( ( msg ) => ( {
112+ ...msg ,
113+ life : msg . life - REFRESH_INTERVAL ,
114+ } ) )
115+ . filter ( ( msg ) => msg . id !== action . id )
73116 }
74117 return state
75118 } , [ ] )
@@ -95,13 +138,59 @@ export const ToastProvider = ({ children }) => {
95138 { toasts . map ( ( msg ) => (
96139 < Collapse key = { msg . id } in = { msg . life < msg . fullLife } >
97140 < Fade in = { msg . life > 600 } >
98- < div className = { classNames ( c . msgBox , msg . type ) } >
99- { msg . message }
100- </ div >
141+ < Notification
142+ type = { msg . type }
143+ message = { msg . message }
144+ onClose = { ( ) => changeToasts ( { type : "remove" , id : msg . id } ) }
145+ />
101146 </ Fade >
102147 </ Collapse >
103148 ) ) }
104149 </ div >
105150 </ >
106151 )
107152}
153+
154+ export const Notification = ( { type, message, onClose } ) => {
155+ const classes = useStyles ( )
156+ let Icon = null
157+ switch ( type ) {
158+ case "success" :
159+ Icon = SuccessIcon
160+ break
161+ case "warning" :
162+ Icon = WarningIcon
163+ break
164+ case "error" :
165+ Icon = ErrorIcon
166+ break
167+ default :
168+ Icon = InfoIcon
169+ }
170+ return (
171+ < paper
172+ className = { classes . notificationPaper }
173+ style = { { position : "relative" } }
174+ >
175+ < div className = { classNames ( classes . icon , type ) } >
176+ < Icon fontSize = "large" style = { { padding : 12 } } />
177+ </ div >
178+ < div style = { { margin : "auto 0" } } >
179+ < Typography variant = "body1" > { message } </ Typography >
180+ </ div >
181+ < div
182+ style = { {
183+ position : "absolute" ,
184+ top : - 10 ,
185+ right : - 10 ,
186+ backgroundColor : "#FFF" ,
187+ borderRadius : 100 ,
188+ } }
189+ >
190+ < IconButton color = "action" size = "small" >
191+ < CloseIcon onClick = { onClose } />
192+ </ IconButton >
193+ </ div >
194+ </ paper >
195+ )
196+ }
0 commit comments