Skip to canvas
Proton Design System
/
Introduction
Changelog
Colors
Icons
Layers Management
Responsive
Sass Css Variables
Typography
Alert
Autocomplete
Badge
ButtonGroup
Checkbox
Collapsible
Copy
CountrySelect
DateInput
Details
Dropdown
Dropzone
EllipsisLoader
Errors
Icon
InputButton
InputField
InputFieldStacked
LabelStack
Logo
Meter
MiddleEllipsis
Modal
NotificationSkip to canvas
Price
Progress
Promotion Button
QuickSettings
Radio
Scale
Select
Spotlight
Table
Tabs
Toggle
TopBanner
TotpInput
VideoInstructions
Avatar
Banner
Button
Card
CircleLoader
DashboardCard
Donut
Href
InlineLinkButton
Input
Kbd
NotificationDot
Pill
ProtonLoader
Scroll
Slider
Stepper
UserAvatar
VerticalSteps
Vr
Border
Border Radius
Colors
Columns
Cursor
Divide
ExpandClickArea
Gap
HidingDisablingContent
InteractiveFocusHelper
Lists
Margin
Opacity
OpacityOnHover
Padding
Position
Print
Ratio Container
Responsive
Scroll
Shadow
Sizing
Transforms
Typography
  1. Recently opened
  2. Notificationcomponents
  3. Back to componentsESC
  4. Clear history
