@ceed/cds 1.21.0 → 1.22.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.
- package/dist/components/RadioTileGroup/RadioTileGroup.d.ts +56 -0
- package/dist/components/RadioTileGroup/index.d.ts +3 -0
- package/dist/components/data-display/Typography.md +63 -63
- package/dist/components/feedback/Dialog.md +72 -62
- package/dist/components/feedback/Modal.md +426 -138
- package/dist/components/index.d.ts +1 -0
- package/dist/components/inputs/RadioTileGroup.md +418 -0
- package/dist/components/inputs/llms.txt +1 -0
- package/dist/index.browser.js +5 -5
- package/dist/index.browser.js.map +4 -4
- package/dist/index.cjs +345 -181
- package/dist/index.d.ts +1 -1
- package/dist/index.js +212 -48
- package/dist/llms.txt +1 -0
- package/framer/index.js +39 -39
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import type { SxProps } from '@mui/joy/styles/types';
|
|
3
|
+
export interface RadioTileOption<T = string> {
|
|
4
|
+
value: T;
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
startDecorator?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface RadioTileGroupProps<T = string> {
|
|
10
|
+
/**
|
|
11
|
+
* @default 'sm'
|
|
12
|
+
*/
|
|
13
|
+
size?: 'sm' | 'md' | 'lg';
|
|
14
|
+
options: RadioTileOption<T>[];
|
|
15
|
+
value?: T;
|
|
16
|
+
defaultValue?: T;
|
|
17
|
+
name?: string;
|
|
18
|
+
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
19
|
+
sx?: SxProps;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
className?: string;
|
|
22
|
+
useIndicator?: boolean;
|
|
23
|
+
flex?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 지정하지 않으면 한 row에 모든 옵션이 렌더링된다.
|
|
26
|
+
* - 특정 rows 이내로 렌더링 하고 싶으면 `columns: Math.ceil(options.length / 원하는 rows)`로 설정할 수 있다.
|
|
27
|
+
* - 수직으로 렌더링 하고 싶으면 `columns: 1`로 설정할 수 있다.
|
|
28
|
+
* - `flex` 옵션과 함께 사용할수 있다.
|
|
29
|
+
*/
|
|
30
|
+
columns?: number;
|
|
31
|
+
/**
|
|
32
|
+
* @default 'center'
|
|
33
|
+
*/
|
|
34
|
+
textAlign?: 'start' | 'center';
|
|
35
|
+
/**
|
|
36
|
+
* Label for the RadioTileGroup
|
|
37
|
+
*/
|
|
38
|
+
label?: React.ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* Helper text for the RadioTileGroup
|
|
41
|
+
*/
|
|
42
|
+
helperText?: React.ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the RadioTileGroup has an error
|
|
45
|
+
*/
|
|
46
|
+
error?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the RadioTileGroup is required
|
|
49
|
+
*/
|
|
50
|
+
required?: boolean;
|
|
51
|
+
}
|
|
52
|
+
declare function RadioTileGroup<T extends string | number = string>(props: RadioTileGroupProps<T>): React.JSX.Element;
|
|
53
|
+
declare namespace RadioTileGroup {
|
|
54
|
+
var displayName: string;
|
|
55
|
+
}
|
|
56
|
+
export { RadioTileGroup };
|
|
@@ -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" />
|
|
@@ -16,15 +16,15 @@ Typography 컴포넌트는 텍스트를 표시하기 위한 핵심 컴포넌트
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
18
|
```tsx
|
|
19
|
-
import { Typography } from '@ceed/
|
|
19
|
+
import { Typography } from '@ceed/ads';
|
|
20
20
|
|
|
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,22 +74,22 @@ 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
|
-
|
|
85
|
+
The main content of the article goes here. This text uses a readable size and line spacing.
|
|
86
86
|
</Typography>
|
|
87
87
|
|
|
88
88
|
<Typography level="h2" sx={{ mt: 4, mb: 2 }}>
|
|
89
|
-
|
|
89
|
+
Section Title
|
|
90
90
|
</Typography>
|
|
91
91
|
|
|
92
|
-
<Typography level="body-md"
|
|
92
|
+
<Typography level="body-md">The section content continues here.</Typography>
|
|
93
93
|
</article>
|
|
94
94
|
);
|
|
95
95
|
}
|
|
@@ -101,15 +101,15 @@ function ArticlePage() {
|
|
|
101
101
|
<Card>
|
|
102
102
|
<CardContent>
|
|
103
103
|
<Typography level="title-md" sx={{ mb: 1 }}>
|
|
104
|
-
|
|
104
|
+
Product Name
|
|
105
105
|
</Typography>
|
|
106
106
|
|
|
107
107
|
<Typography level="body-sm" color="neutral" sx={{ mb: 2 }}>
|
|
108
|
-
|
|
108
|
+
Category: Electronics
|
|
109
109
|
</Typography>
|
|
110
110
|
|
|
111
111
|
<Typography level="body-md" sx={{ mb: 2 }}>
|
|
112
|
-
|
|
112
|
+
A detailed description of the product goes here.
|
|
113
113
|
</Typography>
|
|
114
114
|
|
|
115
115
|
<Typography level="title-lg" color="primary">
|
|
@@ -125,21 +125,21 @@ function ArticlePage() {
|
|
|
125
125
|
<Stack spacing={2}>
|
|
126
126
|
<FormControl>
|
|
127
127
|
<Typography level="title-sm" component="label">
|
|
128
|
-
|
|
128
|
+
Username
|
|
129
129
|
</Typography>
|
|
130
|
-
<Input placeholder="
|
|
130
|
+
<Input placeholder="Enter your name" />
|
|
131
131
|
<Typography level="body-xs" color="neutral">
|
|
132
|
-
|
|
132
|
+
Please enter your real name.
|
|
133
133
|
</Typography>
|
|
134
134
|
</FormControl>
|
|
135
135
|
|
|
136
136
|
<FormControl error>
|
|
137
137
|
<Typography level="title-sm" component="label">
|
|
138
|
-
|
|
138
|
+
Email Address
|
|
139
139
|
</Typography>
|
|
140
140
|
<Input placeholder="email@example.com" />
|
|
141
141
|
<Typography level="body-xs" color="danger">
|
|
142
|
-
|
|
142
|
+
The email format is invalid.
|
|
143
143
|
</Typography>
|
|
144
144
|
</FormControl>
|
|
145
145
|
</Stack>
|
|
@@ -150,16 +150,16 @@ function ArticlePage() {
|
|
|
150
150
|
```tsx
|
|
151
151
|
<Stack spacing={2}>
|
|
152
152
|
<Box>
|
|
153
|
-
<Typography level="body-md"
|
|
153
|
+
<Typography level="body-md">Server Status:</Typography>
|
|
154
154
|
<Typography level="body-md" color="success">
|
|
155
|
-
|
|
155
|
+
Operating Normally
|
|
156
156
|
</Typography>
|
|
157
157
|
</Box>
|
|
158
158
|
|
|
159
159
|
<Box>
|
|
160
|
-
<Typography level="body-md"
|
|
160
|
+
<Typography level="body-md">Last Updated:</Typography>
|
|
161
161
|
<Typography level="body-sm" color="neutral">
|
|
162
|
-
2
|
|
162
|
+
2 minutes ago
|
|
163
163
|
</Typography>
|
|
164
164
|
</Box>
|
|
165
165
|
</Stack>
|
|
@@ -169,7 +169,7 @@ function ArticlePage() {
|
|
|
169
169
|
|
|
170
170
|
```tsx
|
|
171
171
|
<Stack spacing={1}>
|
|
172
|
-
<Typography level="title-md"
|
|
172
|
+
<Typography level="title-md">Todo List</Typography>
|
|
173
173
|
|
|
174
174
|
{todoItems.map((item) => (
|
|
175
175
|
<Box key={item.id} sx={{ pl: 2 }}>
|
|
@@ -192,39 +192,39 @@ function ArticlePage() {
|
|
|
192
192
|
|
|
193
193
|
## Colors
|
|
194
194
|
|
|
195
|
-
Typography
|
|
195
|
+
Typography supports various colors:
|
|
196
196
|
|
|
197
197
|
```tsx
|
|
198
198
|
<Stack spacing={1}>
|
|
199
|
-
<Typography color="primary">Primary
|
|
200
|
-
<Typography color="neutral">Neutral
|
|
201
|
-
<Typography color="danger">Danger
|
|
202
|
-
<Typography color="success">Success
|
|
203
|
-
<Typography color="warning">Warning
|
|
199
|
+
<Typography color="primary">Primary color</Typography>
|
|
200
|
+
<Typography color="neutral">Neutral color</Typography>
|
|
201
|
+
<Typography color="danger">Danger color</Typography>
|
|
202
|
+
<Typography color="success">Success color</Typography>
|
|
203
|
+
<Typography color="warning">Warning color</Typography>
|
|
204
204
|
</Stack>
|
|
205
205
|
```
|
|
206
206
|
|
|
207
207
|
## Component Prop
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
You can render it as a different HTML element or React component:
|
|
210
210
|
|
|
211
211
|
```tsx
|
|
212
212
|
<Typography level="h1" component="h2">
|
|
213
|
-
|
|
213
|
+
h1 style rendered as an h2 tag
|
|
214
214
|
</Typography>
|
|
215
215
|
|
|
216
216
|
<Typography level="body-md" component="span">
|
|
217
|
-
|
|
217
|
+
Inline text
|
|
218
218
|
</Typography>
|
|
219
219
|
|
|
220
220
|
<Typography level="title-md" component={Link} href="/page">
|
|
221
|
-
|
|
221
|
+
Rendered as a Link component
|
|
222
222
|
</Typography>
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
## Responsive Typography
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
You can use responsive levels:
|
|
228
228
|
|
|
229
229
|
```tsx
|
|
230
230
|
<Typography
|
|
@@ -233,36 +233,36 @@ Typography는 다양한 색상을 지원합니다:
|
|
|
233
233
|
fontSize: { xs: '1.5rem', sm: '2rem', md: '2.5rem' },
|
|
234
234
|
}}
|
|
235
235
|
>
|
|
236
|
-
|
|
236
|
+
Responsive Heading
|
|
237
237
|
</Typography>
|
|
238
238
|
```
|
|
239
239
|
|
|
240
240
|
## Best Practices
|
|
241
241
|
|
|
242
|
-
1.
|
|
242
|
+
1. **Semantic Structure**: Use heading levels in order to create a clear document structure.
|
|
243
243
|
|
|
244
244
|
```tsx
|
|
245
|
-
// ✅
|
|
246
|
-
<Typography level="h1"
|
|
247
|
-
<Typography level="h2"
|
|
248
|
-
<Typography level="h3"
|
|
249
|
-
|
|
250
|
-
// ❌
|
|
251
|
-
<Typography level="h1"
|
|
252
|
-
<Typography level="h3"
|
|
245
|
+
// ✅ Correct order
|
|
246
|
+
<Typography level="h1">Main heading</Typography>
|
|
247
|
+
<Typography level="h2">Section heading</Typography>
|
|
248
|
+
<Typography level="h3">Subsection</Typography>
|
|
249
|
+
|
|
250
|
+
// ❌ Incorrect order
|
|
251
|
+
<Typography level="h1">Main heading</Typography>
|
|
252
|
+
<Typography level="h3">Section heading</Typography>
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
-
2.
|
|
255
|
+
2. **Consistency**: Use the same level for text serving the same purpose.
|
|
256
256
|
|
|
257
|
-
3.
|
|
257
|
+
3. **Readability**: Provide proper line spacing and paragraph separation for body text.
|
|
258
258
|
|
|
259
|
-
4.
|
|
259
|
+
4. **Color Contrast**: Maintain sufficient color contrast to ensure accessibility.
|
|
260
260
|
|
|
261
261
|
## Accessibility
|
|
262
262
|
|
|
263
|
-
-
|
|
264
|
-
-
|
|
265
|
-
-
|
|
266
|
-
-
|
|
263
|
+
- Use appropriate semantic HTML tags
|
|
264
|
+
- Support screen readers
|
|
265
|
+
- Ensure keyboard navigation (when used as a link or button)
|
|
266
|
+
- Maintain sufficient color contrast
|
|
267
267
|
|
|
268
|
-
Typography
|
|
268
|
+
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.
|
|
@@ -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,57 @@ 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** provide explicit `width` and `height` values.
|
|
102
|
+
> DialogFrame inherits its dimensions from `ModalDialog`, which normally receives sizing from the Modal overlay.
|
|
103
|
+
> Without these constraints, the component will not render with correct dimensions.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
<Box sx={{
|
|
107
|
+
width: 480,
|
|
108
|
+
height: 300
|
|
109
|
+
}}>
|
|
110
|
+
<DialogFrame {...args} title="Standalone Dialog" actions={<>
|
|
111
|
+
<Button variant="plain" color="neutral">
|
|
112
|
+
Cancel
|
|
113
|
+
</Button>
|
|
114
|
+
<Button variant="plain">Confirm</Button>
|
|
115
|
+
</>}>
|
|
116
|
+
DialogFrame used without Modal. The parent container must provide explicit width and height.
|
|
117
|
+
</DialogFrame>
|
|
118
|
+
</Box>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { DialogFrame, Button, Box } from '@ceed/cds';
|
|
123
|
+
|
|
124
|
+
// Standalone usage requires explicit container dimensions
|
|
125
|
+
function EmbeddedDialog() {
|
|
126
|
+
return (
|
|
127
|
+
<Box sx={{ width: 480, height: 300 }}>
|
|
128
|
+
<DialogFrame
|
|
129
|
+
title="Settings"
|
|
130
|
+
actions={
|
|
131
|
+
<>
|
|
132
|
+
<Button variant="plain" color="neutral">
|
|
133
|
+
Cancel
|
|
134
|
+
</Button>
|
|
135
|
+
<Button>Save</Button>
|
|
136
|
+
</>
|
|
137
|
+
}
|
|
138
|
+
>
|
|
139
|
+
This dialog is embedded directly in the page layout.
|
|
140
|
+
</DialogFrame>
|
|
141
|
+
</Box>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
97
146
|
## When to Use
|
|
98
147
|
|
|
99
148
|
### ✅ Good Use Cases
|
|
@@ -177,21 +226,11 @@ function QuickAddDialog({ open, onClose, onSubmit }) {
|
|
|
177
226
|
<Stack gap={2}>
|
|
178
227
|
<FormControl>
|
|
179
228
|
<FormLabel>Name</FormLabel>
|
|
180
|
-
<Input
|
|
181
|
-
value={name}
|
|
182
|
-
onChange={(e) => setName(e.target.value)}
|
|
183
|
-
placeholder="Enter name"
|
|
184
|
-
autoFocus
|
|
185
|
-
/>
|
|
229
|
+
<Input value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter name" autoFocus />
|
|
186
230
|
</FormControl>
|
|
187
231
|
<FormControl>
|
|
188
232
|
<FormLabel>Email</FormLabel>
|
|
189
|
-
<Input
|
|
190
|
-
type="email"
|
|
191
|
-
value={email}
|
|
192
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
193
|
-
placeholder="Enter email"
|
|
194
|
-
/>
|
|
233
|
+
<Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Enter email" />
|
|
195
234
|
</FormControl>
|
|
196
235
|
</Stack>
|
|
197
236
|
</DialogFrame>
|
|
@@ -216,15 +255,11 @@ function UnsavedChangesDialog({ open, onClose, onDiscard, onSave }) {
|
|
|
216
255
|
<Button variant="outlined" color="danger" onClick={onDiscard}>
|
|
217
256
|
Discard
|
|
218
257
|
</Button>
|
|
219
|
-
<Button onClick={onSave}>
|
|
220
|
-
Save Changes
|
|
221
|
-
</Button>
|
|
258
|
+
<Button onClick={onSave}>Save Changes</Button>
|
|
222
259
|
</>
|
|
223
260
|
}
|
|
224
261
|
>
|
|
225
|
-
<Typography>
|
|
226
|
-
You have unsaved changes. Would you like to save them before leaving?
|
|
227
|
-
</Typography>
|
|
262
|
+
<Typography>You have unsaved changes. Would you like to save them before leaving?</Typography>
|
|
228
263
|
</DialogFrame>
|
|
229
264
|
</Modal>
|
|
230
265
|
);
|
|
@@ -237,14 +272,7 @@ function UnsavedChangesDialog({ open, onClose, onDiscard, onSave }) {
|
|
|
237
272
|
function InfoDialog({ open, onClose, title, message }) {
|
|
238
273
|
return (
|
|
239
274
|
<Modal open={open} onClose={onClose}>
|
|
240
|
-
<DialogFrame
|
|
241
|
-
title={title}
|
|
242
|
-
actions={
|
|
243
|
-
<Button onClick={onClose}>
|
|
244
|
-
Got it
|
|
245
|
-
</Button>
|
|
246
|
-
}
|
|
247
|
-
>
|
|
275
|
+
<DialogFrame title={title} actions={<Button onClick={onClose}>Got it</Button>}>
|
|
248
276
|
<Typography>{message}</Typography>
|
|
249
277
|
</DialogFrame>
|
|
250
278
|
</Modal>
|
|
@@ -301,18 +329,8 @@ function ProcessingDialog({ open, status, onClose }) {
|
|
|
301
329
|
return (
|
|
302
330
|
<Modal open={open} onClose={isProcessing ? undefined : onClose}>
|
|
303
331
|
<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
|
-
}
|
|
332
|
+
title={isProcessing ? 'Processing...' : isSuccess ? 'Success!' : 'Error'}
|
|
333
|
+
actions={!isProcessing && <Button onClick={onClose}>{isSuccess ? 'Done' : 'Try Again'}</Button>}
|
|
316
334
|
>
|
|
317
335
|
<Box sx={{ textAlign: 'center', py: 2 }}>
|
|
318
336
|
{isProcessing && <CircularProgress />}
|
|
@@ -457,9 +475,7 @@ DialogFrame should be wrapped in Modal for proper behavior:
|
|
|
457
475
|
// Fullscreen for complex content or mobile
|
|
458
476
|
<Modal open={open} onClose={onClose}>
|
|
459
477
|
<DialogFrame fullscreen title="Edit Profile">
|
|
460
|
-
<Box sx={{ p: 2 }}>
|
|
461
|
-
{/* Large form or content */}
|
|
462
|
-
</Box>
|
|
478
|
+
<Box sx={{ p: 2 }}>{/* Large form or content */}</Box>
|
|
463
479
|
</DialogFrame>
|
|
464
480
|
</Modal>
|
|
465
481
|
```
|
|
@@ -500,9 +516,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
500
516
|
|
|
501
517
|
```tsx
|
|
502
518
|
// Title provides context
|
|
503
|
-
<DialogFrame title="Confirm Deletion">
|
|
504
|
-
{/* Content is read after title */}
|
|
505
|
-
</DialogFrame>
|
|
519
|
+
<DialogFrame title="Confirm Deletion">{/* Content is read after title */}</DialogFrame>
|
|
506
520
|
```
|
|
507
521
|
|
|
508
522
|
## Best Practices
|
|
@@ -530,9 +544,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
530
544
|
```tsx
|
|
531
545
|
// ✅ Good: Brief, scannable content
|
|
532
546
|
<DialogFrame title="Delete Project">
|
|
533
|
-
<Typography>
|
|
534
|
-
This will permanently delete the project and all its data.
|
|
535
|
-
</Typography>
|
|
547
|
+
<Typography>This will permanently delete the project and all its data.</Typography>
|
|
536
548
|
</DialogFrame>
|
|
537
549
|
```
|
|
538
550
|
|
|
@@ -560,7 +572,7 @@ DialogFrame inherits accessibility features from Modal:
|
|
|
560
572
|
// ❌ Bad: Dialog for simple feedback
|
|
561
573
|
<DialogFrame title="Success">
|
|
562
574
|
<Typography>Item saved!</Typography>
|
|
563
|
-
</DialogFrame
|
|
575
|
+
</DialogFrame>;
|
|
564
576
|
|
|
565
577
|
// ✅ Good: Use Toast
|
|
566
578
|
showToast({ message: 'Item saved!' });
|
|
@@ -570,9 +582,7 @@ showToast({ message: 'Item saved!' });
|
|
|
570
582
|
|
|
571
583
|
```tsx
|
|
572
584
|
// ❌ Bad: Complex form in dialog
|
|
573
|
-
<DialogFrame title="Create Account">
|
|
574
|
-
{/* 20+ form fields */}
|
|
575
|
-
</DialogFrame>
|
|
585
|
+
<DialogFrame title="Create Account">{/* 20+ form fields */}</DialogFrame>
|
|
576
586
|
```
|
|
577
587
|
|
|
578
588
|
3. **Don't use vague button labels**: Be specific about actions
|
|
@@ -599,9 +609,7 @@ For dialogs with heavy content:
|
|
|
599
609
|
function HeavyDialog({ open, onClose }) {
|
|
600
610
|
return (
|
|
601
611
|
<Modal open={open} onClose={onClose}>
|
|
602
|
-
<DialogFrame title="Data Preview">
|
|
603
|
-
{open && <HeavyDataComponent />}
|
|
604
|
-
</DialogFrame>
|
|
612
|
+
<DialogFrame title="Data Preview">{open && <HeavyDataComponent />}</DialogFrame>
|
|
605
613
|
</Modal>
|
|
606
614
|
);
|
|
607
615
|
}
|
|
@@ -625,11 +633,13 @@ const handleCancel = useCallback(() => {
|
|
|
625
633
|
Unmount dialog completely when not needed:
|
|
626
634
|
|
|
627
635
|
```tsx
|
|
628
|
-
{
|
|
629
|
-
|
|
630
|
-
<
|
|
631
|
-
|
|
632
|
-
|
|
636
|
+
{
|
|
637
|
+
open && (
|
|
638
|
+
<Modal open={open} onClose={onClose}>
|
|
639
|
+
<DialogFrame>...</DialogFrame>
|
|
640
|
+
</Modal>
|
|
641
|
+
);
|
|
642
|
+
}
|
|
633
643
|
```
|
|
634
644
|
|
|
635
645
|
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.
|