@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.
- 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/index.d.ts +2 -0
- package/dist/cjs/library.css +19 -6
- package/dist/cjs/library.js +3 -3
- 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/index.d.ts +2 -0
- package/dist/esm/library.css +19 -6
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +108 -2
- 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,702 @@
|
|
|
1
|
+
# ModalFooter
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
A specialized footer component designed for modal dialogs that provides structured button layouts and styling options. Supports both single and dual button configurations with customizable styling variants including stroke options for visual separation from modal content.
|
|
6
|
+
|
|
7
|
+
## Aliases
|
|
8
|
+
|
|
9
|
+
- ModalFooter
|
|
10
|
+
- DialogFooter
|
|
11
|
+
- ModalActions
|
|
12
|
+
- DialogActions
|
|
13
|
+
- ModalButtons
|
|
14
|
+
|
|
15
|
+
## Props Breakdown
|
|
16
|
+
|
|
17
|
+
**Extends:** Omit<HTMLAttributes<HTMLDivElement>, 'style'> (inherits div properties except style)
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Required | Description |
|
|
20
|
+
|------|------|---------|----------|-------------|
|
|
21
|
+
| `type` | `'1Button' \| '2Buttons'` | `'1Button'` | No | Layout type - single or dual button configuration |
|
|
22
|
+
| `style` | `'NoStroke' \| 'WithStroke'` | `'NoStroke'` | No | Visual style variant with optional top border |
|
|
23
|
+
| `primaryButton` | `ReactNode` | - | No | Primary action button element |
|
|
24
|
+
| `secondaryButton` | `ReactNode` | - | No | Secondary action button (only for 2Buttons type) |
|
|
25
|
+
| `className` | `string` | - | No | Additional CSS class names |
|
|
26
|
+
| `children` | `ReactNode` | - | No | Custom content overriding button props |
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
### Basic Single Button Footer
|
|
31
|
+
```tsx
|
|
32
|
+
import { Modal, ModalFooter, Button, Text } from '@delightui/components';
|
|
33
|
+
|
|
34
|
+
function SingleButtonExample() {
|
|
35
|
+
const [showModal, setShowModal] = useState(false);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<Button onClick={() => setShowModal(true)}>
|
|
40
|
+
Show Info Modal
|
|
41
|
+
</Button>
|
|
42
|
+
|
|
43
|
+
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
|
44
|
+
<div className="modal-content">
|
|
45
|
+
<Text type="Heading4">Information</Text>
|
|
46
|
+
<Text>This is an informational modal with a single action button.</Text>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<ModalFooter
|
|
50
|
+
type="1Button"
|
|
51
|
+
primaryButton={
|
|
52
|
+
<Button onClick={() => setShowModal(false)}>
|
|
53
|
+
Got it
|
|
54
|
+
</Button>
|
|
55
|
+
}
|
|
56
|
+
/>
|
|
57
|
+
</Modal>
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Confirmation Modal with Two Buttons
|
|
64
|
+
```tsx
|
|
65
|
+
function ConfirmationExample() {
|
|
66
|
+
const [showModal, setShowModal] = useState(false);
|
|
67
|
+
const [loading, setLoading] = useState(false);
|
|
68
|
+
|
|
69
|
+
const handleConfirm = async () => {
|
|
70
|
+
setLoading(true);
|
|
71
|
+
// Simulate API call
|
|
72
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
73
|
+
setLoading(false);
|
|
74
|
+
setShowModal(false);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<>
|
|
79
|
+
<Button style="Destructive" onClick={() => setShowModal(true)}>
|
|
80
|
+
Delete Item
|
|
81
|
+
</Button>
|
|
82
|
+
|
|
83
|
+
<Modal
|
|
84
|
+
show={showModal}
|
|
85
|
+
onHide={() => setShowModal(false)}
|
|
86
|
+
disableBackdropDismiss={loading}
|
|
87
|
+
>
|
|
88
|
+
<div className="modal-content">
|
|
89
|
+
<Text type="Heading4">Confirm Deletion</Text>
|
|
90
|
+
<Text>
|
|
91
|
+
Are you sure you want to delete this item? This action cannot be undone.
|
|
92
|
+
</Text>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<ModalFooter
|
|
96
|
+
type="2Buttons"
|
|
97
|
+
style="WithStroke"
|
|
98
|
+
secondaryButton={
|
|
99
|
+
<Button
|
|
100
|
+
type="Outlined"
|
|
101
|
+
onClick={() => setShowModal(false)}
|
|
102
|
+
disabled={loading}
|
|
103
|
+
>
|
|
104
|
+
Cancel
|
|
105
|
+
</Button>
|
|
106
|
+
}
|
|
107
|
+
primaryButton={
|
|
108
|
+
<Button
|
|
109
|
+
style="Destructive"
|
|
110
|
+
loading={loading}
|
|
111
|
+
onClick={handleConfirm}
|
|
112
|
+
>
|
|
113
|
+
Delete
|
|
114
|
+
</Button>
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
</Modal>
|
|
118
|
+
</>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Form Modal Footer
|
|
124
|
+
```tsx
|
|
125
|
+
function FormModalExample() {
|
|
126
|
+
const [showModal, setShowModal] = useState(false);
|
|
127
|
+
const [formData, setFormData] = useState({ name: '', email: '' });
|
|
128
|
+
const [saving, setSaving] = useState(false);
|
|
129
|
+
|
|
130
|
+
const handleSubmit = async () => {
|
|
131
|
+
setSaving(true);
|
|
132
|
+
// Simulate form submission
|
|
133
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
134
|
+
setSaving(false);
|
|
135
|
+
setShowModal(false);
|
|
136
|
+
setFormData({ name: '', email: '' });
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const isFormValid = formData.name.trim() && formData.email.trim();
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<Button onClick={() => setShowModal(true)}>
|
|
144
|
+
Add New User
|
|
145
|
+
</Button>
|
|
146
|
+
|
|
147
|
+
<Modal show={showModal} onHide={() => setShowModal(false)} size="Medium">
|
|
148
|
+
<div className="modal-content">
|
|
149
|
+
<Text type="Heading4">Add New User</Text>
|
|
150
|
+
|
|
151
|
+
<FormField label="Full Name" required>
|
|
152
|
+
<Input
|
|
153
|
+
value={formData.name}
|
|
154
|
+
onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
|
|
155
|
+
placeholder="Enter full name"
|
|
156
|
+
/>
|
|
157
|
+
</FormField>
|
|
158
|
+
|
|
159
|
+
<FormField label="Email Address" required>
|
|
160
|
+
<Input
|
|
161
|
+
type="email"
|
|
162
|
+
value={formData.email}
|
|
163
|
+
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
|
|
164
|
+
placeholder="Enter email address"
|
|
165
|
+
/>
|
|
166
|
+
</FormField>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<ModalFooter
|
|
170
|
+
type="2Buttons"
|
|
171
|
+
style="WithStroke"
|
|
172
|
+
secondaryButton={
|
|
173
|
+
<Button
|
|
174
|
+
type="Outlined"
|
|
175
|
+
onClick={() => setShowModal(false)}
|
|
176
|
+
disabled={saving}
|
|
177
|
+
>
|
|
178
|
+
Cancel
|
|
179
|
+
</Button>
|
|
180
|
+
}
|
|
181
|
+
primaryButton={
|
|
182
|
+
<Button
|
|
183
|
+
onClick={handleSubmit}
|
|
184
|
+
loading={saving}
|
|
185
|
+
disabled={!isFormValid}
|
|
186
|
+
>
|
|
187
|
+
Add User
|
|
188
|
+
</Button>
|
|
189
|
+
}
|
|
190
|
+
/>
|
|
191
|
+
</Modal>
|
|
192
|
+
</>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Settings Modal Footer
|
|
198
|
+
```tsx
|
|
199
|
+
function SettingsModalExample() {
|
|
200
|
+
const [showModal, setShowModal] = useState(false);
|
|
201
|
+
const [settings, setSettings] = useState({
|
|
202
|
+
notifications: true,
|
|
203
|
+
darkMode: false,
|
|
204
|
+
autoSave: true
|
|
205
|
+
});
|
|
206
|
+
const [hasChanges, setHasChanges] = useState(false);
|
|
207
|
+
|
|
208
|
+
const handleSettingChange = (key, value) => {
|
|
209
|
+
setSettings(prev => ({ ...prev, [key]: value }));
|
|
210
|
+
setHasChanges(true);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const handleSave = () => {
|
|
214
|
+
console.log('Saving settings:', settings);
|
|
215
|
+
setHasChanges(false);
|
|
216
|
+
setShowModal(false);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const handleReset = () => {
|
|
220
|
+
setSettings({
|
|
221
|
+
notifications: true,
|
|
222
|
+
darkMode: false,
|
|
223
|
+
autoSave: true
|
|
224
|
+
});
|
|
225
|
+
setHasChanges(false);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<>
|
|
230
|
+
<Button onClick={() => setShowModal(true)}>
|
|
231
|
+
Settings
|
|
232
|
+
</Button>
|
|
233
|
+
|
|
234
|
+
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
|
235
|
+
<div className="modal-content">
|
|
236
|
+
<Text type="Heading4">Application Settings</Text>
|
|
237
|
+
|
|
238
|
+
<div className="settings-list">
|
|
239
|
+
<FormField label="Enable Notifications">
|
|
240
|
+
<Toggle
|
|
241
|
+
checked={settings.notifications}
|
|
242
|
+
onChange={(checked) => handleSettingChange('notifications', checked)}
|
|
243
|
+
/>
|
|
244
|
+
</FormField>
|
|
245
|
+
|
|
246
|
+
<FormField label="Dark Mode">
|
|
247
|
+
<Toggle
|
|
248
|
+
checked={settings.darkMode}
|
|
249
|
+
onChange={(checked) => handleSettingChange('darkMode', checked)}
|
|
250
|
+
/>
|
|
251
|
+
</FormField>
|
|
252
|
+
|
|
253
|
+
<FormField label="Auto Save">
|
|
254
|
+
<Toggle
|
|
255
|
+
checked={settings.autoSave}
|
|
256
|
+
onChange={(checked) => handleSettingChange('autoSave', checked)}
|
|
257
|
+
/>
|
|
258
|
+
</FormField>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
|
|
262
|
+
<ModalFooter
|
|
263
|
+
type="2Buttons"
|
|
264
|
+
style="WithStroke"
|
|
265
|
+
secondaryButton={
|
|
266
|
+
<ButtonGroup>
|
|
267
|
+
<Button
|
|
268
|
+
type="Text"
|
|
269
|
+
onClick={handleReset}
|
|
270
|
+
disabled={!hasChanges}
|
|
271
|
+
>
|
|
272
|
+
Reset
|
|
273
|
+
</Button>
|
|
274
|
+
<Button
|
|
275
|
+
type="Outlined"
|
|
276
|
+
onClick={() => setShowModal(false)}
|
|
277
|
+
>
|
|
278
|
+
Cancel
|
|
279
|
+
</Button>
|
|
280
|
+
</ButtonGroup>
|
|
281
|
+
}
|
|
282
|
+
primaryButton={
|
|
283
|
+
<Button
|
|
284
|
+
onClick={handleSave}
|
|
285
|
+
disabled={!hasChanges}
|
|
286
|
+
>
|
|
287
|
+
Save Changes
|
|
288
|
+
</Button>
|
|
289
|
+
}
|
|
290
|
+
/>
|
|
291
|
+
</Modal>
|
|
292
|
+
</>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Custom Footer Content
|
|
298
|
+
```tsx
|
|
299
|
+
function CustomFooterExample() {
|
|
300
|
+
const [showModal, setShowModal] = useState(false);
|
|
301
|
+
const [step, setStep] = useState(1);
|
|
302
|
+
const totalSteps = 3;
|
|
303
|
+
|
|
304
|
+
const nextStep = () => setStep(prev => Math.min(prev + 1, totalSteps));
|
|
305
|
+
const prevStep = () => setStep(prev => Math.max(prev - 1, 1));
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<>
|
|
309
|
+
<Button onClick={() => setShowModal(true)}>
|
|
310
|
+
Start Wizard
|
|
311
|
+
</Button>
|
|
312
|
+
|
|
313
|
+
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
|
314
|
+
<div className="modal-content">
|
|
315
|
+
<Text type="Heading4">Setup Wizard - Step {step} of {totalSteps}</Text>
|
|
316
|
+
|
|
317
|
+
{step === 1 && (
|
|
318
|
+
<div>
|
|
319
|
+
<Text>Welcome to the setup wizard. We'll help you get started.</Text>
|
|
320
|
+
</div>
|
|
321
|
+
)}
|
|
322
|
+
|
|
323
|
+
{step === 2 && (
|
|
324
|
+
<div>
|
|
325
|
+
<Text>Please configure your preferences.</Text>
|
|
326
|
+
<FormField label="Your Name">
|
|
327
|
+
<Input placeholder="Enter your name" />
|
|
328
|
+
</FormField>
|
|
329
|
+
</div>
|
|
330
|
+
)}
|
|
331
|
+
|
|
332
|
+
{step === 3 && (
|
|
333
|
+
<div>
|
|
334
|
+
<Text>Setup complete! You're ready to go.</Text>
|
|
335
|
+
</div>
|
|
336
|
+
)}
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<ModalFooter style="WithStroke">
|
|
340
|
+
<div className="wizard-footer">
|
|
341
|
+
<div className="step-indicator">
|
|
342
|
+
{Array.from({ length: totalSteps }, (_, i) => (
|
|
343
|
+
<div
|
|
344
|
+
key={i}
|
|
345
|
+
className={`step-dot ${i + 1 <= step ? 'active' : ''}`}
|
|
346
|
+
/>
|
|
347
|
+
))}
|
|
348
|
+
</div>
|
|
349
|
+
|
|
350
|
+
<div className="wizard-actions">
|
|
351
|
+
<Button
|
|
352
|
+
type="Outlined"
|
|
353
|
+
onClick={step === 1 ? () => setShowModal(false) : prevStep}
|
|
354
|
+
>
|
|
355
|
+
{step === 1 ? 'Cancel' : 'Back'}
|
|
356
|
+
</Button>
|
|
357
|
+
|
|
358
|
+
<Button
|
|
359
|
+
onClick={step === totalSteps ? () => setShowModal(false) : nextStep}
|
|
360
|
+
>
|
|
361
|
+
{step === totalSteps ? 'Finish' : 'Next'}
|
|
362
|
+
</Button>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
</ModalFooter>
|
|
366
|
+
</Modal>
|
|
367
|
+
</>
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Save Draft Modal
|
|
373
|
+
```tsx
|
|
374
|
+
function SaveDraftExample() {
|
|
375
|
+
const [showModal, setShowModal] = useState(false);
|
|
376
|
+
const [content, setContent] = useState('');
|
|
377
|
+
const [saving, setSaving] = useState(false);
|
|
378
|
+
|
|
379
|
+
const handleSaveDraft = async () => {
|
|
380
|
+
setSaving(true);
|
|
381
|
+
// Simulate saving draft
|
|
382
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
383
|
+
setSaving(false);
|
|
384
|
+
setShowModal(false);
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const handlePublish = async () => {
|
|
388
|
+
setSaving(true);
|
|
389
|
+
// Simulate publishing
|
|
390
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
391
|
+
setSaving(false);
|
|
392
|
+
setShowModal(false);
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
return (
|
|
396
|
+
<>
|
|
397
|
+
<Button onClick={() => setShowModal(true)}>
|
|
398
|
+
Create Post
|
|
399
|
+
</Button>
|
|
400
|
+
|
|
401
|
+
<Modal show={showModal} onHide={() => setShowModal(false)} size="Large">
|
|
402
|
+
<div className="modal-content">
|
|
403
|
+
<Text type="Heading4">Create New Post</Text>
|
|
404
|
+
|
|
405
|
+
<FormField label="Post Content">
|
|
406
|
+
<TextArea
|
|
407
|
+
value={content}
|
|
408
|
+
onChange={(e) => setContent(e.target.value)}
|
|
409
|
+
placeholder="Write your post content here..."
|
|
410
|
+
rows={6}
|
|
411
|
+
/>
|
|
412
|
+
</FormField>
|
|
413
|
+
</div>
|
|
414
|
+
|
|
415
|
+
<ModalFooter style="WithStroke">
|
|
416
|
+
<div className="post-footer">
|
|
417
|
+
<div className="post-info">
|
|
418
|
+
<Text type="BodySmall">
|
|
419
|
+
{content.length} characters
|
|
420
|
+
</Text>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div className="post-actions">
|
|
424
|
+
<Button
|
|
425
|
+
type="Text"
|
|
426
|
+
onClick={() => setShowModal(false)}
|
|
427
|
+
disabled={saving}
|
|
428
|
+
>
|
|
429
|
+
Discard
|
|
430
|
+
</Button>
|
|
431
|
+
|
|
432
|
+
<Button
|
|
433
|
+
type="Outlined"
|
|
434
|
+
onClick={handleSaveDraft}
|
|
435
|
+
loading={saving}
|
|
436
|
+
disabled={!content.trim()}
|
|
437
|
+
>
|
|
438
|
+
Save Draft
|
|
439
|
+
</Button>
|
|
440
|
+
|
|
441
|
+
<Button
|
|
442
|
+
onClick={handlePublish}
|
|
443
|
+
loading={saving}
|
|
444
|
+
disabled={!content.trim()}
|
|
445
|
+
>
|
|
446
|
+
Publish
|
|
447
|
+
</Button>
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
</ModalFooter>
|
|
451
|
+
</Modal>
|
|
452
|
+
</>
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Error Modal Footer
|
|
458
|
+
```tsx
|
|
459
|
+
function ErrorModalExample() {
|
|
460
|
+
const [showModal, setShowModal] = useState(false);
|
|
461
|
+
const [error] = useState({
|
|
462
|
+
title: 'Connection Error',
|
|
463
|
+
message: 'Unable to connect to the server. Please check your internet connection and try again.',
|
|
464
|
+
details: 'Error code: 500 - Internal Server Error'
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
const handleRetry = () => {
|
|
468
|
+
// Simulate retry logic
|
|
469
|
+
console.log('Retrying...');
|
|
470
|
+
setShowModal(false);
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
return (
|
|
474
|
+
<>
|
|
475
|
+
<Button onClick={() => setShowModal(true)}>
|
|
476
|
+
Trigger Error
|
|
477
|
+
</Button>
|
|
478
|
+
|
|
479
|
+
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
|
480
|
+
<div className="modal-content error-modal">
|
|
481
|
+
<div className="error-icon">
|
|
482
|
+
<Icon icon="Error" size="Large" className="error-icon-style" />
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
<Text type="Heading4">{error.title}</Text>
|
|
486
|
+
<Text type="Body">{error.message}</Text>
|
|
487
|
+
|
|
488
|
+
<details className="error-details">
|
|
489
|
+
<summary>Technical Details</summary>
|
|
490
|
+
<Text type="BodySmall" className="error-details-text">
|
|
491
|
+
{error.details}
|
|
492
|
+
</Text>
|
|
493
|
+
</details>
|
|
494
|
+
</div>
|
|
495
|
+
|
|
496
|
+
<ModalFooter
|
|
497
|
+
type="2Buttons"
|
|
498
|
+
style="WithStroke"
|
|
499
|
+
secondaryButton={
|
|
500
|
+
<Button
|
|
501
|
+
type="Outlined"
|
|
502
|
+
onClick={() => setShowModal(false)}
|
|
503
|
+
>
|
|
504
|
+
Close
|
|
505
|
+
</Button>
|
|
506
|
+
}
|
|
507
|
+
primaryButton={
|
|
508
|
+
<Button onClick={handleRetry}>
|
|
509
|
+
Retry
|
|
510
|
+
</Button>
|
|
511
|
+
}
|
|
512
|
+
/>
|
|
513
|
+
</Modal>
|
|
514
|
+
</>
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Terms and Conditions Modal
|
|
520
|
+
```tsx
|
|
521
|
+
function TermsModalExample() {
|
|
522
|
+
const [showModal, setShowModal] = useState(false);
|
|
523
|
+
const [accepted, setAccepted] = useState(false);
|
|
524
|
+
const [scrolledToBottom, setScrolledToBottom] = useState(false);
|
|
525
|
+
|
|
526
|
+
const handleScroll = (event) => {
|
|
527
|
+
const { scrollTop, scrollHeight, clientHeight } = event.target;
|
|
528
|
+
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
|
529
|
+
setScrolledToBottom(isAtBottom);
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
const handleAccept = () => {
|
|
533
|
+
setAccepted(true);
|
|
534
|
+
setShowModal(false);
|
|
535
|
+
console.log('Terms accepted');
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
return (
|
|
539
|
+
<>
|
|
540
|
+
<Button onClick={() => setShowModal(true)}>
|
|
541
|
+
View Terms & Conditions
|
|
542
|
+
</Button>
|
|
543
|
+
|
|
544
|
+
<Modal show={showModal} onHide={() => setShowModal(false)} size="Large">
|
|
545
|
+
<div className="modal-content">
|
|
546
|
+
<Text type="Heading4">Terms and Conditions</Text>
|
|
547
|
+
|
|
548
|
+
<div
|
|
549
|
+
className="terms-content"
|
|
550
|
+
onScroll={handleScroll}
|
|
551
|
+
style={{
|
|
552
|
+
maxHeight: '400px',
|
|
553
|
+
overflowY: 'auto',
|
|
554
|
+
border: '1px solid #ccc',
|
|
555
|
+
padding: '16px',
|
|
556
|
+
marginBottom: '16px'
|
|
557
|
+
}}
|
|
558
|
+
>
|
|
559
|
+
<Text type="Body">
|
|
560
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
|
|
561
|
+
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
|
562
|
+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
|
563
|
+
commodo consequat...
|
|
564
|
+
</Text>
|
|
565
|
+
|
|
566
|
+
<Text type="Body">
|
|
567
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
|
568
|
+
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
|
569
|
+
proident, sunt in culpa qui officia deserunt mollit anim id est laborum...
|
|
570
|
+
</Text>
|
|
571
|
+
|
|
572
|
+
{/* Add more content to make it scrollable */}
|
|
573
|
+
{Array.from({ length: 20 }, (_, i) => (
|
|
574
|
+
<Text key={i} type="Body">
|
|
575
|
+
Section {i + 1}: Additional terms and conditions content that requires
|
|
576
|
+
scrolling to read completely...
|
|
577
|
+
</Text>
|
|
578
|
+
))}
|
|
579
|
+
</div>
|
|
580
|
+
|
|
581
|
+
<FormField>
|
|
582
|
+
<Checkbox
|
|
583
|
+
checked={accepted}
|
|
584
|
+
onChange={setAccepted}
|
|
585
|
+
label="I have read and accept the terms and conditions"
|
|
586
|
+
disabled={!scrolledToBottom}
|
|
587
|
+
/>
|
|
588
|
+
</FormField>
|
|
589
|
+
</div>
|
|
590
|
+
|
|
591
|
+
<ModalFooter
|
|
592
|
+
type="2Buttons"
|
|
593
|
+
style="WithStroke"
|
|
594
|
+
secondaryButton={
|
|
595
|
+
<Button
|
|
596
|
+
type="Outlined"
|
|
597
|
+
onClick={() => setShowModal(false)}
|
|
598
|
+
>
|
|
599
|
+
Cancel
|
|
600
|
+
</Button>
|
|
601
|
+
}
|
|
602
|
+
primaryButton={
|
|
603
|
+
<Button
|
|
604
|
+
onClick={handleAccept}
|
|
605
|
+
disabled={!accepted || !scrolledToBottom}
|
|
606
|
+
>
|
|
607
|
+
Accept & Continue
|
|
608
|
+
</Button>
|
|
609
|
+
}
|
|
610
|
+
/>
|
|
611
|
+
</Modal>
|
|
612
|
+
</>
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Loading Modal Footer
|
|
618
|
+
```tsx
|
|
619
|
+
function LoadingModalExample() {
|
|
620
|
+
const [showModal, setShowModal] = useState(false);
|
|
621
|
+
const [uploadProgress, setUploadProgress] = useState(0);
|
|
622
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
623
|
+
|
|
624
|
+
const simulateUpload = async () => {
|
|
625
|
+
setIsUploading(true);
|
|
626
|
+
setUploadProgress(0);
|
|
627
|
+
|
|
628
|
+
// Simulate upload progress
|
|
629
|
+
for (let i = 0; i <= 100; i += 10) {
|
|
630
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
631
|
+
setUploadProgress(i);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
setIsUploading(false);
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
const startUpload = () => {
|
|
638
|
+
setShowModal(true);
|
|
639
|
+
simulateUpload();
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
return (
|
|
643
|
+
<>
|
|
644
|
+
<Button onClick={startUpload}>
|
|
645
|
+
Upload File
|
|
646
|
+
</Button>
|
|
647
|
+
|
|
648
|
+
<Modal
|
|
649
|
+
show={showModal}
|
|
650
|
+
onHide={() => setShowModal(false)}
|
|
651
|
+
disableBackdropDismiss={isUploading}
|
|
652
|
+
>
|
|
653
|
+
<div className="modal-content">
|
|
654
|
+
<Text type="Heading4">File Upload</Text>
|
|
655
|
+
|
|
656
|
+
<div className="upload-progress">
|
|
657
|
+
<Text type="Body">
|
|
658
|
+
{isUploading ? 'Uploading...' : 'Upload Complete!'}
|
|
659
|
+
</Text>
|
|
660
|
+
|
|
661
|
+
<ProgressBar
|
|
662
|
+
value={uploadProgress}
|
|
663
|
+
max={100}
|
|
664
|
+
className="upload-progress-bar"
|
|
665
|
+
/>
|
|
666
|
+
|
|
667
|
+
<Text type="BodySmall">
|
|
668
|
+
{uploadProgress}% complete
|
|
669
|
+
</Text>
|
|
670
|
+
</div>
|
|
671
|
+
</div>
|
|
672
|
+
|
|
673
|
+
<ModalFooter
|
|
674
|
+
type={isUploading ? "1Button" : "2Buttons"}
|
|
675
|
+
style="WithStroke"
|
|
676
|
+
secondaryButton={
|
|
677
|
+
!isUploading ? (
|
|
678
|
+
<Button
|
|
679
|
+
type="Outlined"
|
|
680
|
+
onClick={() => setShowModal(false)}
|
|
681
|
+
>
|
|
682
|
+
Close
|
|
683
|
+
</Button>
|
|
684
|
+
) : undefined
|
|
685
|
+
}
|
|
686
|
+
primaryButton={
|
|
687
|
+
isUploading ? (
|
|
688
|
+
<Button disabled loading>
|
|
689
|
+
Uploading...
|
|
690
|
+
</Button>
|
|
691
|
+
) : (
|
|
692
|
+
<Button onClick={() => setShowModal(false)}>
|
|
693
|
+
Done
|
|
694
|
+
</Button>
|
|
695
|
+
)
|
|
696
|
+
}
|
|
697
|
+
/>
|
|
698
|
+
</Modal>
|
|
699
|
+
</>
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
```
|