Skip to sidebar
1import type { ChangeEvent, SetStateAction } from 'react'; 2import { useState } from 'react'; 3 4import { Button, CircleLoader } from '@proton/atoms'; 5import type { CreateNotificationOptions, CustomNotificationProps } from '@proton/components'; 6import { Checkbox, InputFieldTwo, NotificationButton, RadioGroup, useNotifications } from '@proton/components'; 7 8import { getTitle } from '../../helpers/title'; 9import mdx from './Notification.mdx'; 10 11export default { 12 title: getTitle(__filename, false), 13 parameters: { 14 docs: { 15 page: mdx, 16 }, 17 }, 18}; 19 20const ExpandableNotification = () => { 21 const [open, setOpen] = useState(false); 22 return ( 23 <> 24 <span>{!open ? 'Expand' : 'Collapse'} me</span> 25 {open && <div style={{ height: 100, width: 100 }}></div>} 26 <NotificationButton onClick={() => setOpen(!open)}>{!open ? 'Expand' : 'Collapse'}</NotificationButton> 27 </> 28 ); 29}; 30 31const CloseableNotification = ({ onClose }: CustomNotificationProps) => { 32 return ( 33 <> 34 <span>I've done the thing</span> 35 <NotificationButton onClick={onClose}>Undo</NotificationButton> 36 </> 37 ); 38}; 39 40const WarningNotification = ({ onClose }: CustomNotificationProps) => { 41 return ( 42 <> 43 <span>Oh no, not again</span> 44 <NotificationButton onClick={onClose}>Edit</NotificationButton> 45 </> 46 ); 47}; 48
49export const Basic = () => { 50 const { createNotification } = useNotifications(); 51 52 const handleClick = (options: CreateNotificationOptions) => () => { 53 createNotification(options); 54 }; 55 56 const types = ['info', 'warning'] as const; 57 58 const BuildYourOwn = () => { 59 const [byoExpiration, setByoExpiration] = useState(5000); 60 const [byoText, setByoText] = useState('Lorem ipsum'); 61 const [byoType, setByoType] = useState<(typeof types)[number]>(types[0]); 62 const [byoCloseButton, setCloseButton] = useState(true); 63 64 const [byoButtonShow, setByoButtonShow] = useState(false); 65 const [byoButtonText, setByoButtonText] = useState('Undo'); 66 67 const [byoLoader, setByoLoader] = useState(false); 68 69 const ByoContent = ({ onClose }: CustomNotificationProps) => { 70 return ( 71 <> 72 <span>{byoText}</span> 73 {byoButtonShow && <NotificationButton onClick={onClose}>{byoButtonText}</NotificationButton>} 74 {byoLoader && <CircleLoader />} 75 </> 76 ); 77 }; 78 79 return ( 80 <div className="block"> 81 <form> 82 <div className="flex flex-column gap-4 mb-4"> 83 <InputFieldTwo 84 name="content" 85 id="content" 86 label="Content" 87 value={byoText} 88 onChange={(e: { target: { value: SetStateAction<string> } }) => setByoText(e.target.value)} 89 /> 90 91 <div> 92 <strong className="block mb-4">Type</strong> 93 <RadioGroup 94 name="type" 95 onChange={(v) => setByoType(v)} 96 value={byoType} 97 options={types.map((type) => ({ value: type, label: type }))} 98 /> 99 </div> 100 101 <Checkbox 102 id="closebutton" 103 checked={byoCloseButton} 104 onChange={() => { 105 setCloseButton(!byoCloseButton); 106 setByoLoader(false); 107 }} 108 > 109 Show Close Button 110 </Checkbox> 111 112 <Checkbox 113 id="loader" 114 checked={byoLoader} 115 onChange={() => { 116 setByoLoader(!byoLoader); 117 setCloseButton(false); 118 }} 119 > 120 Show Loader 121 </Checkbox> 122 123 <Checkbox 124 id="byoButtonShow" 125 checked={byoButtonShow} 126 onChange={() => setByoButtonShow(!byoButtonShow)} 127 > 128 Show Button 129 </Checkbox> 130 <InputFieldTwo 131 name="byoButtonText" 132 id="byoButtonText" 133 label="Button Text" 134 className="w-custom" 135 style={{ '--w-custom': '10em' }} 136 value={byoButtonText} 137 onChange={(e: { target: { value: SetStateAction<string> } }) => 138 setByoButtonText(e.target.value) 139 } 140 /> 141 142 <InputFieldTwo 143 name="expiration" 144 id="expiration" 145 label="Expiration" 146 className="w-custom" 147 style={{ '--w-custom': '10em' }} 148 value={byoExpiration} 149 type="number" 150 onChange={(event: ChangeEvent<HTMLInputElement>) => 151 setByoExpiration(Number(event.target.value)) 152 } 153 /> 154 </div> 155 156 <Button 157 onClick={handleClick({ 158 key: byoText, 159 type: byoType, 160 text: <ByoContent />, 161 showCloseButton: byoCloseButton, 162 expiration: byoExpiration, 163 })} 164 className="mr-4 mb-4" 165 > 166 Trigger 167 </Button> 168 </form> 169 </div> 170 ); 171 }; 172 173 return ( 174 <div> 175 <h4 className="mb-4">Presets</h4> 176 <Button 177 color="success" 178 onClick={handleClick({ 179 type: 'success', 180 text: 'You did it', 181 })} 182 className="mr-4 mb-4" 183 > 184 Default notification 185 </Button> 186 <Button 187 color="info" 188 onClick={handleClick({ key: 'close', type: 'info', text: <CloseableNotification /> })} 189 className="mr-4 mb-4" 190 > 191 Default with action 192 </Button> 193 <Button 194 color="info" 195 onClick={handleClick({ type: 'info', text: 'whoop', showCloseButton: false })} 196 className="mr-4 mb-4" 197 > 198 Default without close button 199 </Button> 200 <Button 201 color="info" 202 onClick={handleClick({ 203 key: 'close2', 204 type: 'info', 205 text: <CloseableNotification />, 206 showCloseButton: false, 207 })} 208 className="mr-4 mb-4" 209 > 210 Default without close button but with an action 211 </Button> 212 <Button 213 color="success" 214 onClick={handleClick({ 215 key: 'spinner', 216 type: 'success', 217 showCloseButton: false, 218 text: ( 219 <> 220 Doing the thing... <CircleLoader /> 221 </> 222 ), 223 })} 224 className="mr-4 mb-4" 225 > 226 Default with spinner 227 </Button> 228 229 <Button 230 color="warning" 231 onClick={handleClick({ 232 type: 'warning', 233 text: 'Uh oh', 234 })} 235 className="mr-4 mb-4" 236 > 237 Default warning 238 </Button> 239 <Button 240 color="warning" 241 onClick={handleClick({ key: 'warning', type: 'warning', text: <WarningNotification /> })} 242 className="mr-4 mb-4" 243 > 244 Warning with action 245 </Button> 246 <Button 247 color="warning" 248 onClick={handleClick({ key: 'warning2', type: 'warning', text: 'Dammit', showCloseButton: false })} 249 className="mr-4 mb-4" 250 > 251 Warning without close button 252 </Button> 253 <Button 254 color="warning" 255 onClick={handleClick({ 256 key: 'warning3', 257 type: 'warning', 258 text: <WarningNotification />, 259 showCloseButton: false, 260 })} 261 className="mr-4 mb-4" 262 > 263 Warning without close button but with an action 264 </Button> 265 <Button 266 color="info" 267 onClick={handleClick({ 268 key: 'expandable', 269 type: 'info', 270 text: <ExpandableNotification />, 271 expiration: -1, 272 })} 273 className="mr-4 mb-4" 274 > 275 Expandable notification 276 </Button> 277 278 <hr /> 279 <h4 className="mb-4">Build your own</h4> 280 <BuildYourOwn /> 281 </div> 282 ); 283};
284 285export const Expiration = () => { 286 const { createNotification } = useNotifications(); 287 288 const handleClick = (options: CreateNotificationOptions) => () => { 289 createNotification(options); 290 }; 291 292 return ( 293 <div> 294 <Button 295 onClick={handleClick({ type: 'info', text: 'I expire after 5 seconds!', expiration: 3000 })} 296 className="mr-4 mb-4" 297 > 298 Expires after 3 seconds 299 </Button> 300 <Button 301 onClick={handleClick({ type: 'info', text: 'I expire after 500 milliseconds!', expiration: 500 })} 302 className="mr-4 mb-4" 303 > 304 Expires after 500 milliseconds 305 </Button> 306 </div> 307 ); 308};