@delightui/components 0.1.104 → 0.1.106
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.
- package/README.md +104 -1
- package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
- package/dist/cjs/components/molecules/Popover/Popover.presenter.d.ts +26 -0
- package/dist/cjs/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/cjs/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/cjs/components/molecules/Select/Select.d.ts +5 -5
- package/dist/cjs/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/cjs/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/cjs/components/molecules/Select/index.d.ts +2 -9
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/cjs/components/utils/index.d.ts +2 -0
- package/dist/cjs/library.css +13 -0
- package/dist/cjs/library.js +2 -2
- package/dist/cjs/library.js.map +1 -1
- package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
- package/dist/esm/components/molecules/Popover/Popover.presenter.d.ts +26 -0
- package/dist/esm/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/esm/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/esm/components/molecules/Select/Select.d.ts +5 -5
- package/dist/esm/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/esm/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/esm/components/molecules/Select/index.d.ts +2 -9
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/esm/components/utils/index.d.ts +2 -0
- package/dist/esm/library.css +13 -0
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +156 -12
- package/docs/README.md +264 -0
- package/docs/components/atoms/ActionImage.md +119 -0
- package/docs/components/atoms/Button.md +197 -0
- package/docs/components/atoms/Checkbox.md +299 -0
- package/docs/components/atoms/CheckboxItem.md +314 -0
- package/docs/components/atoms/Chip.md +380 -0
- package/docs/components/atoms/CustomToggle.md +270 -0
- package/docs/components/atoms/Icon.md +365 -0
- package/docs/components/atoms/IconButton.md +407 -0
- package/docs/components/atoms/Image.md +448 -0
- package/docs/components/atoms/Input.md +430 -0
- package/docs/components/atoms/ListItem.md +502 -0
- package/docs/components/atoms/Password.md +472 -0
- package/docs/components/atoms/RadioButton.md +614 -0
- package/docs/components/atoms/RadioButtonItem.md +588 -0
- package/docs/components/atoms/ResponsiveComponent.md +612 -0
- package/docs/components/atoms/SelectListItem.md +609 -0
- package/docs/components/atoms/Slider.md +605 -0
- package/docs/components/atoms/Spinner.md +605 -0
- package/docs/components/atoms/Text.md +463 -0
- package/docs/components/atoms/TextArea.md +670 -0
- package/docs/components/atoms/ToastNotification.md +668 -0
- package/docs/components/atoms/Toggle.md +737 -0
- package/docs/components/atoms/ToggleButton.md +751 -0
- package/docs/components/atoms/Tooltip.md +391 -0
- package/docs/components/molecules/Accordion.md +440 -0
- package/docs/components/molecules/AccordionGroup.md +547 -0
- package/docs/components/molecules/ActionCard.md +546 -0
- package/docs/components/molecules/Breadcrumb.md +403 -0
- package/docs/components/molecules/Breadcrumbs.md +485 -0
- package/docs/components/molecules/ButtonGroup.md +383 -0
- package/docs/components/molecules/Card.md +298 -0
- package/docs/components/molecules/ChipInput.md +646 -0
- package/docs/components/molecules/ContextMenu.md +768 -0
- package/docs/components/molecules/CustomTimeSelector.md +116 -0
- package/docs/components/molecules/DatePicker.md +516 -0
- package/docs/components/molecules/DateTimeSelector.md +166 -0
- package/docs/components/molecules/FormField.md +312 -0
- package/docs/components/molecules/Grid.md +577 -0
- package/docs/components/molecules/GridItem.md +834 -0
- package/docs/components/molecules/GridList.md +244 -0
- package/docs/components/molecules/List.md +485 -0
- package/docs/components/molecules/Modal.md +470 -0
- package/docs/components/molecules/ModalFooter.md +702 -0
- package/docs/components/molecules/ModalHeader.md +756 -0
- package/docs/components/molecules/ModalProvider.md +205 -0
- package/docs/components/molecules/Nav.md +530 -0
- package/docs/components/molecules/NavItem.md +572 -0
- package/docs/components/molecules/NavLink.md +499 -0
- package/docs/components/molecules/Option.md +521 -0
- package/docs/components/molecules/Pagination.md +592 -0
- package/docs/components/molecules/PaginationNumberField.md +722 -0
- package/docs/components/molecules/Popover.md +516 -0
- package/docs/components/molecules/ProgressBar.md +624 -0
- package/docs/components/molecules/RadioGroup.md +831 -0
- package/docs/components/molecules/RepeaterList.md +185 -0
- package/docs/components/molecules/Select.md +402 -0
- package/docs/components/molecules/SortableTrigger.md +82 -0
- package/docs/components/molecules/useModal.md +379 -0
- package/docs/components/organisms/Dropzone.md +346 -0
- package/docs/components/organisms/DropzoneClear.md +135 -0
- package/docs/components/organisms/DropzoneContent.md +216 -0
- package/docs/components/organisms/DropzoneFilename.md +191 -0
- package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
- package/docs/components/organisms/DropzoneTrigger.md +209 -0
- package/docs/components/organisms/Form.md +533 -0
- package/docs/components/organisms/SlideOutPanel.md +662 -0
- package/docs/components/organisms/TabContent.md +902 -0
- package/docs/components/organisms/TabItem.md +1091 -0
- package/docs/components/organisms/Table.md +611 -0
- package/docs/components/organisms/TableBody.md +679 -0
- package/docs/components/organisms/TableCell.md +482 -0
- package/docs/components/organisms/TableHeader.md +513 -0
- package/docs/components/organisms/TableHeaderCell.md +661 -0
- package/docs/components/organisms/TableRow.md +715 -0
- package/docs/components/organisms/Tabs.md +1330 -0
- package/docs/components/utils/ConditionalView.md +568 -0
- package/docs/components/utils/RenderStateView.md +726 -0
- package/docs/components/utils/WrapTextNodes.md +614 -0
- 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
|
+
```
|