@ceed/ads 1.23.0 → 1.23.1
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.
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
Typography
|
|
5
|
+
The Typography component is a core component for displaying text. It is based on Joy UI Typography and provides a variety of text levels and styles. You can apply consistent typography across all text elements such as headings, body text, and labels.
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
<Typography children="Typography" />
|
|
@@ -21,10 +21,10 @@ import { Typography } from '@ceed/ads';
|
|
|
21
21
|
function MyComponent() {
|
|
22
22
|
return (
|
|
23
23
|
<div>
|
|
24
|
-
<Typography level="h1"
|
|
25
|
-
<Typography level="body-md"
|
|
24
|
+
<Typography level="h1">Main Heading</Typography>
|
|
25
|
+
<Typography level="body-md">This is body text.</Typography>
|
|
26
26
|
<Typography level="body-sm" color="neutral">
|
|
27
|
-
|
|
27
|
+
This is supporting description text.
|
|
28
28
|
</Typography>
|
|
29
29
|
</div>
|
|
30
30
|
);
|
|
@@ -35,18 +35,18 @@ function MyComponent() {
|
|
|
35
35
|
|
|
36
36
|
### Headings
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Levels for headings. Use them to clearly define page structure.
|
|
39
39
|
|
|
40
40
|
```tsx
|
|
41
|
-
<Typography level="h1">H1 -
|
|
42
|
-
<Typography level="h2">H2 -
|
|
43
|
-
<Typography level="h3">H3 -
|
|
44
|
-
<Typography level="h4">H4 -
|
|
41
|
+
<Typography level="h1">H1 - Main page heading</Typography>
|
|
42
|
+
<Typography level="h2">H2 - Section heading</Typography>
|
|
43
|
+
<Typography level="h3">H3 - Subsection heading</Typography>
|
|
44
|
+
<Typography level="h4">H4 - Detailed heading</Typography>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
### Titles
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Used for important titles or emphasized text.
|
|
50
50
|
|
|
51
51
|
```tsx
|
|
52
52
|
<Typography level="title-lg">Large Title</Typography>
|
|
@@ -56,13 +56,13 @@ function MyComponent() {
|
|
|
56
56
|
|
|
57
57
|
### Body Text
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Levels for body text. Use these for most readable content.
|
|
60
60
|
|
|
61
61
|
```tsx
|
|
62
|
-
<Typography level="body-lg"
|
|
63
|
-
<Typography level="body-md"
|
|
64
|
-
<Typography level="body-sm"
|
|
65
|
-
<Typography level="body-xs"
|
|
62
|
+
<Typography level="body-lg">Large body text</Typography>
|
|
63
|
+
<Typography level="body-md">Regular body text</Typography>
|
|
64
|
+
<Typography level="body-sm">Small body text</Typography>
|
|
65
|
+
<Typography level="body-xs">Extra small text</Typography>
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
## Common Use Cases
|
|
@@ -74,24 +74,24 @@ function ArticlePage() {
|
|
|
74
74
|
return (
|
|
75
75
|
<article>
|
|
76
76
|
<Typography level="h1" sx={{ mb: 2 }}>
|
|
77
|
-
|
|
77
|
+
Article Title
|
|
78
78
|
</Typography>
|
|
79
79
|
|
|
80
80
|
<Typography level="body-sm" color="neutral" sx={{ mb: 3 }}>
|
|
81
|
-
|
|
81
|
+
January 15, 2024 · Written by John Doe
|
|
82
82
|
</Typography>
|
|
83
83
|
|
|
84
84
|
<Typography level="body-md" sx={{ mb: 2 }}>
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
The main content of the article goes here. This text uses a readable size
|
|
86
|
+
and line spacing.
|
|
87
87
|
</Typography>
|
|
88
88
|
|
|
89
89
|
<Typography level="h2" sx={{ mt: 4, mb: 2 }}>
|
|
90
|
-
|
|
90
|
+
Section Title
|
|
91
91
|
</Typography>
|
|
92
92
|
|
|
93
93
|
<Typography level="body-md">
|
|
94
|
-
|
|
94
|
+
The section content continues here.
|
|
95
95
|
</Typography>
|
|
96
96
|
</article>
|
|
97
97
|
);
|
|
@@ -104,15 +104,15 @@ function ArticlePage() {
|
|
|
104
104
|
<Card>
|
|
105
105
|
<CardContent>
|
|
106
106
|
<Typography level="title-md" sx={{ mb: 1 }}>
|
|
107
|
-
|
|
107
|
+
Product Name
|
|
108
108
|
</Typography>
|
|
109
109
|
|
|
110
110
|
<Typography level="body-sm" color="neutral" sx={{ mb: 2 }}>
|
|
111
|
-
|
|
111
|
+
Category: Electronics
|
|
112
112
|
</Typography>
|
|
113
113
|
|
|
114
114
|
<Typography level="body-md" sx={{ mb: 2 }}>
|
|
115
|
-
|
|
115
|
+
A detailed description of the product goes here.
|
|
116
116
|
</Typography>
|
|
117
117
|
|
|
118
118
|
<Typography level="title-lg" color="primary">
|
|
@@ -128,21 +128,21 @@ function ArticlePage() {
|
|
|
128
128
|
<Stack spacing={2}>
|
|
129
129
|
<FormControl>
|
|
130
130
|
<Typography level="title-sm" component="label">
|
|
131
|
-
|
|
131
|
+
Username
|
|
132
132
|
</Typography>
|
|
133
|
-
<Input placeholder="
|
|
133
|
+
<Input placeholder="Enter your name" />
|
|
134
134
|
<Typography level="body-xs" color="neutral">
|
|
135
|
-
|
|
135
|
+
Please enter your real name.
|
|
136
136
|
</Typography>
|
|
137
137
|
</FormControl>
|
|
138
138
|
|
|
139
139
|
<FormControl error>
|
|
140
140
|
<Typography level="title-sm" component="label">
|
|
141
|
-
|
|
141
|
+
Email Address
|
|
142
142
|
</Typography>
|
|
143
143
|
<Input placeholder="email@example.com" />
|
|
144
144
|
<Typography level="body-xs" color="danger">
|
|
145
|
-
|
|
145
|
+
The email format is invalid.
|
|
146
146
|
</Typography>
|
|
147
147
|
</FormControl>
|
|
148
148
|
</Stack>
|
|
@@ -153,16 +153,16 @@ function ArticlePage() {
|
|
|
153
153
|
```tsx
|
|
154
154
|
<Stack spacing={2}>
|
|
155
155
|
<Box>
|
|
156
|
-
<Typography level="body-md"
|
|
156
|
+
<Typography level="body-md">Server Status:</Typography>
|
|
157
157
|
<Typography level="body-md" color="success">
|
|
158
|
-
|
|
158
|
+
Operating Normally
|
|
159
159
|
</Typography>
|
|
160
160
|
</Box>
|
|
161
161
|
|
|
162
162
|
<Box>
|
|
163
|
-
<Typography level="body-md"
|
|
163
|
+
<Typography level="body-md">Last Updated:</Typography>
|
|
164
164
|
<Typography level="body-sm" color="neutral">
|
|
165
|
-
2
|
|
165
|
+
2 minutes ago
|
|
166
166
|
</Typography>
|
|
167
167
|
</Box>
|
|
168
168
|
</Stack>
|
|
@@ -172,7 +172,7 @@ function ArticlePage() {
|
|
|
172
172
|
|
|
173
173
|
```tsx
|
|
174
174
|
<Stack spacing={1}>
|
|
175
|
-
<Typography level="title-md"
|
|
175
|
+
<Typography level="title-md">Todo List</Typography>
|
|
176
176
|
|
|
177
177
|
{todoItems.map((item) => (
|
|
178
178
|
<Box key={item.id} sx={{ pl: 2 }}>
|
|
@@ -195,39 +195,39 @@ function ArticlePage() {
|
|
|
195
195
|
|
|
196
196
|
## Colors
|
|
197
197
|
|
|
198
|
-
Typography
|
|
198
|
+
Typography supports various colors:
|
|
199
199
|
|
|
200
200
|
```tsx
|
|
201
201
|
<Stack spacing={1}>
|
|
202
|
-
<Typography color="primary">Primary
|
|
203
|
-
<Typography color="neutral">Neutral
|
|
204
|
-
<Typography color="danger">Danger
|
|
205
|
-
<Typography color="success">Success
|
|
206
|
-
<Typography color="warning">Warning
|
|
202
|
+
<Typography color="primary">Primary color</Typography>
|
|
203
|
+
<Typography color="neutral">Neutral color</Typography>
|
|
204
|
+
<Typography color="danger">Danger color</Typography>
|
|
205
|
+
<Typography color="success">Success color</Typography>
|
|
206
|
+
<Typography color="warning">Warning color</Typography>
|
|
207
207
|
</Stack>
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
## Component Prop
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
You can render it as a different HTML element or React component:
|
|
213
213
|
|
|
214
214
|
```tsx
|
|
215
215
|
<Typography level="h1" component="h2">
|
|
216
|
-
|
|
216
|
+
h1 style rendered as an h2 tag
|
|
217
217
|
</Typography>
|
|
218
218
|
|
|
219
219
|
<Typography level="body-md" component="span">
|
|
220
|
-
|
|
220
|
+
Inline text
|
|
221
221
|
</Typography>
|
|
222
222
|
|
|
223
223
|
<Typography level="title-md" component={Link} href="/page">
|
|
224
|
-
|
|
224
|
+
Rendered as a Link component
|
|
225
225
|
</Typography>
|
|
226
226
|
```
|
|
227
227
|
|
|
228
228
|
## Responsive Typography
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
You can use responsive levels:
|
|
231
231
|
|
|
232
232
|
```tsx
|
|
233
233
|
<Typography
|
|
@@ -236,36 +236,36 @@ Typography는 다양한 색상을 지원합니다:
|
|
|
236
236
|
fontSize: { xs: '1.5rem', sm: '2rem', md: '2.5rem' }
|
|
237
237
|
}}
|
|
238
238
|
>
|
|
239
|
-
|
|
239
|
+
Responsive Heading
|
|
240
240
|
</Typography>
|
|
241
241
|
```
|
|
242
242
|
|
|
243
243
|
## Best Practices
|
|
244
244
|
|
|
245
|
-
1.
|
|
245
|
+
1. **Semantic Structure**: Use heading levels in order to create a clear document structure.
|
|
246
246
|
|
|
247
247
|
```tsx
|
|
248
|
-
// ✅
|
|
249
|
-
<Typography level="h1"
|
|
250
|
-
<Typography level="h2"
|
|
251
|
-
<Typography level="h3"
|
|
252
|
-
|
|
253
|
-
// ❌
|
|
254
|
-
<Typography level="h1"
|
|
255
|
-
<Typography level="h3"
|
|
248
|
+
// ✅ Correct order
|
|
249
|
+
<Typography level="h1">Main heading</Typography>
|
|
250
|
+
<Typography level="h2">Section heading</Typography>
|
|
251
|
+
<Typography level="h3">Subsection</Typography>
|
|
252
|
+
|
|
253
|
+
// ❌ Incorrect order
|
|
254
|
+
<Typography level="h1">Main heading</Typography>
|
|
255
|
+
<Typography level="h3">Section heading</Typography>
|
|
256
256
|
```
|
|
257
257
|
|
|
258
|
-
2.
|
|
258
|
+
2. **Consistency**: Use the same level for text serving the same purpose.
|
|
259
259
|
|
|
260
|
-
3.
|
|
260
|
+
3. **Readability**: Provide proper line spacing and paragraph separation for body text.
|
|
261
261
|
|
|
262
|
-
4.
|
|
262
|
+
4. **Color Contrast**: Maintain sufficient color contrast to ensure accessibility.
|
|
263
263
|
|
|
264
264
|
## Accessibility
|
|
265
265
|
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
266
|
+
- Use appropriate semantic HTML tags
|
|
267
|
+
- Support screen readers
|
|
268
|
+
- Ensure keyboard navigation (when used as a link or button)
|
|
269
|
+
- Maintain sufficient color contrast
|
|
270
270
|
|
|
271
|
-
Typography
|
|
271
|
+
Typography plays a key role in effectively conveying information and creating visual hierarchy in user interfaces. By choosing appropriate levels and styles, you can create content that is easy to read and accessible.
|
|
@@ -41,15 +41,7 @@ The Modal component is a dialog overlay that appears on top of the main content,
|
|
|
41
41
|
## Usage
|
|
42
42
|
|
|
43
43
|
```tsx
|
|
44
|
-
import {
|
|
45
|
-
Modal,
|
|
46
|
-
ModalDialog,
|
|
47
|
-
ModalClose,
|
|
48
|
-
DialogTitle,
|
|
49
|
-
DialogContent,
|
|
50
|
-
DialogActions,
|
|
51
|
-
Button,
|
|
52
|
-
} from '@ceed/ads';
|
|
44
|
+
import { Modal, ModalDialog, ModalClose, DialogTitle, DialogContent, DialogActions, Button } from '@ceed/ads';
|
|
53
45
|
|
|
54
46
|
function MyComponent() {
|
|
55
47
|
const [open, setOpen] = useState(false);
|
|
@@ -61,9 +53,7 @@ function MyComponent() {
|
|
|
61
53
|
<ModalDialog>
|
|
62
54
|
<ModalClose />
|
|
63
55
|
<DialogTitle>Modal Title</DialogTitle>
|
|
64
|
-
<DialogContent>
|
|
65
|
-
Place your content here.
|
|
66
|
-
</DialogContent>
|
|
56
|
+
<DialogContent>Place your content here.</DialogContent>
|
|
67
57
|
<DialogActions>
|
|
68
58
|
<Button onClick={() => setOpen(false)}>Close</Button>
|
|
69
59
|
</DialogActions>
|
|
@@ -74,6 +64,28 @@ function MyComponent() {
|
|
|
74
64
|
}
|
|
75
65
|
```
|
|
76
66
|
|
|
67
|
+
### ModalFrame Usage
|
|
68
|
+
|
|
69
|
+
`ModalFrame` is a convenience component that combines `ModalDialog` + `ModalClose` + `DialogTitle` + `DialogContent` into a single composable unit.
|
|
70
|
+
It provides a concise way to build modals with a title, close button, and content area.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Modal, ModalFrame } from '@ceed/ads';
|
|
74
|
+
|
|
75
|
+
function DetailModal({ open, onClose }) {
|
|
76
|
+
return (
|
|
77
|
+
<Modal open={open} onClose={onClose}>
|
|
78
|
+
<ModalFrame title="Detail" onClose={onClose}>
|
|
79
|
+
Content goes here.
|
|
80
|
+
</ModalFrame>
|
|
81
|
+
</Modal>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **Note**: Connect the same handler to both `Modal`'s `onClose` and `ModalFrame`'s `onClose`.
|
|
87
|
+
> `Modal` handles backdrop click and ESC key, while `ModalFrame` handles the X button click.
|
|
88
|
+
|
|
77
89
|
## Examples
|
|
78
90
|
|
|
79
91
|
### Basic Modal
|
|
@@ -292,6 +304,162 @@ Modals can be stacked on top of each other when necessary.
|
|
|
292
304
|
</>
|
|
293
305
|
```
|
|
294
306
|
|
|
307
|
+
### ModalFrame
|
|
308
|
+
|
|
309
|
+
ModalFrame is a convenience component that automatically provides a title, close button, and content area.
|
|
310
|
+
|
|
311
|
+
#### ModalFrame Playground
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
<>
|
|
315
|
+
<Button onClick={() => setOpen(true)}>Open ModalFrame</Button>
|
|
316
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
317
|
+
<ModalFrame title="ModalFrame Title" onClose={() => setOpen(false)}>
|
|
318
|
+
<Typography>
|
|
319
|
+
ModalFrame automatically composes ModalDialog, ModalClose, DialogTitle, and DialogContent. You only need
|
|
320
|
+
to provide a title, onClose handler, and children.
|
|
321
|
+
</Typography>
|
|
322
|
+
</ModalFrame>
|
|
323
|
+
</Modal>
|
|
324
|
+
</>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### titleStartDecorator
|
|
328
|
+
|
|
329
|
+
Display an icon or decorative element before the title.
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
<>
|
|
333
|
+
<Button onClick={() => setOpen(true)}>With Decorator</Button>
|
|
334
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
335
|
+
<ModalFrame title="Details" titleStartDecorator={<InfoOutlinedIcon />} onClose={() => setOpen(false)}>
|
|
336
|
+
<Typography>
|
|
337
|
+
Use the <code>titleStartDecorator</code> prop to display an icon or element before the title.
|
|
338
|
+
</Typography>
|
|
339
|
+
</ModalFrame>
|
|
340
|
+
</Modal>
|
|
341
|
+
</>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Form Content
|
|
345
|
+
|
|
346
|
+
An inline form pattern where the submit button lives inside the content area.
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
<>
|
|
350
|
+
<Button onClick={() => setOpen(true)}>Form in ModalFrame</Button>
|
|
351
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
352
|
+
<ModalFrame title="Create Project" onClose={() => setOpen(false)}>
|
|
353
|
+
<form onSubmit={(event: React.FormEvent<HTMLFormElement>) => {
|
|
354
|
+
event.preventDefault();
|
|
355
|
+
setOpen(false);
|
|
356
|
+
}}>
|
|
357
|
+
<Stack spacing={2}>
|
|
358
|
+
<FormControl>
|
|
359
|
+
<FormLabel>Name</FormLabel>
|
|
360
|
+
<Input required />
|
|
361
|
+
</FormControl>
|
|
362
|
+
<FormControl>
|
|
363
|
+
<FormLabel>Description</FormLabel>
|
|
364
|
+
<Input required />
|
|
365
|
+
</FormControl>
|
|
366
|
+
<Button type="submit">Submit</Button>
|
|
367
|
+
</Stack>
|
|
368
|
+
</form>
|
|
369
|
+
</ModalFrame>
|
|
370
|
+
</Modal>
|
|
371
|
+
</>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Sizes
|
|
375
|
+
|
|
376
|
+
Compare sm / md / lg sizes side by side.
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
<Stack direction="row" spacing={2}>
|
|
380
|
+
<Button size="sm" onClick={() => setOpenSm(true)}>
|
|
381
|
+
Small
|
|
382
|
+
</Button>
|
|
383
|
+
<Button size="md" onClick={() => setOpenMd(true)}>
|
|
384
|
+
Medium
|
|
385
|
+
</Button>
|
|
386
|
+
<Button size="lg" onClick={() => setOpenLg(true)}>
|
|
387
|
+
Large
|
|
388
|
+
</Button>
|
|
389
|
+
<Modal open={openSm} onClose={() => setOpenSm(false)}>
|
|
390
|
+
<ModalFrame title="Small ModalFrame" size="sm" onClose={() => setOpenSm(false)}>
|
|
391
|
+
<Typography>This is a small ModalFrame.</Typography>
|
|
392
|
+
</ModalFrame>
|
|
393
|
+
</Modal>
|
|
394
|
+
<Modal open={openMd} onClose={() => setOpenMd(false)}>
|
|
395
|
+
<ModalFrame title="Medium ModalFrame" size="md" onClose={() => setOpenMd(false)}>
|
|
396
|
+
<Typography>This is a medium ModalFrame.</Typography>
|
|
397
|
+
</ModalFrame>
|
|
398
|
+
</Modal>
|
|
399
|
+
<Modal open={openLg} onClose={() => setOpenLg(false)}>
|
|
400
|
+
<ModalFrame title="Large ModalFrame" size="lg" onClose={() => setOpenLg(false)}>
|
|
401
|
+
<Typography>This is a large ModalFrame.</Typography>
|
|
402
|
+
</ModalFrame>
|
|
403
|
+
</Modal>
|
|
404
|
+
</Stack>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
#### Custom Content
|
|
408
|
+
|
|
409
|
+
A layout example suited for displaying detailed information.
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
<>
|
|
413
|
+
<Button onClick={() => setOpen(true)}>Custom Content</Button>
|
|
414
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
415
|
+
<ModalFrame title="Order Details" onClose={() => setOpen(false)}>
|
|
416
|
+
<Stack spacing={2}>
|
|
417
|
+
<Box>
|
|
418
|
+
<Typography level="title-sm">Order ID</Typography>
|
|
419
|
+
<Typography level="body-sm">ORD-2024-00123</Typography>
|
|
420
|
+
</Box>
|
|
421
|
+
<Divider />
|
|
422
|
+
<Box>
|
|
423
|
+
<Typography level="title-sm">Customer</Typography>
|
|
424
|
+
<Typography level="body-sm">John Doe</Typography>
|
|
425
|
+
</Box>
|
|
426
|
+
<Divider />
|
|
427
|
+
<Box>
|
|
428
|
+
<Typography level="title-sm">Status</Typography>
|
|
429
|
+
<Typography level="body-sm" color="success">
|
|
430
|
+
Completed
|
|
431
|
+
</Typography>
|
|
432
|
+
</Box>
|
|
433
|
+
</Stack>
|
|
434
|
+
</ModalFrame>
|
|
435
|
+
</Modal>
|
|
436
|
+
</>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
#### Standalone
|
|
440
|
+
|
|
441
|
+
ModalFrame can be used without a Modal wrapper for embedding dialog-style layouts directly within a page.
|
|
442
|
+
|
|
443
|
+
> ⚠️ **Important** ⚠️
|
|
444
|
+
>
|
|
445
|
+
> When using ModalFrame without Modal, the parent container **must** provide explicit `width` and `height` values.
|
|
446
|
+
> ModalFrame inherits its dimensions from `ModalDialog`, which normally receives sizing from the Modal overlay.
|
|
447
|
+
> Without these constraints, the component will not render with correct dimensions.
|
|
448
|
+
|
|
449
|
+
```tsx
|
|
450
|
+
<Box sx={{
|
|
451
|
+
width: 480,
|
|
452
|
+
height: 300
|
|
453
|
+
}}>
|
|
454
|
+
<ModalFrame title="Standalone ModalFrame" onClose={() => console.log('close')}>
|
|
455
|
+
<Typography>
|
|
456
|
+
ModalFrame used without Modal. The parent container must provide
|
|
457
|
+
explicit width and height.
|
|
458
|
+
</Typography>
|
|
459
|
+
</ModalFrame>
|
|
460
|
+
</Box>
|
|
461
|
+
```
|
|
462
|
+
|
|
295
463
|
## When to Use
|
|
296
464
|
|
|
297
465
|
### ✅ Good Use Cases
|
|
@@ -327,8 +495,7 @@ function DeleteConfirmation({ item, onDelete, onCancel }) {
|
|
|
327
495
|
</DialogTitle>
|
|
328
496
|
<Divider />
|
|
329
497
|
<DialogContent>
|
|
330
|
-
This action cannot be undone. All data associated with this item
|
|
331
|
-
will be permanently removed.
|
|
498
|
+
This action cannot be undone. All data associated with this item will be permanently removed.
|
|
332
499
|
</DialogContent>
|
|
333
500
|
<DialogActions>
|
|
334
501
|
<Button variant="solid" color="danger" onClick={onDelete}>
|
|
@@ -404,8 +571,7 @@ function TermsModal({ open, onAccept, onDecline }) {
|
|
|
404
571
|
<DialogTitle>Terms of Service</DialogTitle>
|
|
405
572
|
<DialogContent>
|
|
406
573
|
<Typography level="body-sm">
|
|
407
|
-
Please read and accept the following terms and conditions before
|
|
408
|
-
proceeding...
|
|
574
|
+
Please read and accept the following terms and conditions before proceeding...
|
|
409
575
|
</Typography>
|
|
410
576
|
{/* Terms content */}
|
|
411
577
|
</DialogContent>
|
|
@@ -433,11 +599,7 @@ function ImagePreviewModal({ image, open, onClose }) {
|
|
|
433
599
|
<Modal open={open} onClose={onClose}>
|
|
434
600
|
<ModalDialog layout="center" sx={{ p: 0, overflow: 'hidden' }}>
|
|
435
601
|
<ModalClose sx={{ top: 8, right: 8, zIndex: 1 }} />
|
|
436
|
-
<img
|
|
437
|
-
src={image.src}
|
|
438
|
-
alt={image.alt}
|
|
439
|
-
style={{ maxWidth: '90vw', maxHeight: '90vh', objectFit: 'contain' }}
|
|
440
|
-
/>
|
|
602
|
+
<img src={image.src} alt={image.alt} style={{ maxWidth: '90vw', maxHeight: '90vh', objectFit: 'contain' }} />
|
|
441
603
|
</ModalDialog>
|
|
442
604
|
</Modal>
|
|
443
605
|
);
|
|
@@ -468,22 +630,69 @@ function LoadingModal({ open, message }) {
|
|
|
468
630
|
Modal uses a composition pattern with multiple sub-components:
|
|
469
631
|
|
|
470
632
|
```tsx
|
|
471
|
-
<Modal>
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
633
|
+
<Modal>
|
|
634
|
+
{/* Overlay and backdrop */}
|
|
635
|
+
<ModalDialog>
|
|
636
|
+
{/* Dialog container */}
|
|
637
|
+
<ModalClose /> {/* Close button (optional) */}
|
|
638
|
+
<DialogTitle>
|
|
639
|
+
{/* Header */}
|
|
475
640
|
Title
|
|
476
641
|
</DialogTitle>
|
|
477
|
-
<DialogContent>
|
|
642
|
+
<DialogContent>
|
|
643
|
+
{/* Body */}
|
|
478
644
|
Content goes here
|
|
479
645
|
</DialogContent>
|
|
480
|
-
<DialogActions>
|
|
646
|
+
<DialogActions>
|
|
647
|
+
{/* Footer */}
|
|
481
648
|
<Button>Action</Button>
|
|
482
649
|
</DialogActions>
|
|
483
650
|
</ModalDialog>
|
|
484
651
|
</Modal>
|
|
485
652
|
```
|
|
486
653
|
|
|
654
|
+
## Component Roles
|
|
655
|
+
|
|
656
|
+
| Component | Role | When to Use |
|
|
657
|
+
| ----------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
658
|
+
| **Modal** | Overlay backdrop, open/close state management | Always required as the outermost wrapper |
|
|
659
|
+
| **ModalDialog** | Dialog container (variant/size/layout) | When you need direct control over layout |
|
|
660
|
+
| **ModalClose** | Close (X) button in the top-right corner | When users should be able to close via a button |
|
|
661
|
+
| **ModalOverflow** | Scrollable area | When content exceeds the viewport |
|
|
662
|
+
| **ModalFrame** | Combines ModalDialog + ModalClose + DialogTitle + DialogContent | When you only need a title + close + content (no action buttons) |
|
|
663
|
+
| **DialogTitle** | Header area (styled padding) | When composing manually |
|
|
664
|
+
| **DialogContent** | Body area (styled padding) | When composing manually |
|
|
665
|
+
| **DialogActions** | Footer action button area | When confirm/cancel buttons are needed |
|
|
666
|
+
|
|
667
|
+
## Choosing the Right Component
|
|
668
|
+
|
|
669
|
+
### ModalFrame vs DialogFrame
|
|
670
|
+
|
|
671
|
+
| | ModalFrame | DialogFrame |
|
|
672
|
+
| ------------------ | ----------------------------------------------- | --------------------------------------- |
|
|
673
|
+
| Close (X) button | Built-in | None |
|
|
674
|
+
| Title decorator | `titleStartDecorator` | None |
|
|
675
|
+
| Action button area | None | `actions` prop (required) |
|
|
676
|
+
| Fullscreen | `layout="fullscreen"` | `fullscreen` prop |
|
|
677
|
+
| Best for | Information display, detail views, inline forms | Confirm/cancel dialogs, decision-making |
|
|
678
|
+
|
|
679
|
+
### Use ModalFrame when
|
|
680
|
+
|
|
681
|
+
- You need an informational modal with a close button (detail views, previews)
|
|
682
|
+
- The form's submit button lives inside the content area
|
|
683
|
+
- You need an icon next to the title
|
|
684
|
+
|
|
685
|
+
### Use DialogFrame when
|
|
686
|
+
|
|
687
|
+
- Explicit action buttons (confirm/cancel) must be pinned to the bottom
|
|
688
|
+
- User decisions are required (delete confirmation, save confirmation)
|
|
689
|
+
- Only explicit choices should be allowed without a close (X) button
|
|
690
|
+
|
|
691
|
+
### Use manual composition when
|
|
692
|
+
|
|
693
|
+
- You need a custom layout that doesn't fit the ModalFrame/DialogFrame pattern
|
|
694
|
+
- You want to use both ModalClose and DialogActions together
|
|
695
|
+
|
|
487
696
|
## Props and Customization
|
|
488
697
|
|
|
489
698
|
### Modal Props
|
|
@@ -505,6 +714,17 @@ Modal uses a composition pattern with multiple sub-components:
|
|
|
505
714
|
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Dialog size |
|
|
506
715
|
| `layout` | `'center' \| 'fullscreen'` | `'center'` | Layout mode |
|
|
507
716
|
|
|
717
|
+
### ModalFrame Props
|
|
718
|
+
|
|
719
|
+
| Prop | Type | Default | Description |
|
|
720
|
+
| --------------------- | ------------ | ------- | ------------------------------------------ |
|
|
721
|
+
| `title` | `ReactNode` | - | Title displayed in the header |
|
|
722
|
+
| `children` | `ReactNode` | - | Body content |
|
|
723
|
+
| `titleStartDecorator` | `ReactNode` | - | Icon or element displayed before the title |
|
|
724
|
+
| `onClose` | `() => void` | - | Callback when the close button is clicked |
|
|
725
|
+
|
|
726
|
+
ModalFrame accepts all ModalDialog props (`variant`, `color`, `size`, `layout`, `sx`, etc.).
|
|
727
|
+
|
|
508
728
|
### Custom Styling
|
|
509
729
|
|
|
510
730
|
```tsx
|
|
@@ -543,17 +763,10 @@ Modal components include comprehensive accessibility features:
|
|
|
543
763
|
- `aria-describedby` connects to DialogContent
|
|
544
764
|
|
|
545
765
|
```tsx
|
|
546
|
-
<Modal
|
|
547
|
-
open={open}
|
|
548
|
-
onClose={onClose}
|
|
549
|
-
aria-labelledby="modal-title"
|
|
550
|
-
aria-describedby="modal-description"
|
|
551
|
-
>
|
|
766
|
+
<Modal open={open} onClose={onClose} aria-labelledby="modal-title" aria-describedby="modal-description">
|
|
552
767
|
<ModalDialog>
|
|
553
768
|
<DialogTitle id="modal-title">Accessible Title</DialogTitle>
|
|
554
|
-
<DialogContent id="modal-description">
|
|
555
|
-
This content is read by screen readers.
|
|
556
|
-
</DialogContent>
|
|
769
|
+
<DialogContent id="modal-description">This content is read by screen readers.</DialogContent>
|
|
557
770
|
</ModalDialog>
|
|
558
771
|
</Modal>
|
|
559
772
|
```
|
|
@@ -582,7 +795,9 @@ Modal components include comprehensive accessibility features:
|
|
|
582
795
|
```tsx
|
|
583
796
|
// ✅ Good: Clear action buttons
|
|
584
797
|
<DialogActions>
|
|
585
|
-
<Button variant="solid" color="danger">
|
|
798
|
+
<Button variant="solid" color="danger">
|
|
799
|
+
Delete
|
|
800
|
+
</Button>
|
|
586
801
|
<Button variant="plain">Cancel</Button>
|
|
587
802
|
</DialogActions>
|
|
588
803
|
```
|
|
@@ -657,15 +872,11 @@ Use `keepMounted` only when the modal needs to preserve state between openings:
|
|
|
657
872
|
Memoize modal content when it depends on complex data:
|
|
658
873
|
|
|
659
874
|
```tsx
|
|
660
|
-
const modalContent = useMemo(() =>
|
|
661
|
-
<ComplexContent data={data} />
|
|
662
|
-
), [data]);
|
|
875
|
+
const modalContent = useMemo(() => <ComplexContent data={data} />, [data]);
|
|
663
876
|
|
|
664
877
|
<Modal open={open} onClose={onClose}>
|
|
665
|
-
<ModalDialog>
|
|
666
|
-
|
|
667
|
-
</ModalDialog>
|
|
668
|
-
</Modal>
|
|
878
|
+
<ModalDialog>{modalContent}</ModalDialog>
|
|
879
|
+
</Modal>;
|
|
669
880
|
```
|
|
670
881
|
|
|
671
882
|
Modal is a powerful component for focused user interactions. Use it thoughtfully to maintain a smooth user experience while capturing important decisions and inputs.
|