@ceed/ads 1.13.4 → 1.15.0-next.2
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/Overview.md +11 -0
- package/dist/components/Menu/Menu.d.ts +2 -5
- package/dist/components/Stepper/Stepper.d.ts +6 -0
- package/dist/components/data-display/Avatar.md +428 -0
- package/dist/components/data-display/Badge.md +315 -0
- package/dist/components/data-display/Chip.md +301 -0
- package/dist/components/data-display/DataTable.md +452 -0
- package/dist/components/data-display/InfoSign.md +160 -0
- package/dist/components/data-display/Markdown.md +17 -0
- package/dist/components/data-display/Table.md +1330 -0
- package/dist/components/data-display/Tooltip.md +444 -0
- package/dist/components/data-display/Typography.md +271 -0
- package/dist/components/data-display/llms.txt +17 -0
- package/dist/components/feedback/Alert.md +663 -0
- package/dist/components/feedback/Dialog.md +33 -0
- package/dist/components/feedback/Modal.md +39 -0
- package/dist/components/feedback/llms.txt +11 -0
- package/dist/components/inputs/Autocomplete.md +103 -0
- package/dist/components/inputs/Button.md +334 -0
- package/dist/components/inputs/ButtonGroup.md +382 -0
- package/dist/components/inputs/Calendar.md +19 -0
- package/dist/components/inputs/Checkbox.md +649 -0
- package/dist/components/inputs/CurrencyInput.md +91 -0
- package/dist/components/inputs/DatePicker.md +67 -0
- package/dist/components/inputs/DateRangePicker.md +55 -0
- package/dist/components/inputs/FilterMenu.md +210 -0
- package/dist/components/inputs/IconButton.md +361 -0
- package/dist/components/inputs/Input.md +283 -0
- package/dist/components/inputs/MonthPicker.md +72 -0
- package/dist/components/inputs/MonthRangePicker.md +70 -0
- package/dist/components/inputs/PercentageInput.md +116 -0
- package/dist/components/inputs/RadioButton.md +350 -0
- package/dist/components/inputs/RadioTileGroup.md +418 -0
- package/dist/components/inputs/Select.md +56 -0
- package/dist/components/inputs/Switch.md +577 -0
- package/dist/components/inputs/Textarea.md +64 -0
- package/dist/components/inputs/Uploader/Uploader.md +238 -0
- package/dist/components/inputs/Uploader/llms.txt +9 -0
- package/dist/components/inputs/llms.txt +31 -0
- package/dist/components/layout/Box.md +997 -0
- package/dist/components/layout/Container.md +23 -0
- package/dist/components/layout/Grid.md +728 -0
- package/dist/components/layout/Stack.md +937 -0
- package/dist/components/layout/llms.txt +12 -0
- package/dist/components/llms.txt +14 -0
- package/dist/components/navigation/Breadcrumbs.md +51 -0
- package/dist/components/navigation/Dropdown.md +768 -0
- package/dist/components/navigation/IconMenuButton.md +35 -0
- package/dist/components/navigation/InsetDrawer.md +133 -0
- package/dist/components/navigation/Link.md +24 -0
- package/dist/components/navigation/Menu.md +957 -0
- package/dist/components/navigation/MenuButton.md +39 -0
- package/dist/components/navigation/NavigationGroup.md +17 -0
- package/dist/components/navigation/NavigationItem.md +17 -0
- package/dist/components/navigation/Navigator.md +17 -0
- package/dist/components/navigation/Pagination.md +17 -0
- package/dist/components/navigation/ProfileMenu.md +34 -0
- package/dist/components/navigation/Stepper.md +108 -0
- package/dist/components/navigation/Tabs.md +34 -0
- package/dist/components/navigation/llms.txt +22 -0
- package/dist/components/surfaces/Accordions.md +96 -0
- package/dist/components/surfaces/Card.md +786 -0
- package/dist/components/surfaces/Divider.md +762 -0
- package/dist/components/surfaces/Sheet.md +900 -0
- package/dist/components/surfaces/llms.txt +12 -0
- package/dist/index.cjs +22 -10
- package/dist/index.js +22 -10
- package/dist/llms.txt +75 -0
- package/framer/index.js +36 -36
- package/package.json +8 -4
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Switch 컴포넌트는 사용자가 옵션을 켜고 끌 수 있는 토글 형태의 입력 요소입니다. Joy UI의 Switch를 기반으로 하며, 다양한 크기, 색상, 장식 요소를 지원합니다. 설정 화면, 기능 활성화/비활성화, 모드 전환 등에 주로 사용됩니다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Switch />
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Field | Description | Default |
|
|
12
|
+
| -------------- | ----------- | ------- |
|
|
13
|
+
| variant | — | — |
|
|
14
|
+
| color | — | — |
|
|
15
|
+
| size | — | — |
|
|
16
|
+
| startDecorator | — | — |
|
|
17
|
+
| endDecorator | — | — |
|
|
18
|
+
| checked | — | — |
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { Switch } from '@ceed/ads';
|
|
24
|
+
|
|
25
|
+
function MyComponent() {
|
|
26
|
+
const [enabled, setEnabled] = useState(false);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Switch
|
|
30
|
+
checked={enabled}
|
|
31
|
+
onChange={(e) => setEnabled(e.target.checked)}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
가장 기본적인 Switch 사용법입니다.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<Switch />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With Labels
|
|
48
|
+
|
|
49
|
+
라벨과 함께 사용하는 Switch입니다. 폼 컨트롤 내에서 설명과 함께 사용할 수 있습니다.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<FormControl orientation="horizontal" sx={{
|
|
53
|
+
width: 300,
|
|
54
|
+
justifyContent: 'space-between'
|
|
55
|
+
}}>
|
|
56
|
+
<div>
|
|
57
|
+
<FormLabel>Show captions</FormLabel>
|
|
58
|
+
<FormHelperText sx={{
|
|
59
|
+
mt: 0
|
|
60
|
+
}}>All languages available.</FormHelperText>
|
|
61
|
+
</div>
|
|
62
|
+
<Switch checked={checked} onChange={e => setChecked(e.target.checked)} color={checked ? 'success' : 'neutral'} variant={checked ? 'solid' : 'outlined'} endDecorator={checked ? 'On' : 'Off'} slotProps={{
|
|
63
|
+
endDecorator: {
|
|
64
|
+
sx: {
|
|
65
|
+
minWidth: 24
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}} />
|
|
69
|
+
</FormControl>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Inline Labels
|
|
73
|
+
|
|
74
|
+
인라인 형태로 텍스트와 함께 사용할 수 있습니다.
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<Typography component="label" endDecorator={<Switch sx={{
|
|
78
|
+
ml: 1
|
|
79
|
+
}} />}>
|
|
80
|
+
Turn alarm on
|
|
81
|
+
</Typography>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### With Decorators
|
|
85
|
+
|
|
86
|
+
아이콘이나 다른 요소를 장식으로 추가할 수 있습니다.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<Switch color={dark ? 'primary' : 'danger'} slotProps={{
|
|
90
|
+
input: {
|
|
91
|
+
'aria-label': 'dark mode'
|
|
92
|
+
}
|
|
93
|
+
}} startDecorator={<LightModeIcon sx={theme => ({
|
|
94
|
+
color: dark ? 'currentColor' : 'var(--ceed-palette-danger-solidBg)'
|
|
95
|
+
})} />} endDecorator={<DarkModeIcon sx={theme => ({
|
|
96
|
+
color: dark ? 'var(--ceed-palette-primary-solidBg)' : 'currentColor'
|
|
97
|
+
})} />} checked={dark} onChange={event => setDark(event.target.checked)} />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Track Children
|
|
101
|
+
|
|
102
|
+
트랙 내부에 텍스트나 다른 요소를 표시할 수 있습니다.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<Stack direction="row" spacing={4}>
|
|
106
|
+
<Switch {...args} slotProps={{
|
|
107
|
+
track: {
|
|
108
|
+
children: <React.Fragment>
|
|
109
|
+
<Typography component="span" level="inherit" sx={{
|
|
110
|
+
ml: '10px'
|
|
111
|
+
}}>
|
|
112
|
+
On
|
|
113
|
+
</Typography>
|
|
114
|
+
<Typography component="span" level="inherit" sx={{
|
|
115
|
+
mr: '8px'
|
|
116
|
+
}}>
|
|
117
|
+
Off
|
|
118
|
+
</Typography>
|
|
119
|
+
</React.Fragment>
|
|
120
|
+
}
|
|
121
|
+
}} sx={{
|
|
122
|
+
'--Switch-thumbSize': '27px',
|
|
123
|
+
'--Switch-trackWidth': '64px',
|
|
124
|
+
'--Switch-trackHeight': '31px'
|
|
125
|
+
}} />
|
|
126
|
+
<Switch color="success" slotProps={{
|
|
127
|
+
track: {
|
|
128
|
+
children: <React.Fragment>
|
|
129
|
+
<span>I</span>
|
|
130
|
+
<span>0</span>
|
|
131
|
+
</React.Fragment>,
|
|
132
|
+
sx: {
|
|
133
|
+
justifyContent: 'space-around'
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}} sx={{
|
|
137
|
+
'--Switch-thumbSize': '27px',
|
|
138
|
+
'--Switch-trackWidth': '52px',
|
|
139
|
+
'--Switch-trackHeight': '31px'
|
|
140
|
+
}} />
|
|
141
|
+
</Stack>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Thumb Children
|
|
145
|
+
|
|
146
|
+
썸(토글 버튼) 내부에 아이콘을 표시할 수 있습니다.
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Switch size="lg" slotProps={{
|
|
150
|
+
input: {
|
|
151
|
+
'aria-label': 'Dark mode'
|
|
152
|
+
},
|
|
153
|
+
thumb: {
|
|
154
|
+
children: <DarkModeIcon fontSize="inherit" />
|
|
155
|
+
}
|
|
156
|
+
}} sx={{
|
|
157
|
+
'--Switch-thumbSize': '16px'
|
|
158
|
+
}} />
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Common Use Cases
|
|
162
|
+
|
|
163
|
+
### Settings Panel
|
|
164
|
+
|
|
165
|
+
설정 패널에서 기능을 활성화/비활성화할 때 사용합니다.
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
<Stack spacing={3}>
|
|
169
|
+
<FormControl orientation="horizontal" sx={{ width: 400, justifyContent: 'space-between' }}>
|
|
170
|
+
<div>
|
|
171
|
+
<FormLabel>알림 받기</FormLabel>
|
|
172
|
+
<FormHelperText sx={{ mt: 0 }}>
|
|
173
|
+
새로운 메시지가 도착했을 때 알림을 받습니다.
|
|
174
|
+
</FormHelperText>
|
|
175
|
+
</div>
|
|
176
|
+
<Switch
|
|
177
|
+
checked={notifications}
|
|
178
|
+
onChange={(e) => setNotifications(e.target.checked)}
|
|
179
|
+
color="success"
|
|
180
|
+
/>
|
|
181
|
+
</FormControl>
|
|
182
|
+
|
|
183
|
+
<FormControl orientation="horizontal" sx={{ width: 400, justifyContent: 'space-between' }}>
|
|
184
|
+
<div>
|
|
185
|
+
<FormLabel>자동 저장</FormLabel>
|
|
186
|
+
<FormHelperText sx={{ mt: 0 }}>
|
|
187
|
+
작업 내용을 자동으로 저장합니다.
|
|
188
|
+
</FormHelperText>
|
|
189
|
+
</div>
|
|
190
|
+
<Switch
|
|
191
|
+
checked={autoSave}
|
|
192
|
+
onChange={(e) => setAutoSave(e.target.checked)}
|
|
193
|
+
/>
|
|
194
|
+
</FormControl>
|
|
195
|
+
</Stack>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Theme Toggle
|
|
199
|
+
|
|
200
|
+
다크 모드/라이트 모드 전환에 자주 사용됩니다.
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
function ThemeToggle() {
|
|
204
|
+
const [darkMode, setDarkMode] = useState(false);
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<Switch
|
|
208
|
+
checked={darkMode}
|
|
209
|
+
onChange={(e) => setDarkMode(e.target.checked)}
|
|
210
|
+
color={darkMode ? 'primary' : 'danger'}
|
|
211
|
+
startDecorator={<LightModeIcon />}
|
|
212
|
+
endDecorator={<DarkModeIcon />}
|
|
213
|
+
slotProps={{
|
|
214
|
+
input: { 'aria-label': '다크 모드 토글' },
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Feature Flags
|
|
222
|
+
|
|
223
|
+
기능의 활성화/비활성화를 제어할 때 사용합니다.
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
<Card>
|
|
227
|
+
<CardContent>
|
|
228
|
+
<Typography level="title-md" sx={{ mb: 2 }}>
|
|
229
|
+
실험적 기능
|
|
230
|
+
</Typography>
|
|
231
|
+
|
|
232
|
+
<Stack spacing={2}>
|
|
233
|
+
<FormControl orientation="horizontal" sx={{ justifyContent: 'space-between' }}>
|
|
234
|
+
<FormLabel>베타 기능 활성화</FormLabel>
|
|
235
|
+
<Switch
|
|
236
|
+
checked={betaFeatures}
|
|
237
|
+
onChange={(e) => setBetaFeatures(e.target.checked)}
|
|
238
|
+
color="warning"
|
|
239
|
+
endDecorator={betaFeatures ? 'On' : 'Off'}
|
|
240
|
+
/>
|
|
241
|
+
</FormControl>
|
|
242
|
+
|
|
243
|
+
<FormControl orientation="horizontal" sx={{ justifyContent: 'space-between' }}>
|
|
244
|
+
<FormLabel>고급 모드</FormLabel>
|
|
245
|
+
<Switch
|
|
246
|
+
checked={advancedMode}
|
|
247
|
+
onChange={(e) => setAdvancedMode(e.target.checked)}
|
|
248
|
+
disabled={!betaFeatures}
|
|
249
|
+
/>
|
|
250
|
+
</FormControl>
|
|
251
|
+
</Stack>
|
|
252
|
+
</CardContent>
|
|
253
|
+
</Card>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### List Items with Switches
|
|
257
|
+
|
|
258
|
+
목록 아이템에서 각 항목을 개별적으로 제어할 때 사용합니다.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
<List>
|
|
262
|
+
{permissions.map((permission) => (
|
|
263
|
+
<ListItem key={permission.id} endAction={
|
|
264
|
+
<Switch
|
|
265
|
+
checked={permission.enabled}
|
|
266
|
+
onChange={(e) => handlePermissionToggle(permission.id, e.target.checked)}
|
|
267
|
+
size="sm"
|
|
268
|
+
color={permission.enabled ? 'success' : 'neutral'}
|
|
269
|
+
/>
|
|
270
|
+
}>
|
|
271
|
+
<ListItemContent>
|
|
272
|
+
<Typography level="title-sm">{permission.name}</Typography>
|
|
273
|
+
<Typography level="body-sm" color="neutral">
|
|
274
|
+
{permission.description}
|
|
275
|
+
</Typography>
|
|
276
|
+
</ListItemContent>
|
|
277
|
+
</ListItem>
|
|
278
|
+
))}
|
|
279
|
+
</List>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Controlled Form
|
|
283
|
+
|
|
284
|
+
폼 상태 관리와 함께 사용하는 예제입니다.
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
function UserPreferences() {
|
|
288
|
+
const [preferences, setPreferences] = useState({
|
|
289
|
+
emailNotifications: true,
|
|
290
|
+
smsNotifications: false,
|
|
291
|
+
pushNotifications: true,
|
|
292
|
+
darkMode: false,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const handleToggle = (key: keyof typeof preferences) => (
|
|
296
|
+
event: React.ChangeEvent<HTMLInputElement>
|
|
297
|
+
) => {
|
|
298
|
+
setPreferences(prev => ({
|
|
299
|
+
...prev,
|
|
300
|
+
[key]: event.target.checked
|
|
301
|
+
}));
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<form onSubmit={handleSubmit}>
|
|
306
|
+
<Stack spacing={3}>
|
|
307
|
+
<Typography level="h4">알림 설정</Typography>
|
|
308
|
+
|
|
309
|
+
<Stack spacing={2}>
|
|
310
|
+
<Typography component="label" endDecorator={
|
|
311
|
+
<Switch
|
|
312
|
+
checked={preferences.emailNotifications}
|
|
313
|
+
onChange={handleToggle('emailNotifications')}
|
|
314
|
+
sx={{ ml: 1 }}
|
|
315
|
+
/>
|
|
316
|
+
}>
|
|
317
|
+
이메일 알림
|
|
318
|
+
</Typography>
|
|
319
|
+
|
|
320
|
+
<Typography component="label" endDecorator={
|
|
321
|
+
<Switch
|
|
322
|
+
checked={preferences.smsNotifications}
|
|
323
|
+
onChange={handleToggle('smsNotifications')}
|
|
324
|
+
sx={{ ml: 1 }}
|
|
325
|
+
/>
|
|
326
|
+
}>
|
|
327
|
+
SMS 알림
|
|
328
|
+
</Typography>
|
|
329
|
+
|
|
330
|
+
<Typography component="label" endDecorator={
|
|
331
|
+
<Switch
|
|
332
|
+
checked={preferences.pushNotifications}
|
|
333
|
+
onChange={handleToggle('pushNotifications')}
|
|
334
|
+
sx={{ ml: 1 }}
|
|
335
|
+
/>
|
|
336
|
+
}>
|
|
337
|
+
푸시 알림
|
|
338
|
+
</Typography>
|
|
339
|
+
</Stack>
|
|
340
|
+
|
|
341
|
+
<Divider />
|
|
342
|
+
|
|
343
|
+
<Typography component="label" endDecorator={
|
|
344
|
+
<Switch
|
|
345
|
+
checked={preferences.darkMode}
|
|
346
|
+
onChange={handleToggle('darkMode')}
|
|
347
|
+
startDecorator={<LightModeIcon />}
|
|
348
|
+
endDecorator={<DarkModeIcon />}
|
|
349
|
+
sx={{ ml: 1 }}
|
|
350
|
+
/>
|
|
351
|
+
}>
|
|
352
|
+
다크 모드
|
|
353
|
+
</Typography>
|
|
354
|
+
|
|
355
|
+
<Button type="submit">설정 저장</Button>
|
|
356
|
+
</Stack>
|
|
357
|
+
</form>
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Props and Customization
|
|
363
|
+
|
|
364
|
+
### Colors
|
|
365
|
+
|
|
366
|
+
다양한 색상을 적용할 수 있습니다.
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
<Stack direction="row" spacing={2}>
|
|
370
|
+
<Switch color="primary" checked />
|
|
371
|
+
<Switch color="success" checked />
|
|
372
|
+
<Switch color="warning" checked />
|
|
373
|
+
<Switch color="danger" checked />
|
|
374
|
+
<Switch color="neutral" checked />
|
|
375
|
+
</Stack>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Sizes
|
|
379
|
+
|
|
380
|
+
스위치의 크기를 조절할 수 있습니다.
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
384
|
+
<Switch size="sm" checked />
|
|
385
|
+
<Switch size="md" checked />
|
|
386
|
+
<Switch size="lg" checked />
|
|
387
|
+
</Stack>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Variants
|
|
391
|
+
|
|
392
|
+
다양한 시각적 스타일을 적용할 수 있습니다.
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
<Stack direction="row" spacing={2}>
|
|
396
|
+
<Switch variant="solid" checked />
|
|
397
|
+
<Switch variant="soft" checked />
|
|
398
|
+
<Switch variant="outlined" checked />
|
|
399
|
+
<Switch variant="plain" checked />
|
|
400
|
+
</Stack>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Custom Styling
|
|
404
|
+
|
|
405
|
+
CSS 변수를 통해 세밀한 커스터마이징이 가능합니다.
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
<Switch
|
|
409
|
+
checked={customSwitch}
|
|
410
|
+
onChange={(e) => setCustomSwitch(e.target.checked)}
|
|
411
|
+
sx={{
|
|
412
|
+
'--Switch-thumbSize': '24px',
|
|
413
|
+
'--Switch-trackWidth': '60px',
|
|
414
|
+
'--Switch-trackHeight': '32px',
|
|
415
|
+
'--Switch-trackRadius': '16px',
|
|
416
|
+
'--Switch-thumbRadius': '12px',
|
|
417
|
+
}}
|
|
418
|
+
/>
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## States
|
|
422
|
+
|
|
423
|
+
### Disabled State
|
|
424
|
+
|
|
425
|
+
비활성 상태의 스위치입니다.
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
<Stack direction="row" spacing={2}>
|
|
429
|
+
<Switch disabled />
|
|
430
|
+
<Switch disabled checked />
|
|
431
|
+
</Stack>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Loading/Processing State
|
|
435
|
+
|
|
436
|
+
처리 중일 때의 시각적 피드백을 제공할 수 있습니다.
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
function ProcessingSwitch() {
|
|
440
|
+
const [processing, setProcessing] = useState(false);
|
|
441
|
+
const [enabled, setEnabled] = useState(false);
|
|
442
|
+
|
|
443
|
+
const handleToggle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
444
|
+
setProcessing(true);
|
|
445
|
+
try {
|
|
446
|
+
// API 호출 시뮬레이션
|
|
447
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
448
|
+
setEnabled(event.target.checked);
|
|
449
|
+
} finally {
|
|
450
|
+
setProcessing(false);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
return (
|
|
455
|
+
<Switch
|
|
456
|
+
checked={enabled}
|
|
457
|
+
onChange={handleToggle}
|
|
458
|
+
disabled={processing}
|
|
459
|
+
endDecorator={processing ? 'Processing...' : (enabled ? 'On' : 'Off')}
|
|
460
|
+
/>
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Best Practices
|
|
466
|
+
|
|
467
|
+
1. **명확한 라벨**: 스위치가 무엇을 제어하는지 명확하게 표시하세요.
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
// ✅ 명확한 라벨
|
|
471
|
+
<Typography component="label" endDecorator={<Switch />}>
|
|
472
|
+
이메일 알림 받기
|
|
473
|
+
</Typography>
|
|
474
|
+
|
|
475
|
+
// ❌ 모호한 라벨
|
|
476
|
+
<Typography component="label" endDecorator={<Switch />}>
|
|
477
|
+
설정
|
|
478
|
+
</Typography>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
2. **즉시 효과**: 스위치 토글은 즉시 효과가 나타나야 합니다.
|
|
482
|
+
|
|
483
|
+
3. **적절한 색상 사용**:
|
|
484
|
+
- 일반적인 기능: `primary` 또는 기본 색상
|
|
485
|
+
- 성공/활성화: `success`
|
|
486
|
+
- 주의사항: `warning`
|
|
487
|
+
- 위험한 기능: `danger`
|
|
488
|
+
|
|
489
|
+
4. **상태 표시**: 현재 상태를 명확히 보여주는 장식 요소를 활용하세요.
|
|
490
|
+
|
|
491
|
+
```tsx
|
|
492
|
+
<Switch
|
|
493
|
+
checked={enabled}
|
|
494
|
+
onChange={handleChange}
|
|
495
|
+
endDecorator={enabled ? '켜짐' : '꺼짐'}
|
|
496
|
+
color={enabled ? 'success' : 'neutral'}
|
|
497
|
+
/>
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
5. **그룹화**: 관련된 스위치들은 논리적으로 그룹화하세요.
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
<Stack spacing={3}>
|
|
504
|
+
<Typography level="title-md">알림 설정</Typography>
|
|
505
|
+
<Stack spacing={1} sx={{ pl: 1 }}>
|
|
506
|
+
<Switch label="이메일 알림" />
|
|
507
|
+
<Switch label="SMS 알림" />
|
|
508
|
+
<Switch label="푸시 알림" />
|
|
509
|
+
</Stack>
|
|
510
|
+
</Stack>
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Accessibility
|
|
514
|
+
|
|
515
|
+
Switch 컴포넌트는 다음과 같은 접근성 기능을 제공합니다:
|
|
516
|
+
|
|
517
|
+
### 키보드 탐색
|
|
518
|
+
|
|
519
|
+
- **Tab**: 스위치로 포커스 이동
|
|
520
|
+
- **Space**: 스위치 토글
|
|
521
|
+
- **Enter**: 스위치 토글 (라벨이 연결된 경우)
|
|
522
|
+
|
|
523
|
+
### ARIA 속성
|
|
524
|
+
|
|
525
|
+
- `role="switch"`: 스위치 역할 정의
|
|
526
|
+
- `aria-checked`: 현재 상태 표시
|
|
527
|
+
- `aria-label` 또는 `aria-labelledby`: 접근 가능한 이름 제공
|
|
528
|
+
|
|
529
|
+
### 추가 접근성 고려사항
|
|
530
|
+
|
|
531
|
+
```tsx
|
|
532
|
+
<Switch
|
|
533
|
+
slotProps={{
|
|
534
|
+
input: {
|
|
535
|
+
'aria-label': '다크 모드 활성화',
|
|
536
|
+
'aria-describedby': 'dark-mode-description',
|
|
537
|
+
},
|
|
538
|
+
}}
|
|
539
|
+
/>
|
|
540
|
+
<FormHelperText id="dark-mode-description">
|
|
541
|
+
화면을 어둡게 표시하여 눈의 피로를 줄입니다.
|
|
542
|
+
</FormHelperText>
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### 색상 대비 및 시각적 표시
|
|
546
|
+
|
|
547
|
+
```tsx
|
|
548
|
+
// 색상에만 의존하지 않고 텍스트 표시도 함께 제공
|
|
549
|
+
<Switch
|
|
550
|
+
checked={enabled}
|
|
551
|
+
onChange={handleChange}
|
|
552
|
+
endDecorator={
|
|
553
|
+
<Typography level="body-xs" sx={{ minWidth: 32 }}>
|
|
554
|
+
{enabled ? 'ON' : 'OFF'}
|
|
555
|
+
</Typography>
|
|
556
|
+
}
|
|
557
|
+
/>
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
## Performance Considerations
|
|
561
|
+
|
|
562
|
+
1. **상태 최적화**: 불필요한 리렌더링을 방지하기 위해 상태를 적절히 관리하세요.
|
|
563
|
+
|
|
564
|
+
```tsx
|
|
565
|
+
// ✅ 개별 상태 관리
|
|
566
|
+
const [emailNotify, setEmailNotify] = useState(false);
|
|
567
|
+
const [smsNotify, setSmsNotify] = useState(false);
|
|
568
|
+
|
|
569
|
+
// ❌ 전체 객체 업데이트로 인한 불필요한 리렌더링
|
|
570
|
+
const [settings, setSettings] = useState({ email: false, sms: false });
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
2. **비동기 처리**: API 호출이 필요한 경우 적절한 로딩 상태를 제공하세요.
|
|
574
|
+
|
|
575
|
+
3. **메모이제이션**: 복잡한 핸들러는 useCallback으로 메모이제이션하세요.
|
|
576
|
+
|
|
577
|
+
Switch는 직관적이고 접근 가능한 토글 인터페이스를 제공하는 핵심 입력 컴포넌트입니다. 적절한 라벨링과 시각적 피드백을 통해 사용자 친화적인 설정 및 제어 인터페이스를 만들 수 있습니다.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Textarea
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<Textarea name="Textarea" />
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
| Field | Description | Default |
|
|
10
|
+
| -------------- | ----------- | ---------- |
|
|
11
|
+
| name | — | "Textarea" |
|
|
12
|
+
| variant | — | — |
|
|
13
|
+
| color | — | — |
|
|
14
|
+
| size | — | — |
|
|
15
|
+
| label | — | — |
|
|
16
|
+
| startDecorator | — | — |
|
|
17
|
+
| endDecorator | — | — |
|
|
18
|
+
| required | — | — |
|
|
19
|
+
| disabled | — | — |
|
|
20
|
+
| error | — | — |
|
|
21
|
+
| onChange | — | — |
|
|
22
|
+
|
|
23
|
+
### Variants
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<>
|
|
27
|
+
<Textarea name="Solid" placeholder="Type in here…" variant="solid" />
|
|
28
|
+
<Textarea name="Soft" placeholder="Type in here…" variant="soft" />
|
|
29
|
+
<Textarea name="Outlined" placeholder="Type in here…" variant="outlined" />
|
|
30
|
+
<Textarea name="Plain" placeholder="Type in here…" variant="plain" />
|
|
31
|
+
</>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Sizes
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<>
|
|
38
|
+
<Textarea size="sm" name="Size" placeholder="Small" />
|
|
39
|
+
<Textarea size="md" name="Size" placeholder="Medium" />
|
|
40
|
+
<Textarea size="lg" name="Size" placeholder="Large" />
|
|
41
|
+
</>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Colors
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<>
|
|
48
|
+
<Textarea name="Primary" placeholder="Type in here…" variant="outlined" color="primary" />
|
|
49
|
+
<Textarea name="Neutral" placeholder="Type in here…" variant="outlined" color="neutral" />
|
|
50
|
+
<Textarea name="Danger" placeholder="Type in here…" variant="outlined" color="danger" />
|
|
51
|
+
<Textarea name="Warning" placeholder="Type in here…" variant="outlined" color="warning" />
|
|
52
|
+
</>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Variants
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<>
|
|
59
|
+
<Textarea name="Solid" placeholder="Type in here…" variant="solid" />
|
|
60
|
+
<Textarea name="Soft" placeholder="Type in here…" variant="soft" />
|
|
61
|
+
<Textarea name="Outlined" placeholder="Type in here…" variant="outlined" />
|
|
62
|
+
<Textarea name="Plain" placeholder="Type in here…" variant="plain" />
|
|
63
|
+
</>
|
|
64
|
+
```
|