@ceed/cds 1.24.1-next.3 → 1.25.0
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/dist/chunks/rehype-accent-FZRUD7VI.js +39 -0
- package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
- package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
- package/dist/components/DataTable/components.d.ts +2 -1
- package/dist/components/DataTable/styled.d.ts +3 -1
- package/dist/components/DataTable/types.d.ts +1 -0
- package/dist/components/RadioTileGroup/RadioTileGroup.d.ts +56 -0
- package/dist/components/RadioTileGroup/index.d.ts +3 -0
- package/dist/components/data-display/DataTable.md +77 -1
- package/dist/components/data-display/InfoSign.md +74 -91
- package/dist/components/data-display/Typography.md +411 -94
- package/dist/components/feedback/CircularProgress.md +257 -0
- package/dist/components/feedback/Dialog.md +76 -62
- package/dist/components/feedback/Modal.md +430 -138
- package/dist/components/feedback/Skeleton.md +280 -0
- package/dist/components/feedback/llms.txt +2 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/inputs/Autocomplete.md +356 -107
- package/dist/components/inputs/ButtonGroup.md +115 -104
- package/dist/components/inputs/CurrencyInput.md +183 -5
- package/dist/components/inputs/DatePicker.md +108 -431
- package/dist/components/inputs/DateRangePicker.md +131 -492
- package/dist/components/inputs/FilterableCheckboxGroup.md +145 -19
- package/dist/components/inputs/FormControl.md +361 -0
- package/dist/components/inputs/IconButton.md +137 -88
- package/dist/components/inputs/Input.md +204 -73
- package/dist/components/inputs/MonthPicker.md +95 -422
- package/dist/components/inputs/MonthRangePicker.md +89 -466
- package/dist/components/inputs/PercentageInput.md +185 -16
- package/dist/components/inputs/RadioButton.md +163 -35
- package/dist/components/inputs/RadioList.md +241 -0
- package/dist/components/inputs/RadioTileGroup.md +507 -0
- package/dist/components/inputs/Select.md +222 -326
- package/dist/components/inputs/Slider.md +334 -0
- package/dist/components/inputs/Switch.md +143 -376
- package/dist/components/inputs/Textarea.md +213 -10
- package/dist/components/inputs/Uploader/Uploader.md +145 -66
- package/dist/components/inputs/llms.txt +4 -0
- package/dist/components/navigation/Breadcrumbs.md +57 -308
- package/dist/components/navigation/Drawer.md +180 -0
- package/dist/components/navigation/Dropdown.md +98 -215
- package/dist/components/navigation/IconMenuButton.md +40 -502
- package/dist/components/navigation/InsetDrawer.md +281 -650
- package/dist/components/navigation/Link.md +31 -348
- package/dist/components/navigation/Menu.md +92 -285
- package/dist/components/navigation/MenuButton.md +55 -448
- package/dist/components/navigation/Pagination.md +47 -338
- package/dist/components/navigation/Stepper.md +160 -28
- package/dist/components/navigation/Tabs.md +57 -316
- package/dist/components/surfaces/Accordions.md +49 -804
- package/dist/components/surfaces/Card.md +97 -157
- package/dist/components/surfaces/Divider.md +83 -234
- package/dist/components/surfaces/Sheet.md +153 -328
- package/dist/guides/ThemeProvider.md +89 -0
- package/dist/guides/llms.txt +9 -0
- package/dist/index.browser.js +224 -0
- package/dist/index.browser.js.map +7 -0
- package/dist/index.cjs +648 -390
- package/dist/index.d.ts +1 -1
- package/dist/index.js +563 -361
- package/dist/llms.txt +9 -0
- package/framer/index.js +1 -163
- package/package.json +22 -17
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# CircularProgress
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
The CircularProgress component displays a circular loading indicator. It is based on Joy UI's CircularProgress and supports both indeterminate (spinning) and determinate (progress percentage) modes. Use it to provide visual feedback during asynchronous operations like data fetching, file uploads, or form submissions.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<CircularProgress />
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Field | Description | Default |
|
|
12
|
+
| ----------- | ----------- | ------- |
|
|
13
|
+
| size | — | — |
|
|
14
|
+
| color | — | — |
|
|
15
|
+
| variant | — | — |
|
|
16
|
+
| value | — | — |
|
|
17
|
+
| determinate | — | — |
|
|
18
|
+
| thickness | — | — |
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { CircularProgress } from '@ceed/cds';
|
|
24
|
+
|
|
25
|
+
function MyComponent() {
|
|
26
|
+
return <CircularProgress />;
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Sizes
|
|
31
|
+
|
|
32
|
+
CircularProgress supports three sizes: `sm`, `md` (default), and `lg`.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<>
|
|
36
|
+
<CircularProgress size="sm" />
|
|
37
|
+
<CircularProgress size="md" />
|
|
38
|
+
<CircularProgress size="lg" />
|
|
39
|
+
</>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<CircularProgress size="sm" />
|
|
44
|
+
<CircularProgress size="md" />
|
|
45
|
+
<CircularProgress size="lg" />
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Colors
|
|
49
|
+
|
|
50
|
+
Five semantic colors are available via the `color` prop. The default is `primary`.
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<>
|
|
54
|
+
<CircularProgress color="primary" />
|
|
55
|
+
<CircularProgress color="neutral" />
|
|
56
|
+
<CircularProgress color="danger" />
|
|
57
|
+
<CircularProgress color="success" />
|
|
58
|
+
<CircularProgress color="warning" />
|
|
59
|
+
</>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<CircularProgress color="primary" />
|
|
64
|
+
<CircularProgress color="neutral" />
|
|
65
|
+
<CircularProgress color="danger" />
|
|
66
|
+
<CircularProgress color="success" />
|
|
67
|
+
<CircularProgress color="warning" />
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Variants
|
|
71
|
+
|
|
72
|
+
Four visual variants are supported: `solid`, `soft` (default), `outlined`, and `plain`.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<>
|
|
76
|
+
<CircularProgress variant="solid" />
|
|
77
|
+
<CircularProgress variant="soft" />
|
|
78
|
+
<CircularProgress variant="outlined" />
|
|
79
|
+
<CircularProgress variant="plain" />
|
|
80
|
+
</>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<CircularProgress variant="solid" />
|
|
85
|
+
<CircularProgress variant="soft" />
|
|
86
|
+
<CircularProgress variant="outlined" />
|
|
87
|
+
<CircularProgress variant="plain" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Determinate Mode
|
|
91
|
+
|
|
92
|
+
Set `determinate` to `true` and provide a `value` (0–100) to display specific progress.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<>
|
|
96
|
+
<CircularProgress determinate value={25} />
|
|
97
|
+
<CircularProgress determinate value={50} />
|
|
98
|
+
<CircularProgress determinate value={75} />
|
|
99
|
+
<CircularProgress determinate value={100} />
|
|
100
|
+
</>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<CircularProgress determinate value={25} />
|
|
105
|
+
<CircularProgress determinate value={50} />
|
|
106
|
+
<CircularProgress determinate value={75} />
|
|
107
|
+
<CircularProgress determinate value={100} />
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## With Label
|
|
111
|
+
|
|
112
|
+
Pass children to display a label inside the progress ring. This is useful for showing the current percentage.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<CircularProgress determinate value={66}>
|
|
116
|
+
<Typography level="body-xs">66%</Typography>
|
|
117
|
+
</CircularProgress>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<CircularProgress determinate value={66}>
|
|
122
|
+
<Typography level="body-xs">66%</Typography>
|
|
123
|
+
</CircularProgress>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## In Button
|
|
127
|
+
|
|
128
|
+
Use CircularProgress inside a Button to indicate a loading state.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<>
|
|
132
|
+
<Button startDecorator={<CircularProgress variant="solid" size="sm" />}>
|
|
133
|
+
Loading…
|
|
134
|
+
</Button>
|
|
135
|
+
<Button disabled>
|
|
136
|
+
<CircularProgress variant="soft" size="sm" />
|
|
137
|
+
</Button>
|
|
138
|
+
</>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<Button startDecorator={<CircularProgress variant="solid" size="sm" />}>
|
|
143
|
+
Loading…
|
|
144
|
+
</Button>
|
|
145
|
+
|
|
146
|
+
<Button disabled>
|
|
147
|
+
<CircularProgress variant="soft" size="sm" />
|
|
148
|
+
</Button>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Thickness
|
|
152
|
+
|
|
153
|
+
Control the stroke thickness of the progress ring with the `thickness` prop.
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
<>
|
|
157
|
+
<CircularProgress thickness={2} />
|
|
158
|
+
<CircularProgress thickness={4} />
|
|
159
|
+
<CircularProgress thickness={8} />
|
|
160
|
+
</>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<CircularProgress thickness={2} />
|
|
165
|
+
<CircularProgress thickness={4} />
|
|
166
|
+
<CircularProgress thickness={8} />
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Common Use Cases
|
|
170
|
+
|
|
171
|
+
### Data Fetching Indicator
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
function DataLoader() {
|
|
175
|
+
const [loading, setLoading] = React.useState(true);
|
|
176
|
+
const [data, setData] = React.useState(null);
|
|
177
|
+
|
|
178
|
+
React.useEffect(() => {
|
|
179
|
+
fetchData().then((result) => {
|
|
180
|
+
setData(result);
|
|
181
|
+
setLoading(false);
|
|
182
|
+
});
|
|
183
|
+
}, []);
|
|
184
|
+
|
|
185
|
+
if (loading) {
|
|
186
|
+
return (
|
|
187
|
+
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
|
|
188
|
+
<CircularProgress />
|
|
189
|
+
</Box>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return <DataView data={data} />;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### File Upload Progress
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
function FileUpload({ progress }: { progress: number }) {
|
|
201
|
+
return (
|
|
202
|
+
<Stack direction="row" alignItems="center" spacing={2}>
|
|
203
|
+
<CircularProgress determinate value={progress} size="lg">
|
|
204
|
+
<Typography level="body-xs">{progress}%</Typography>
|
|
205
|
+
</CircularProgress>
|
|
206
|
+
<Typography level="body-md">Uploading file…</Typography>
|
|
207
|
+
</Stack>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Inline Loading Button
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
function SubmitButton({ isSubmitting }: { isSubmitting: boolean }) {
|
|
216
|
+
return (
|
|
217
|
+
<Button
|
|
218
|
+
disabled={isSubmitting}
|
|
219
|
+
startDecorator={
|
|
220
|
+
isSubmitting ? <CircularProgress variant="solid" size="sm" /> : null
|
|
221
|
+
}
|
|
222
|
+
>
|
|
223
|
+
{isSubmitting ? 'Submitting…' : 'Submit'}
|
|
224
|
+
</Button>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Best Practices
|
|
230
|
+
|
|
231
|
+
1. **Use indeterminate for unknown durations**: When you cannot estimate progress, use the default spinning mode. Switch to determinate only when you can track actual progress.
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
// ✅ Unknown duration — indeterminate
|
|
235
|
+
<CircularProgress />
|
|
236
|
+
|
|
237
|
+
// ✅ Known progress — determinate
|
|
238
|
+
<CircularProgress determinate value={uploadProgress} />
|
|
239
|
+
|
|
240
|
+
// ❌ Don't use determinate with a static value for loading
|
|
241
|
+
<CircularProgress determinate value={50} />
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
2. **Size appropriately**: Use `sm` for inline contexts (buttons, table cells), `md` for general use, and `lg` for prominent page-level loading states.
|
|
245
|
+
|
|
246
|
+
3. **Match variant with context**: Use `solid` variant inside solid buttons, and `soft` (default) for standalone usage to maintain visual consistency.
|
|
247
|
+
|
|
248
|
+
4. **Add descriptive text**: Always pair the indicator with text or an `aria-label` so users understand what is loading.
|
|
249
|
+
|
|
250
|
+
5. **Avoid multiple spinners**: Show one loading indicator per distinct loading region. Multiple spinners on a page create visual clutter.
|
|
251
|
+
|
|
252
|
+
## Accessibility
|
|
253
|
+
|
|
254
|
+
- CircularProgress has `role="progressbar"` by default.
|
|
255
|
+
- In determinate mode, `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` are set automatically.
|
|
256
|
+
- Add `aria-label` or nearby descriptive text to explain what is loading (e.g., `aria-label="Loading user data"`).
|
|
257
|
+
- Ensure sufficient color contrast between the progress ring and its background, especially with the `plain` variant.
|
|
@@ -43,9 +43,7 @@ function ConfirmationDialog({ open, onClose, onConfirm }) {
|
|
|
43
43
|
<Button variant="plain" color="neutral" onClick={onClose}>
|
|
44
44
|
Cancel
|
|
45
45
|
</Button>
|
|
46
|
-
<Button onClick={onConfirm}>
|
|
47
|
-
Confirm
|
|
48
|
-
</Button>
|
|
46
|
+
<Button onClick={onConfirm}>Confirm</Button>
|
|
49
47
|
</>
|
|
50
48
|
}
|
|
51
49
|
>
|
|
@@ -94,6 +92,61 @@ Dialog Content
|
|
|
94
92
|
</DialogFrame>
|
|
95
93
|
```
|
|
96
94
|
|
|
95
|
+
### Standalone Usage
|
|
96
|
+
|
|
97
|
+
DialogFrame can be used without a Modal wrapper for embedding dialog-style layouts directly within a page.
|
|
98
|
+
|
|
99
|
+
> ⚠️ **Important** ⚠️
|
|
100
|
+
>
|
|
101
|
+
> When using DialogFrame without Modal, the parent container **must** meet the following requirements:
|
|
102
|
+
>
|
|
103
|
+
> - `position: 'relative'` — DialogFrame uses absolute positioning internally
|
|
104
|
+
> - Explicit `width` and `height` — `height` must be an absolute value (e.g., `300`, `'400px'`), not a relative value like `%` or `auto`
|
|
105
|
+
>
|
|
106
|
+
> DialogFrame inherits its dimensions from `ModalDialog`, which normally receives sizing from the Modal overlay. Without these constraints, the component will not render with correct dimensions.
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<Box sx={{
|
|
110
|
+
position: 'relative',
|
|
111
|
+
width: 480,
|
|
112
|
+
height: 300
|
|
113
|
+
}}>
|
|
114
|
+
<DialogFrame {...args} title="Standalone Dialog" actions={<>
|
|
115
|
+
<Button variant="plain" color="neutral">
|
|
116
|
+
Cancel
|
|
117
|
+
</Button>
|
|
118
|
+
<Button variant="plain">Confirm</Button>
|
|
119
|
+
</>}>
|
|
120
|
+
DialogFrame used without Modal. The parent container must provide explicit width and height.
|
|
121
|
+
</DialogFrame>
|
|
122
|
+
</Box>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { DialogFrame, Button, Box } from '@ceed/cds';
|
|
127
|
+
|
|
128
|
+
// Standalone usage requires explicit container dimensions
|
|
129
|
+
function EmbeddedDialog() {
|
|
130
|
+
return (
|
|
131
|
+
<Box sx={{ position: 'relative', width: 480, height: 300 }}>
|
|
132
|
+
<DialogFrame
|
|
133
|
+
title="Settings"
|
|
134
|
+
actions={
|
|
135
|
+
<>
|
|
136
|
+
<Button variant="plain" color="neutral">
|
|
137
|
+
Cancel
|
|
138
|
+
</Button>
|
|
139
|
+
<Button>Save</Button>
|
|
140
|
+
</>
|
|
141
|
+
}
|
|
142
|
+
>
|
|
143
|
+
This dialog is embedded directly in the page layout.
|
|
144
|
+
</DialogFrame>
|
|
145
|
+
</Box>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
97
150
|
## When to Use
|
|
98
151
|
|
|
99
152
|
### ✅ Good Use Cases
|
|
@@ -177,21 +230,11 @@ function QuickAddDialog({ open, onClose, onSubmit }) {
|
|
|
177
230
|
<Stack gap={2}>
|
|
178
231
|
<FormControl>
|
|
179
232
|
<FormLabel>Name</FormLabel>
|
|
180
|
-
<Input
|
|
181
|
-
value={name}
|
|
182
|
-
onChange={(e) => setName(e.target.value)}
|
|
183
|
-
placeholder="Enter name"
|
|
184
|
-
autoFocus
|
|
185
|
-
/>
|
|
233
|
+
<Input value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter name" autoFocus />
|
|
186
234
|
</FormControl>
|
|
187
235
|
<FormControl>
|
|
188
236
|
<FormLabel>Email</FormLabel>
|
|
189
|
-
<Input
|
|
190
|
-
type="email"
|
|
191
|
-
value={email}
|
|
192
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
193
|
-
placeholder="Enter email"
|
|
194
|
-
/>
|
|
237
|
+
<Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Enter email" />
|
|
195
238
|
</FormControl>
|
|
196
239
|
</Stack>
|
|
197
240
|
</DialogFrame>
|
|
@@ -216,15 +259,11 @@ function UnsavedChangesDialog({ open, onClose, onDiscard, onSave }) {
|
|
|
216
259
|
<Button variant="outlined" color="danger" onClick={onDiscard}>
|
|
217
260
|
Discard
|
|
218
261
|
</Button>
|
|
219
|
-
<Button onClick={onSave}>
|
|
220
|
-
Save Changes
|
|
221
|
-
</Button>
|
|
262
|
+
<Button onClick={onSave}>Save Changes</Button>
|
|
222
263
|
</>
|
|
223
264
|
}
|
|
224
265
|
>
|
|
225
|
-
<Typography>
|
|
226
|
-
You have unsaved changes. Would you like to save them before leaving?
|
|
227
|
-
</Typography>
|
|
266
|
+
<Typography>You have unsaved changes. Would you like to save them before leaving?</Typography>
|
|
228
267
|
</DialogFrame>
|
|
229
268
|
</Modal>
|
|
230
269
|
);
|
|
@@ -237,14 +276,7 @@ function UnsavedChangesDialog({ open, onClose, onDiscard, onSave }) {
|
|
|
237
276
|
function InfoDialog({ open, onClose, title, message }) {
|
|
238
277
|
return (
|
|
239
278
|
<Modal open={open} onClose={onClose}>
|
|
240
|
-
<DialogFrame
|
|
241
|
-
title={title}
|
|
242
|
-
actions={
|
|
243
|
-
<Button onClick={onClose}>
|
|
244
|
-
Got it
|
|
245
|
-
</Button>
|
|
246
|
-
}
|
|
247
|
-
>
|
|
279
|
+
<DialogFrame title={title} actions={<Button onClick={onClose}>Got it</Button>}>
|
|
248
280
|
<Typography>{message}</Typography>
|
|
249
281
|
</DialogFrame>
|
|
250
282
|
</Modal>
|
|
@@ -301,18 +333,8 @@ function ProcessingDialog({ open, status, onClose }) {
|
|
|
301
333
|
return (
|
|
302
334
|
<Modal open={open} onClose={isProcessing ? undefined : onClose}>
|
|
303
335
|
<DialogFrame
|
|
304
|
-
title={
|
|
305
|
-
|
|
306
|
-
isSuccess ? 'Success!' :
|
|
307
|
-
'Error'
|
|
308
|
-
}
|
|
309
|
-
actions={
|
|
310
|
-
!isProcessing && (
|
|
311
|
-
<Button onClick={onClose}>
|
|
312
|
-
{isSuccess ? 'Done' : 'Try Again'}
|
|
313
|
-
</Button>
|
|
314
|
-
)
|
|
315
|
-
}
|
|
336
|
+
title={isProcessing ? 'Processing...' : isSuccess ? 'Success!' : 'Error'}
|
|
337
|
+
actions={!isProcessing && <Button onClick={onClose}>{isSuccess ? 'Done' : 'Try Again'}</Button>}
|
|
316
338
|
>
|
|
317
339
|
<Box sx={{ textAlign: 'center', py: 2 }}>
|
|
318
340
|
{isProcessing && <CircularProgress />}
|
|
@@ -457,9 +479,7 @@ DialogFrame should be wrapped in Modal for proper behavior:
|
|
|
457
479
|
// Fullscreen for complex content or mobile
|
|
458
480
|
<Modal open={open} onClose={onClose}>
|
|
459
481
|
<DialogFrame fullscreen title="Edit Profile">
|
|
460
|
-
<Box sx={{ p: 2 }}>
|
|
461
|
-
{/* Large form or content */}
|
|
462
|
-
</Box>
|
|
482
|
+
<Box sx={{ p: 2 }}>{/* Large form or content */}</Box>
|
|
463
483
|
</DialogFrame>
|
|
464
484
|
</Modal>
|
|
465
485
|
```
|
|
@@ -500,9 +520,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
500
520
|
|
|
501
521
|
```tsx
|
|
502
522
|
// Title provides context
|
|
503
|
-
<DialogFrame title="Confirm Deletion">
|
|
504
|
-
{/* Content is read after title */}
|
|
505
|
-
</DialogFrame>
|
|
523
|
+
<DialogFrame title="Confirm Deletion">{/* Content is read after title */}</DialogFrame>
|
|
506
524
|
```
|
|
507
525
|
|
|
508
526
|
## Best Practices
|
|
@@ -530,9 +548,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
530
548
|
```tsx
|
|
531
549
|
// ✅ Good: Brief, scannable content
|
|
532
550
|
<DialogFrame title="Delete Project">
|
|
533
|
-
<Typography>
|
|
534
|
-
This will permanently delete the project and all its data.
|
|
535
|
-
</Typography>
|
|
551
|
+
<Typography>This will permanently delete the project and all its data.</Typography>
|
|
536
552
|
</DialogFrame>
|
|
537
553
|
```
|
|
538
554
|
|
|
@@ -560,7 +576,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
560
576
|
// ❌ Bad: Dialog for simple feedback
|
|
561
577
|
<DialogFrame title="Success">
|
|
562
578
|
<Typography>Item saved!</Typography>
|
|
563
|
-
</DialogFrame
|
|
579
|
+
</DialogFrame>;
|
|
564
580
|
|
|
565
581
|
// ✅ Good: Use Toast
|
|
566
582
|
showToast({ message: 'Item saved!' });
|
|
@@ -570,9 +586,7 @@ showToast({ message: 'Item saved!' });
|
|
|
570
586
|
|
|
571
587
|
```tsx
|
|
572
588
|
// ❌ Bad: Complex form in dialog
|
|
573
|
-
<DialogFrame title="Create Account">
|
|
574
|
-
{/* 20+ form fields */}
|
|
575
|
-
</DialogFrame>
|
|
589
|
+
<DialogFrame title="Create Account">{/* 20+ form fields */}</DialogFrame>
|
|
576
590
|
```
|
|
577
591
|
|
|
578
592
|
3. **Don't use vague button labels**: Be specific about actions
|
|
@@ -599,9 +613,7 @@ For dialogs with heavy content:
|
|
|
599
613
|
function HeavyDialog({ open, onClose }) {
|
|
600
614
|
return (
|
|
601
615
|
<Modal open={open} onClose={onClose}>
|
|
602
|
-
<DialogFrame title="Data Preview">
|
|
603
|
-
{open && <HeavyDataComponent />}
|
|
604
|
-
</DialogFrame>
|
|
616
|
+
<DialogFrame title="Data Preview">{open && <HeavyDataComponent />}</DialogFrame>
|
|
605
617
|
</Modal>
|
|
606
618
|
);
|
|
607
619
|
}
|
|
@@ -625,11 +637,13 @@ const handleCancel = useCallback(() => {
|
|
|
625
637
|
Unmount dialog completely when not needed:
|
|
626
638
|
|
|
627
639
|
```tsx
|
|
628
|
-
{
|
|
629
|
-
|
|
630
|
-
<
|
|
631
|
-
|
|
632
|
-
|
|
640
|
+
{
|
|
641
|
+
open && (
|
|
642
|
+
<Modal open={open} onClose={onClose}>
|
|
643
|
+
<DialogFrame>...</DialogFrame>
|
|
644
|
+
</Modal>
|
|
645
|
+
);
|
|
646
|
+
}
|
|
633
647
|
```
|
|
634
648
|
|
|
635
649
|
DialogFrame provides a consistent structure for dialog content. Combine it with Modal for proper overlay behavior, keep content concise and actionable, and always provide clear options for users to proceed or cancel.
|