@delightui/components 0.1.105 → 0.1.107

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +104 -1
  2. package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
  3. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  4. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  5. package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  6. package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  7. package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
  8. package/dist/cjs/components/molecules/index.d.ts +2 -0
  9. package/dist/cjs/library.css +19 -6
  10. package/dist/cjs/library.js +3 -3
  11. package/dist/cjs/library.js.map +1 -1
  12. package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
  13. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  14. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  15. package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  16. package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  17. package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
  18. package/dist/esm/components/molecules/index.d.ts +2 -0
  19. package/dist/esm/library.css +19 -6
  20. package/dist/esm/library.js +3 -3
  21. package/dist/esm/library.js.map +1 -1
  22. package/dist/index.d.ts +108 -2
  23. package/docs/README.md +264 -0
  24. package/docs/components/atoms/ActionImage.md +119 -0
  25. package/docs/components/atoms/Button.md +197 -0
  26. package/docs/components/atoms/Checkbox.md +299 -0
  27. package/docs/components/atoms/CheckboxItem.md +314 -0
  28. package/docs/components/atoms/Chip.md +380 -0
  29. package/docs/components/atoms/CustomToggle.md +270 -0
  30. package/docs/components/atoms/Icon.md +365 -0
  31. package/docs/components/atoms/IconButton.md +407 -0
  32. package/docs/components/atoms/Image.md +448 -0
  33. package/docs/components/atoms/Input.md +430 -0
  34. package/docs/components/atoms/ListItem.md +502 -0
  35. package/docs/components/atoms/Password.md +472 -0
  36. package/docs/components/atoms/RadioButton.md +614 -0
  37. package/docs/components/atoms/RadioButtonItem.md +588 -0
  38. package/docs/components/atoms/ResponsiveComponent.md +612 -0
  39. package/docs/components/atoms/SelectListItem.md +609 -0
  40. package/docs/components/atoms/Slider.md +605 -0
  41. package/docs/components/atoms/Spinner.md +605 -0
  42. package/docs/components/atoms/Text.md +463 -0
  43. package/docs/components/atoms/TextArea.md +670 -0
  44. package/docs/components/atoms/ToastNotification.md +668 -0
  45. package/docs/components/atoms/Toggle.md +737 -0
  46. package/docs/components/atoms/ToggleButton.md +751 -0
  47. package/docs/components/atoms/Tooltip.md +391 -0
  48. package/docs/components/molecules/Accordion.md +440 -0
  49. package/docs/components/molecules/AccordionGroup.md +547 -0
  50. package/docs/components/molecules/ActionCard.md +546 -0
  51. package/docs/components/molecules/Breadcrumb.md +403 -0
  52. package/docs/components/molecules/Breadcrumbs.md +485 -0
  53. package/docs/components/molecules/ButtonGroup.md +383 -0
  54. package/docs/components/molecules/Card.md +298 -0
  55. package/docs/components/molecules/ChipInput.md +646 -0
  56. package/docs/components/molecules/ContextMenu.md +768 -0
  57. package/docs/components/molecules/CustomTimeSelector.md +116 -0
  58. package/docs/components/molecules/DatePicker.md +516 -0
  59. package/docs/components/molecules/DateTimeSelector.md +166 -0
  60. package/docs/components/molecules/FormField.md +312 -0
  61. package/docs/components/molecules/Grid.md +577 -0
  62. package/docs/components/molecules/GridItem.md +834 -0
  63. package/docs/components/molecules/GridList.md +244 -0
  64. package/docs/components/molecules/List.md +485 -0
  65. package/docs/components/molecules/Modal.md +470 -0
  66. package/docs/components/molecules/ModalFooter.md +702 -0
  67. package/docs/components/molecules/ModalHeader.md +756 -0
  68. package/docs/components/molecules/ModalProvider.md +205 -0
  69. package/docs/components/molecules/Nav.md +530 -0
  70. package/docs/components/molecules/NavItem.md +572 -0
  71. package/docs/components/molecules/NavLink.md +499 -0
  72. package/docs/components/molecules/Option.md +521 -0
  73. package/docs/components/molecules/Pagination.md +592 -0
  74. package/docs/components/molecules/PaginationNumberField.md +722 -0
  75. package/docs/components/molecules/Popover.md +516 -0
  76. package/docs/components/molecules/ProgressBar.md +624 -0
  77. package/docs/components/molecules/RadioGroup.md +831 -0
  78. package/docs/components/molecules/RepeaterList.md +185 -0
  79. package/docs/components/molecules/Select.md +402 -0
  80. package/docs/components/molecules/SortableTrigger.md +82 -0
  81. package/docs/components/molecules/useModal.md +379 -0
  82. package/docs/components/organisms/Dropzone.md +346 -0
  83. package/docs/components/organisms/DropzoneClear.md +135 -0
  84. package/docs/components/organisms/DropzoneContent.md +216 -0
  85. package/docs/components/organisms/DropzoneFilename.md +191 -0
  86. package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
  87. package/docs/components/organisms/DropzoneTrigger.md +209 -0
  88. package/docs/components/organisms/Form.md +533 -0
  89. package/docs/components/organisms/SlideOutPanel.md +662 -0
  90. package/docs/components/organisms/TabContent.md +902 -0
  91. package/docs/components/organisms/TabItem.md +1091 -0
  92. package/docs/components/organisms/Table.md +611 -0
  93. package/docs/components/organisms/TableBody.md +679 -0
  94. package/docs/components/organisms/TableCell.md +482 -0
  95. package/docs/components/organisms/TableHeader.md +513 -0
  96. package/docs/components/organisms/TableHeaderCell.md +661 -0
  97. package/docs/components/organisms/TableRow.md +715 -0
  98. package/docs/components/organisms/Tabs.md +1330 -0
  99. package/docs/components/utils/ConditionalView.md +568 -0
  100. package/docs/components/utils/RenderStateView.md +726 -0
  101. package/docs/components/utils/WrapTextNodes.md +614 -0
  102. package/package.json +3 -2
@@ -0,0 +1,668 @@
1
+ # ToastNotification
2
+
3
+ A versatile notification component that displays temporary messages to users. It supports different styles (neutral, success, error), customizable icons, dismissible behavior, and auto-dismiss functionality. Toast notifications are ideal for providing feedback about user actions and system status updates.
4
+
5
+ ## Aliases
6
+
7
+ - ToastNotification
8
+ - Toast
9
+ - Notification
10
+
11
+ ## Props Breakdown
12
+
13
+ **Extends:** `HTMLAttributes<HTMLDivElement>` (excluding `style`)
14
+
15
+ | Prop | Type | Default | Required | Description |
16
+ |------|------|---------|----------|-------------|
17
+ | `style` | `'Neutral' \| 'Error' \| 'Success'` | `'Neutral'` | No | Style of the toast notification |
18
+ | `isDismissable` | `boolean` | `true` | No | Determines if the toast notification is dismissible |
19
+ | `leadingIcon` | `ReactNode` | `undefined` | No | Icon displayed before the message content |
20
+ | `trailingIcon` | `ReactNode` | `undefined` | No | Icon displayed after the message content |
21
+ | `closeIcon` | `ReactNode` | `undefined` | No | Close button/icon for dismissible toast notifications |
22
+ | `removeToast` | `(event?: MouseEvent<HTMLButtonElement>) => void` | `undefined` | No | Click event handler for the close action |
23
+ | `duration` | `number` | `undefined` | No | Duration before the toast auto-closes (in milliseconds) |
24
+ | `className` | `string` | `undefined` | No | Additional class for styling |
25
+ | `children` | `ReactNode` | `undefined` | No | The content of the toast notification |
26
+
27
+ Plus all standard HTML div attributes (id, title, aria-*, data-*, etc.).
28
+
29
+ ## Examples
30
+
31
+ ### Basic Toast Notifications
32
+
33
+ ```tsx
34
+ import { ToastNotification, Button } from '@delightui/components';
35
+
36
+ function BasicToastExample() {
37
+ const [toasts, setToasts] = useState<Array<{id: number, type: string, message: string}>>([]);
38
+
39
+ const addToast = (type: 'Neutral' | 'Success' | 'Error', message: string) => {
40
+ const newToast = {
41
+ id: Date.now(),
42
+ type,
43
+ message
44
+ };
45
+ setToasts(prev => [...prev, newToast]);
46
+ };
47
+
48
+ const removeToast = (id: number) => {
49
+ setToasts(prev => prev.filter(toast => toast.id !== id));
50
+ };
51
+
52
+ return (
53
+ <div>
54
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
55
+ <Button onClick={() => addToast('Success', 'Operation completed successfully!')}>
56
+ Success Toast
57
+ </Button>
58
+ <Button onClick={() => addToast('Error', 'An error occurred while processing.')}>
59
+ Error Toast
60
+ </Button>
61
+ <Button onClick={() => addToast('Neutral', 'This is a neutral notification.')}>
62
+ Neutral Toast
63
+ </Button>
64
+ </div>
65
+
66
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
67
+ {toasts.map((toast) => (
68
+ <ToastNotification
69
+ key={toast.id}
70
+ style={toast.type as any}
71
+ removeToast={() => removeToast(toast.id)}
72
+ style={{ marginBottom: '8px' }}
73
+ >
74
+ {toast.message}
75
+ </ToastNotification>
76
+ ))}
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ### Toast with Icons
84
+
85
+ ```tsx
86
+ import { ToastNotification, Icon, Button } from '@delightui/components';
87
+
88
+ function ToastWithIconsExample() {
89
+ const [toasts, setToasts] = useState<Array<{id: number, style: string, message: string, icon: string}>>([]);
90
+
91
+ const addToast = (style: 'Neutral' | 'Success' | 'Error', message: string, icon: string) => {
92
+ const newToast = {
93
+ id: Date.now(),
94
+ style,
95
+ message,
96
+ icon
97
+ };
98
+ setToasts(prev => [...prev, newToast]);
99
+ };
100
+
101
+ const removeToast = (id: number) => {
102
+ setToasts(prev => prev.filter(toast => toast.id !== id));
103
+ };
104
+
105
+ return (
106
+ <div>
107
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
108
+ <Button onClick={() => addToast('Success', 'File uploaded successfully!', 'CheckFilled')}>
109
+ Upload Success
110
+ </Button>
111
+ <Button onClick={() => addToast('Error', 'Connection failed. Please try again.', 'ErrorOutlined')}>
112
+ Connection Error
113
+ </Button>
114
+ <Button onClick={() => addToast('Neutral', 'New message received.', 'InfoFilled')}>
115
+ New Message
116
+ </Button>
117
+ </div>
118
+
119
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
120
+ {toasts.map((toast) => (
121
+ <ToastNotification
122
+ key={toast.id}
123
+ style={toast.style as any}
124
+ leadingIcon={<Icon name={toast.icon} />}
125
+ removeToast={() => removeToast(toast.id)}
126
+ style={{ marginBottom: '8px' }}
127
+ >
128
+ {toast.message}
129
+ </ToastNotification>
130
+ ))}
131
+ </div>
132
+ </div>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ### Auto-dismiss Toasts
138
+
139
+ ```tsx
140
+ import { ToastNotification, Button } from '@delightui/components';
141
+
142
+ function AutoDismissToastExample() {
143
+ const [toasts, setToasts] = useState<Array<{id: number, style: string, message: string, duration: number}>>([]);
144
+
145
+ const addToast = (style: 'Neutral' | 'Success' | 'Error', message: string, duration: number) => {
146
+ const newToast = {
147
+ id: Date.now(),
148
+ style,
149
+ message,
150
+ duration
151
+ };
152
+ setToasts(prev => [...prev, newToast]);
153
+
154
+ // Auto-remove after duration
155
+ setTimeout(() => {
156
+ removeToast(newToast.id);
157
+ }, duration);
158
+ };
159
+
160
+ const removeToast = (id: number) => {
161
+ setToasts(prev => prev.filter(toast => toast.id !== id));
162
+ };
163
+
164
+ return (
165
+ <div>
166
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
167
+ <Button onClick={() => addToast('Success', 'Quick success message!', 2000)}>
168
+ 2 Second Toast
169
+ </Button>
170
+ <Button onClick={() => addToast('Neutral', 'Medium duration message.', 5000)}>
171
+ 5 Second Toast
172
+ </Button>
173
+ <Button onClick={() => addToast('Error', 'Important error that stays longer.', 10000)}>
174
+ 10 Second Toast
175
+ </Button>
176
+ </div>
177
+
178
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
179
+ {toasts.map((toast) => (
180
+ <ToastNotification
181
+ key={toast.id}
182
+ style={toast.style as any}
183
+ duration={toast.duration}
184
+ removeToast={() => removeToast(toast.id)}
185
+ style={{ marginBottom: '8px' }}
186
+ >
187
+ {toast.message}
188
+ </ToastNotification>
189
+ ))}
190
+ </div>
191
+ </div>
192
+ );
193
+ }
194
+ ```
195
+
196
+ ### Non-dismissible Toasts
197
+
198
+ ```tsx
199
+ import { ToastNotification, Button } from '@delightui/components';
200
+
201
+ function NonDismissibleToastExample() {
202
+ const [toasts, setToasts] = useState<Array<{id: number, message: string, dismissible: boolean}>>([]);
203
+
204
+ const addToast = (message: string, dismissible: boolean) => {
205
+ const newToast = {
206
+ id: Date.now(),
207
+ message,
208
+ dismissible
209
+ };
210
+ setToasts(prev => [...prev, newToast]);
211
+ };
212
+
213
+ const removeToast = (id: number) => {
214
+ setToasts(prev => prev.filter(toast => toast.id !== id));
215
+ };
216
+
217
+ const clearAll = () => {
218
+ setToasts([]);
219
+ };
220
+
221
+ return (
222
+ <div>
223
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
224
+ <Button onClick={() => addToast('This toast can be dismissed manually.', true)}>
225
+ Dismissible Toast
226
+ </Button>
227
+ <Button onClick={() => addToast('This toast cannot be dismissed by user.', false)}>
228
+ Non-dismissible Toast
229
+ </Button>
230
+ <Button onClick={clearAll} type="Outlined">
231
+ Clear All
232
+ </Button>
233
+ </div>
234
+
235
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
236
+ {toasts.map((toast) => (
237
+ <ToastNotification
238
+ key={toast.id}
239
+ style="Neutral"
240
+ isDismissable={toast.dismissible}
241
+ removeToast={toast.dismissible ? () => removeToast(toast.id) : undefined}
242
+ style={{ marginBottom: '8px' }}
243
+ >
244
+ {toast.message}
245
+ </ToastNotification>
246
+ ))}
247
+ </div>
248
+ </div>
249
+ );
250
+ }
251
+ ```
252
+
253
+ ### Form Validation Toasts
254
+
255
+ ```tsx
256
+ import { Form, FormField, Input, Button, ToastNotification, Icon } from '@delightui/components';
257
+
258
+ function FormValidationToastExample() {
259
+ const [toasts, setToasts] = useState<Array<{id: number, type: string, message: string}>>([]);
260
+
261
+ const addToast = (type: 'Success' | 'Error', message: string) => {
262
+ const newToast = {
263
+ id: Date.now(),
264
+ type,
265
+ message
266
+ };
267
+ setToasts(prev => [...prev, newToast]);
268
+
269
+ // Auto-remove after 5 seconds
270
+ setTimeout(() => {
271
+ removeToast(newToast.id);
272
+ }, 5000);
273
+ };
274
+
275
+ const removeToast = (id: number) => {
276
+ setToasts(prev => prev.filter(toast => toast.id !== id));
277
+ };
278
+
279
+ const handleSubmit = (data: any) => {
280
+ // Simulate form validation
281
+ if (!data.email || !data.password) {
282
+ addToast('Error', 'Please fill in all required fields.');
283
+ return;
284
+ }
285
+
286
+ if (data.password.length < 8) {
287
+ addToast('Error', 'Password must be at least 8 characters long.');
288
+ return;
289
+ }
290
+
291
+ // Simulate successful submission
292
+ addToast('Success', 'Account created successfully! Welcome aboard.');
293
+ };
294
+
295
+ return (
296
+ <div>
297
+ <Form onSubmit={handleSubmit}>
298
+ <FormField name="email" label="Email" required>
299
+ <Input inputType="Email" placeholder="Enter your email" />
300
+ </FormField>
301
+
302
+ <FormField name="password" label="Password" required>
303
+ <Input inputType="Password" placeholder="Enter your password" />
304
+ </FormField>
305
+
306
+ <Button type="submit">
307
+ Create Account
308
+ </Button>
309
+ </Form>
310
+
311
+ {/* Toast Container */}
312
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
313
+ {toasts.map((toast) => (
314
+ <ToastNotification
315
+ key={toast.id}
316
+ style={toast.type as any}
317
+ leadingIcon={
318
+ <Icon name={toast.type === 'Success' ? 'CheckFilled' : 'ErrorOutlined'} />
319
+ }
320
+ removeToast={() => removeToast(toast.id)}
321
+ style={{ marginBottom: '8px' }}
322
+ >
323
+ {toast.message}
324
+ </ToastNotification>
325
+ ))}
326
+ </div>
327
+ </div>
328
+ );
329
+ }
330
+ ```
331
+
332
+ ### Action Feedback Toasts
333
+
334
+ ```tsx
335
+ import { ToastNotification, Button, Icon } from '@delightui/components';
336
+
337
+ function ActionFeedbackToastExample() {
338
+ const [toasts, setToasts] = useState<Array<{id: number, type: string, message: string, action?: string}>>([]);
339
+
340
+ const addToast = (type: 'Success' | 'Error' | 'Neutral', message: string, action?: string) => {
341
+ const newToast = {
342
+ id: Date.now(),
343
+ type,
344
+ message,
345
+ action
346
+ };
347
+ setToasts(prev => [...prev, newToast]);
348
+
349
+ // Auto-remove after 6 seconds
350
+ setTimeout(() => {
351
+ removeToast(newToast.id);
352
+ }, 6000);
353
+ };
354
+
355
+ const removeToast = (id: number) => {
356
+ setToasts(prev => prev.filter(toast => toast.id !== id));
357
+ };
358
+
359
+ const simulateAction = (actionType: string) => {
360
+ switch (actionType) {
361
+ case 'save':
362
+ addToast('Success', 'Document saved successfully!');
363
+ break;
364
+ case 'delete':
365
+ addToast('Success', 'Item deleted successfully!', 'undo');
366
+ break;
367
+ case 'copy':
368
+ addToast('Neutral', 'Copied to clipboard!');
369
+ break;
370
+ case 'error':
371
+ addToast('Error', 'Failed to save. Please try again.');
372
+ break;
373
+ default:
374
+ break;
375
+ }
376
+ };
377
+
378
+ const handleUndo = () => {
379
+ addToast('Neutral', 'Action undone successfully!');
380
+ };
381
+
382
+ return (
383
+ <div>
384
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px', flexWrap: 'wrap' }}>
385
+ <Button onClick={() => simulateAction('save')}>
386
+ Save Document
387
+ </Button>
388
+ <Button onClick={() => simulateAction('delete')} style="Destructive">
389
+ Delete Item
390
+ </Button>
391
+ <Button onClick={() => simulateAction('copy')} type="Outlined">
392
+ Copy Text
393
+ </Button>
394
+ <Button onClick={() => simulateAction('error')} style="Destructive" type="Outlined">
395
+ Simulate Error
396
+ </Button>
397
+ </div>
398
+
399
+ {/* Toast Container */}
400
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
401
+ {toasts.map((toast) => (
402
+ <ToastNotification
403
+ key={toast.id}
404
+ style={toast.type as any}
405
+ leadingIcon={
406
+ <Icon
407
+ name={
408
+ toast.type === 'Success' ? 'CheckFilled' :
409
+ toast.type === 'Error' ? 'ErrorOutlined' :
410
+ 'InfoFilled'
411
+ }
412
+ />
413
+ }
414
+ trailingIcon={
415
+ toast.action === 'undo' ? (
416
+ <Button size="Small" type="Ghost" onClick={handleUndo}>
417
+ Undo
418
+ </Button>
419
+ ) : undefined
420
+ }
421
+ removeToast={() => removeToast(toast.id)}
422
+ style={{ marginBottom: '8px', minWidth: '300px' }}
423
+ >
424
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
425
+ <span>{toast.message}</span>
426
+ </div>
427
+ </ToastNotification>
428
+ ))}
429
+ </div>
430
+ </div>
431
+ );
432
+ }
433
+ ```
434
+
435
+ ### Progress and Loading Toasts
436
+
437
+ ```tsx
438
+ import { ToastNotification, Spinner, Button, Icon } from '@delightui/components';
439
+
440
+ function ProgressToastExample() {
441
+ const [toasts, setToasts] = useState<Array<{id: number, type: string, message: string, loading?: boolean}>>([]);
442
+
443
+ const addProgressToast = async (operation: string) => {
444
+ const toastId = Date.now();
445
+
446
+ // Add loading toast
447
+ setToasts(prev => [...prev, {
448
+ id: toastId,
449
+ type: 'Neutral',
450
+ message: `${operation} in progress...`,
451
+ loading: true
452
+ }]);
453
+
454
+ // Simulate operation
455
+ await new Promise(resolve => setTimeout(resolve, 3000));
456
+
457
+ // Update to success toast
458
+ setToasts(prev => prev.map(toast =>
459
+ toast.id === toastId
460
+ ? { ...toast, message: `${operation} completed successfully!`, loading: false, type: 'Success' }
461
+ : toast
462
+ ));
463
+
464
+ // Auto-remove after 3 seconds
465
+ setTimeout(() => {
466
+ removeToast(toastId);
467
+ }, 3000);
468
+ };
469
+
470
+ const removeToast = (id: number) => {
471
+ setToasts(prev => prev.filter(toast => toast.id !== id));
472
+ };
473
+
474
+ return (
475
+ <div>
476
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
477
+ <Button onClick={() => addProgressToast('File upload')}>
478
+ Upload File
479
+ </Button>
480
+ <Button onClick={() => addProgressToast('Data processing')}>
481
+ Process Data
482
+ </Button>
483
+ <Button onClick={() => addProgressToast('Backup creation')}>
484
+ Create Backup
485
+ </Button>
486
+ </div>
487
+
488
+ {/* Toast Container */}
489
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
490
+ {toasts.map((toast) => (
491
+ <ToastNotification
492
+ key={toast.id}
493
+ style={toast.type as any}
494
+ leadingIcon={
495
+ toast.loading ?
496
+ <Spinner /> :
497
+ <Icon name={toast.type === 'Success' ? 'CheckFilled' : 'InfoFilled'} />
498
+ }
499
+ isDismissable={!toast.loading}
500
+ removeToast={!toast.loading ? () => removeToast(toast.id) : undefined}
501
+ style={{ marginBottom: '8px' }}
502
+ >
503
+ {toast.message}
504
+ </ToastNotification>
505
+ ))}
506
+ </div>
507
+ </div>
508
+ );
509
+ }
510
+ ```
511
+
512
+ ### Toast Position Variations
513
+
514
+ ```tsx
515
+ import { ToastNotification, Button } from '@delightui/components';
516
+
517
+ function ToastPositionExample() {
518
+ const [toasts, setToasts] = useState<Array<{id: number, message: string, position: string}>>([]);
519
+
520
+ const addToast = (position: string) => {
521
+ const newToast = {
522
+ id: Date.now(),
523
+ message: `Toast from ${position}`,
524
+ position
525
+ };
526
+ setToasts(prev => [...prev, newToast]);
527
+
528
+ // Auto-remove after 4 seconds
529
+ setTimeout(() => {
530
+ removeToast(newToast.id);
531
+ }, 4000);
532
+ };
533
+
534
+ const removeToast = (id: number) => {
535
+ setToasts(prev => prev.filter(toast => toast.id !== id));
536
+ };
537
+
538
+ const getPositionStyles = (position: string) => {
539
+ const baseStyles = { position: 'fixed', zIndex: 1000 };
540
+
541
+ switch (position) {
542
+ case 'top-right':
543
+ return { ...baseStyles, top: '20px', right: '20px' };
544
+ case 'top-left':
545
+ return { ...baseStyles, top: '20px', left: '20px' };
546
+ case 'bottom-right':
547
+ return { ...baseStyles, bottom: '20px', right: '20px' };
548
+ case 'bottom-left':
549
+ return { ...baseStyles, bottom: '20px', left: '20px' };
550
+ case 'top-center':
551
+ return { ...baseStyles, top: '20px', left: '50%', transform: 'translateX(-50%)' };
552
+ case 'bottom-center':
553
+ return { ...baseStyles, bottom: '20px', left: '50%', transform: 'translateX(-50%)' };
554
+ default:
555
+ return { ...baseStyles, top: '20px', right: '20px' };
556
+ }
557
+ };
558
+
559
+ return (
560
+ <div>
561
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '8px', marginBottom: '20px' }}>
562
+ <Button onClick={() => addToast('top-left')} size="Small">
563
+ Top Left
564
+ </Button>
565
+ <Button onClick={() => addToast('top-center')} size="Small">
566
+ Top Center
567
+ </Button>
568
+ <Button onClick={() => addToast('top-right')} size="Small">
569
+ Top Right
570
+ </Button>
571
+ <Button onClick={() => addToast('bottom-left')} size="Small">
572
+ Bottom Left
573
+ </Button>
574
+ <Button onClick={() => addToast('bottom-center')} size="Small">
575
+ Bottom Center
576
+ </Button>
577
+ <Button onClick={() => addToast('bottom-right')} size="Small">
578
+ Bottom Right
579
+ </Button>
580
+ </div>
581
+
582
+ {/* Render toasts by position */}
583
+ {['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'].map(position => {
584
+ const positionToasts = toasts.filter(toast => toast.position === position);
585
+
586
+ return positionToasts.length > 0 ? (
587
+ <div key={position} style={getPositionStyles(position)}>
588
+ {positionToasts.map((toast) => (
589
+ <ToastNotification
590
+ key={toast.id}
591
+ style="Neutral"
592
+ removeToast={() => removeToast(toast.id)}
593
+ style={{ marginBottom: '8px' }}
594
+ >
595
+ {toast.message}
596
+ </ToastNotification>
597
+ ))}
598
+ </div>
599
+ ) : null;
600
+ })}
601
+ </div>
602
+ );
603
+ }
604
+ ```
605
+
606
+ ### Custom Styled Toasts
607
+
608
+ ```tsx
609
+ import { ToastNotification, Button, Icon } from '@delightui/components';
610
+
611
+ function CustomStyledToastExample() {
612
+ const [toasts, setToasts] = useState<Array<{id: number, type: string, message: string, custom?: boolean}>>([]);
613
+
614
+ const addToast = (type: 'Success' | 'Error' | 'Neutral', message: string, custom = false) => {
615
+ const newToast = {
616
+ id: Date.now(),
617
+ type,
618
+ message,
619
+ custom
620
+ };
621
+ setToasts(prev => [...prev, newToast]);
622
+
623
+ setTimeout(() => {
624
+ removeToast(newToast.id);
625
+ }, 5000);
626
+ };
627
+
628
+ const removeToast = (id: number) => {
629
+ setToasts(prev => prev.filter(toast => toast.id !== id));
630
+ };
631
+
632
+ return (
633
+ <div>
634
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px' }}>
635
+ <Button onClick={() => addToast('Success', 'Standard success message')}>
636
+ Standard Toast
637
+ </Button>
638
+ <Button onClick={() => addToast('Success', 'Custom styled success message', true)}>
639
+ Custom Toast
640
+ </Button>
641
+ </div>
642
+
643
+ <div style={{ position: 'fixed', top: '20px', right: '20px', zIndex: 1000 }}>
644
+ {toasts.map((toast) => (
645
+ <ToastNotification
646
+ key={toast.id}
647
+ style={toast.type as any}
648
+ leadingIcon={<Icon name="CheckFilled" />}
649
+ removeToast={() => removeToast(toast.id)}
650
+ className={toast.custom ? 'custom-toast' : ''}
651
+ style={{
652
+ marginBottom: '8px',
653
+ ...(toast.custom && {
654
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
655
+ color: 'white',
656
+ borderRadius: '12px',
657
+ boxShadow: '0 8px 25px rgba(0,0,0,0.2)'
658
+ })
659
+ }}
660
+ >
661
+ {toast.message}
662
+ </ToastNotification>
663
+ ))}
664
+ </div>
665
+ </div>
666
+ );
667
+ }
668
+ ```