@ceed/cds 1.28.1 → 1.29.0-next.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.
Files changed (63) hide show
  1. package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
  2. package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
  3. package/dist/components/SearchBar/SearchBar.d.ts +21 -0
  4. package/dist/components/SearchBar/index.d.ts +3 -0
  5. package/dist/components/data-display/DataTable.md +1 -1
  6. package/dist/components/data-display/InfoSign.md +91 -74
  7. package/dist/components/data-display/Typography.md +94 -411
  8. package/dist/components/feedback/Dialog.md +62 -76
  9. package/dist/components/feedback/Modal.md +138 -430
  10. package/dist/components/feedback/llms.txt +0 -2
  11. package/dist/components/index.d.ts +2 -1
  12. package/dist/components/inputs/Autocomplete.md +107 -356
  13. package/dist/components/inputs/ButtonGroup.md +104 -115
  14. package/dist/components/inputs/CurrencyInput.md +5 -183
  15. package/dist/components/inputs/DatePicker.md +431 -108
  16. package/dist/components/inputs/DateRangePicker.md +492 -131
  17. package/dist/components/inputs/FilterableCheckboxGroup.md +19 -145
  18. package/dist/components/inputs/IconButton.md +88 -137
  19. package/dist/components/inputs/Input.md +73 -204
  20. package/dist/components/inputs/MonthPicker.md +422 -95
  21. package/dist/components/inputs/MonthRangePicker.md +466 -89
  22. package/dist/components/inputs/PercentageInput.md +16 -185
  23. package/dist/components/inputs/RadioButton.md +35 -163
  24. package/dist/components/inputs/SearchBar.md +44 -0
  25. package/dist/components/inputs/Select.md +326 -222
  26. package/dist/components/inputs/Switch.md +376 -143
  27. package/dist/components/inputs/Textarea.md +10 -213
  28. package/dist/components/inputs/Uploader/Uploader.md +66 -145
  29. package/dist/components/inputs/llms.txt +1 -4
  30. package/dist/components/navigation/Breadcrumbs.md +308 -57
  31. package/dist/components/navigation/Drawer.md +0 -180
  32. package/dist/components/navigation/Dropdown.md +215 -98
  33. package/dist/components/navigation/IconMenuButton.md +502 -40
  34. package/dist/components/navigation/InsetDrawer.md +650 -281
  35. package/dist/components/navigation/Link.md +348 -31
  36. package/dist/components/navigation/Menu.md +285 -92
  37. package/dist/components/navigation/MenuButton.md +448 -55
  38. package/dist/components/navigation/Pagination.md +338 -47
  39. package/dist/components/navigation/Stepper.md +28 -160
  40. package/dist/components/navigation/Tabs.md +316 -57
  41. package/dist/components/surfaces/Accordions.md +804 -49
  42. package/dist/components/surfaces/Card.md +157 -97
  43. package/dist/components/surfaces/Divider.md +234 -83
  44. package/dist/components/surfaces/Sheet.md +328 -153
  45. package/dist/index.cjs +411 -574
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +400 -507
  48. package/dist/llms.txt +1 -9
  49. package/framer/index.js +1 -1
  50. package/package.json +17 -22
  51. package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
  52. package/dist/components/RadioTileGroup/RadioTileGroup.d.ts +0 -56
  53. package/dist/components/RadioTileGroup/index.d.ts +0 -3
  54. package/dist/components/feedback/CircularProgress.md +0 -257
  55. package/dist/components/feedback/Skeleton.md +0 -280
  56. package/dist/components/inputs/FormControl.md +0 -361
  57. package/dist/components/inputs/RadioList.md +0 -241
  58. package/dist/components/inputs/RadioTileGroup.md +0 -507
  59. package/dist/components/inputs/Slider.md +0 -334
  60. package/dist/guides/ThemeProvider.md +0 -89
  61. package/dist/guides/llms.txt +0 -9
  62. package/dist/index.browser.js +0 -224
  63. package/dist/index.browser.js.map +0 -7
@@ -2,9 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- The Switch component is a toggle input that lets users turn an option on or off. It is built on Joy UI's Switch and provides a variety of sizes, colors, variants, and decorator slots for icons or text.
6
-
7
- Switches are best suited for binary settings that take effect immediately, such as enabling notifications, toggling dark mode, or activating a feature. Unlike a checkbox (which is often part of a form submission), a switch communicates an instant state change.
5
+ Switch 컴포넌트는 사용자가 옵션을 켜고 있는 토글 형태의 입력 요소입니다. Joy UI Switch 기반으로 하며, 다양한 크기, 색상, 장식 요소를 지원합니다. 설정 화면, 기능 활성화/비활성화, 모드 전환 등에 주로 사용됩니다.
8
6
 
9
7
  ```tsx
10
8
  <Switch />
@@ -27,18 +25,23 @@ import { Switch } from '@ceed/cds';
27
25
  function MyComponent() {
28
26
  const [enabled, setEnabled] = useState(false);
29
27
 
30
- return (
31
- <Switch
32
- checked={enabled}
33
- onChange={(e) => setEnabled(e.target.checked)}
34
- />
35
- );
28
+ return <Switch checked={enabled} onChange={(e) => setEnabled(e.target.checked)} />;
36
29
  }
37
30
  ```
38
31
 
39
- ## With Labels
32
+ ## Examples
33
+
34
+ ### Basic Usage
35
+
36
+ 가장 기본적인 Switch 사용법입니다.
37
+
38
+ ```tsx
39
+ <Switch />
40
+ ```
41
+
42
+ ### With Labels
40
43
 
41
- Use `FormControl` with `FormLabel` and `FormHelperText` to provide a label and description alongside the switch. The `orientation="horizontal"` layout places the label on the left and the switch on the right.
44
+ 라벨과 함께 사용하는 Switch입니다. 컨트롤 내에서 설명과 함께 사용할 있습니다.
42
45
 
43
46
  ```tsx
44
47
  <FormControl orientation="horizontal" sx={{
@@ -61,9 +64,9 @@ Use `FormControl` with `FormLabel` and `FormHelperText` to provide a label and d
61
64
  </FormControl>
62
65
  ```
63
66
 
64
- ## Inline Labels
67
+ ### Inline Labels
65
68
 
66
- For simpler cases, wrap the switch inside a `Typography` component rendered as a `<label>`. This connects the text and switch semantically without requiring a `FormControl`.
69
+ 인라인 형태로 텍스트와 함께 사용할 있습니다.
67
70
 
68
71
  ```tsx
69
72
  <Typography component="label" endDecorator={<Switch sx={{
@@ -73,9 +76,9 @@ Turn alarm on
73
76
  </Typography>
74
77
  ```
75
78
 
76
- ## With Decorators
79
+ ### With Decorators
77
80
 
78
- Use `startDecorator` and `endDecorator` to place icons or text around the switch. This is particularly useful for theme toggles or any context where visual cues reinforce the on/off meaning.
81
+ 아이콘이나 다른 요소를 장식으로 추가할 있습니다.
79
82
 
80
83
  ```tsx
81
84
  <Switch color={dark ? 'primary' : 'danger'} slotProps={{
@@ -89,9 +92,9 @@ Use `startDecorator` and `endDecorator` to place icons or text around the switch
89
92
  })} />} checked={dark} onChange={event => setDark(event.target.checked)} />
90
93
  ```
91
94
 
92
- ## Track Children
95
+ ### Track Children
93
96
 
94
- Display text or symbols inside the switch track using `slotProps.track.children`. This provides an always-visible label (e.g., "On" / "Off" or "I" / "0") directly on the track.
97
+ 트랙 내부에 텍스트나 다른 요소를 표시할 있습니다.
95
98
 
96
99
  ```tsx
97
100
  <Stack direction="row" spacing={4}>
@@ -133,9 +136,9 @@ Display text or symbols inside the switch track using `slotProps.track.children`
133
136
  </Stack>
134
137
  ```
135
138
 
136
- ## Thumb Children
139
+ ### Thumb Children
137
140
 
138
- Place an icon inside the switch thumb using `slotProps.thumb.children`. This is useful for adding a small visual indicator that moves with the toggle.
141
+ 썸(토글 버튼) 내부에 아이콘을 표시할 있습니다.
139
142
 
140
143
  ```tsx
141
144
  <Switch size="lg" slotProps={{
@@ -150,96 +153,36 @@ Place an icon inside the switch thumb using `slotProps.thumb.children`. This is
150
153
  }} />
151
154
  ```
152
155
 
153
- ## All Variants Overview
154
-
155
- A comprehensive view of all color and decoration combinations.
156
-
157
- ```tsx
158
- <Stack direction="row" spacing={4}>
159
- {([undefined, 'primary', 'warning', 'success', 'danger', 'neutral'] as const).map(color => <Stack key={color} spacing={2}>
160
- <Switch color={color} />
161
- <Switch color={color} checked />
162
- <Switch color={color} startDecorator={<LightModeIcon />} endDecorator={<DarkModeIcon />} />
163
- <Switch color={color} slotProps={{
164
- input: {
165
- 'aria-label': 'Dark mode'
166
- },
167
- thumb: {
168
- children: <DarkModeIcon fontSize="inherit" />
169
- },
170
- track: {
171
- children: <React.Fragment>
172
- <span>I</span>
173
- <span>0</span>
174
- </React.Fragment>,
175
- sx: {
176
- justifyContent: 'space-around'
177
- }
178
- }
179
- }} sx={{
180
- '--Switch-thumbSize': '27px',
181
- '--Switch-trackWidth': '52px',
182
- '--Switch-trackHeight': '31px'
183
- }} />
184
- <Typography component="label" startDecorator={<Switch sx={{
185
- ml: 1
186
- }} color={color} />}>
187
- Label
188
- </Typography>
189
- </Stack>)}
190
- </Stack>
191
- ```
192
-
193
156
  ## Common Use Cases
194
157
 
195
158
  ### Settings Panel
196
159
 
197
- ```tsx
198
- function SettingsPanel() {
199
- const [notifications, setNotifications] = useState(true);
200
- const [autoSave, setAutoSave] = useState(false);
201
-
202
- return (
203
- <Stack spacing={3}>
204
- <FormControl
205
- orientation="horizontal"
206
- sx={{ width: 400, justifyContent: 'space-between' }}
207
- >
208
- <div>
209
- <FormLabel>Notifications</FormLabel>
210
- <FormHelperText sx={{ mt: 0 }}>
211
- Receive alerts when new messages arrive.
212
- </FormHelperText>
213
- </div>
214
- <Switch
215
- checked={notifications}
216
- onChange={(e) => setNotifications(e.target.checked)}
217
- color={notifications ? 'success' : 'neutral'}
218
- />
219
- </FormControl>
160
+ 설정 패널에서 기능을 활성화/비활성화할 때 사용합니다.
220
161
 
221
- <FormControl
222
- orientation="horizontal"
223
- sx={{ width: 400, justifyContent: 'space-between' }}
224
- >
225
- <div>
226
- <FormLabel>Auto Save</FormLabel>
227
- <FormHelperText sx={{ mt: 0 }}>
228
- Automatically save your work every 30 seconds.
229
- </FormHelperText>
230
- </div>
231
- <Switch
232
- checked={autoSave}
233
- onChange={(e) => setAutoSave(e.target.checked)}
234
- />
235
- </FormControl>
236
- </Stack>
237
- );
238
- }
162
+ ```tsx
163
+ <Stack spacing={3}>
164
+ <FormControl orientation="horizontal" sx={{ width: 400, justifyContent: 'space-between' }}>
165
+ <div>
166
+ <FormLabel>알림 받기</FormLabel>
167
+ <FormHelperText sx={{ mt: 0 }}>새로운 메시지가 도착했을 때 알림을 받습니다.</FormHelperText>
168
+ </div>
169
+ <Switch checked={notifications} onChange={(e) => setNotifications(e.target.checked)} color="success" />
170
+ </FormControl>
171
+
172
+ <FormControl orientation="horizontal" sx={{ width: 400, justifyContent: 'space-between' }}>
173
+ <div>
174
+ <FormLabel>자동 저장</FormLabel>
175
+ <FormHelperText sx={{ mt: 0 }}>작업 내용을 자동으로 저장합니다.</FormHelperText>
176
+ </div>
177
+ <Switch checked={autoSave} onChange={(e) => setAutoSave(e.target.checked)} />
178
+ </FormControl>
179
+ </Stack>
239
180
  ```
240
181
 
241
182
  ### Theme Toggle
242
183
 
184
+ 다크 모드/라이트 모드 전환에 자주 사용됩니다.
185
+
243
186
  ```tsx
244
187
  function ThemeToggle() {
245
188
  const [darkMode, setDarkMode] = useState(false);
@@ -252,86 +195,376 @@ function ThemeToggle() {
252
195
  startDecorator={<LightModeIcon />}
253
196
  endDecorator={<DarkModeIcon />}
254
197
  slotProps={{
255
- input: { 'aria-label': 'Toggle dark mode' },
198
+ input: { 'aria-label': '다크 모드 토글' },
256
199
  }}
257
200
  />
258
201
  );
259
202
  }
260
203
  ```
261
204
 
262
- ### Feature Flag with Status Text
205
+ ### Feature Flags
206
+
207
+ 기능의 활성화/비활성화를 제어할 때 사용합니다.
263
208
 
264
209
  ```tsx
265
- function FeatureToggle() {
266
- const [betaEnabled, setBetaEnabled] = useState(false);
210
+ <Card>
211
+ <CardContent>
212
+ <Typography level="title-md" sx={{ mb: 2 }}>
213
+ 실험적 기능
214
+ </Typography>
267
215
 
268
- return (
269
- <FormControl
270
- orientation="horizontal"
271
- sx={{ justifyContent: 'space-between' }}
216
+ <Stack spacing={2}>
217
+ <FormControl orientation="horizontal" sx={{ justifyContent: 'space-between' }}>
218
+ <FormLabel>베타 기능 활성화</FormLabel>
219
+ <Switch
220
+ checked={betaFeatures}
221
+ onChange={(e) => setBetaFeatures(e.target.checked)}
222
+ color="warning"
223
+ endDecorator={betaFeatures ? 'On' : 'Off'}
224
+ />
225
+ </FormControl>
226
+
227
+ <FormControl orientation="horizontal" sx={{ justifyContent: 'space-between' }}>
228
+ <FormLabel>고급 모드</FormLabel>
229
+ <Switch checked={advancedMode} onChange={(e) => setAdvancedMode(e.target.checked)} disabled={!betaFeatures} />
230
+ </FormControl>
231
+ </Stack>
232
+ </CardContent>
233
+ </Card>
234
+ ```
235
+
236
+ ### List Items with Switches
237
+
238
+ 목록 아이템에서 각 항목을 개별적으로 제어할 때 사용합니다.
239
+
240
+ ```tsx
241
+ <List>
242
+ {permissions.map((permission) => (
243
+ <ListItem
244
+ key={permission.id}
245
+ endAction={
246
+ <Switch
247
+ checked={permission.enabled}
248
+ onChange={(e) => handlePermissionToggle(permission.id, e.target.checked)}
249
+ size="sm"
250
+ color={permission.enabled ? 'success' : 'neutral'}
251
+ />
252
+ }
272
253
  >
273
- <FormLabel>Enable Beta Features</FormLabel>
274
- <Switch
275
- checked={betaEnabled}
276
- onChange={(e) => setBetaEnabled(e.target.checked)}
277
- color="warning"
278
- endDecorator={betaEnabled ? 'On' : 'Off'}
279
- />
280
- </FormControl>
254
+ <ListItemContent>
255
+ <Typography level="title-sm">{permission.name}</Typography>
256
+ <Typography level="body-sm" color="neutral">
257
+ {permission.description}
258
+ </Typography>
259
+ </ListItemContent>
260
+ </ListItem>
261
+ ))}
262
+ </List>
263
+ ```
264
+
265
+ ### Controlled Form
266
+
267
+ 폼 상태 관리와 함께 사용하는 예제입니다.
268
+
269
+ ```tsx
270
+ function UserPreferences() {
271
+ const [preferences, setPreferences] = useState({
272
+ emailNotifications: true,
273
+ smsNotifications: false,
274
+ pushNotifications: true,
275
+ darkMode: false,
276
+ });
277
+
278
+ const handleToggle = (key: keyof typeof preferences) => (event: React.ChangeEvent<HTMLInputElement>) => {
279
+ setPreferences((prev) => ({
280
+ ...prev,
281
+ [key]: event.target.checked,
282
+ }));
283
+ };
284
+
285
+ return (
286
+ <form onSubmit={handleSubmit}>
287
+ <Stack spacing={3}>
288
+ <Typography level="h4">알림 설정</Typography>
289
+
290
+ <Stack spacing={2}>
291
+ <Typography
292
+ component="label"
293
+ endDecorator={
294
+ <Switch
295
+ checked={preferences.emailNotifications}
296
+ onChange={handleToggle('emailNotifications')}
297
+ sx={{ ml: 1 }}
298
+ />
299
+ }
300
+ >
301
+ 이메일 알림
302
+ </Typography>
303
+
304
+ <Typography
305
+ component="label"
306
+ endDecorator={
307
+ <Switch
308
+ checked={preferences.smsNotifications}
309
+ onChange={handleToggle('smsNotifications')}
310
+ sx={{ ml: 1 }}
311
+ />
312
+ }
313
+ >
314
+ SMS 알림
315
+ </Typography>
316
+
317
+ <Typography
318
+ component="label"
319
+ endDecorator={
320
+ <Switch
321
+ checked={preferences.pushNotifications}
322
+ onChange={handleToggle('pushNotifications')}
323
+ sx={{ ml: 1 }}
324
+ />
325
+ }
326
+ >
327
+ 푸시 알림
328
+ </Typography>
329
+ </Stack>
330
+
331
+ <Divider />
332
+
333
+ <Typography
334
+ component="label"
335
+ endDecorator={
336
+ <Switch
337
+ checked={preferences.darkMode}
338
+ onChange={handleToggle('darkMode')}
339
+ startDecorator={<LightModeIcon />}
340
+ endDecorator={<DarkModeIcon />}
341
+ sx={{ ml: 1 }}
342
+ />
343
+ }
344
+ >
345
+ 다크 모드
346
+ </Typography>
347
+
348
+ <Button type="submit">설정 저장</Button>
349
+ </Stack>
350
+ </form>
281
351
  );
282
352
  }
283
353
  ```
284
354
 
285
- ## Best Practices
355
+ ## Props and Customization
286
356
 
287
- 1. **Use switches for immediate effects**: Switches should apply their change instantly without requiring a "Save" button. If the setting requires a form submission, use a checkbox instead.
357
+ ### Colors
358
+
359
+ 다양한 색상을 적용할 수 있습니다.
360
+
361
+ ```tsx
362
+ <Stack direction="row" spacing={2}>
363
+ <Switch color="primary" checked />
364
+ <Switch color="success" checked />
365
+ <Switch color="warning" checked />
366
+ <Switch color="danger" checked />
367
+ <Switch color="neutral" checked />
368
+ </Stack>
369
+ ```
370
+
371
+ ### Sizes
372
+
373
+ 스위치의 크기를 조절할 수 있습니다.
374
+
375
+ ```tsx
376
+ <Stack direction="row" spacing={2} alignItems="center">
377
+ <Switch size="sm" checked />
378
+ <Switch size="md" checked />
379
+ <Switch size="lg" checked />
380
+ </Stack>
381
+ ```
382
+
383
+ ### Variants
384
+
385
+ 다양한 시각적 스타일을 적용할 수 있습니다.
386
+
387
+ ```tsx
388
+ <Stack direction="row" spacing={2}>
389
+ <Switch variant="solid" checked />
390
+ <Switch variant="soft" checked />
391
+ <Switch variant="outlined" checked />
392
+ <Switch variant="plain" checked />
393
+ </Stack>
394
+ ```
395
+
396
+ ### Custom Styling
397
+
398
+ CSS 변수를 통해 세밀한 커스터마이징이 가능합니다.
288
399
 
289
400
  ```tsx
290
- // ✅ Immediate effect -- toggling notifications on/off
291
401
  <Switch
292
- checked={notificationsEnabled}
293
- onChange={(e) => toggleNotifications(e.target.checked)}
402
+ checked={customSwitch}
403
+ onChange={(e) => setCustomSwitch(e.target.checked)}
404
+ sx={{
405
+ '--Switch-thumbSize': '24px',
406
+ '--Switch-trackWidth': '60px',
407
+ '--Switch-trackHeight': '32px',
408
+ '--Switch-trackRadius': '16px',
409
+ '--Switch-thumbRadius': '12px',
410
+ }}
294
411
  />
412
+ ```
413
+
414
+ ## States
415
+
416
+ ### Disabled State
295
417
 
296
- // Deferred effect requiring form submission -- use Checkbox instead
297
- <form onSubmit={handleSubmit}>
298
- <Switch checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />
299
- <Button type="submit">Save</Button>
300
- </form>
418
+ 비활성 상태의 스위치입니다.
419
+
420
+ ```tsx
421
+ <Stack direction="row" spacing={2}>
422
+ <Switch disabled />
423
+ <Switch disabled checked />
424
+ </Stack>
301
425
  ```
302
426
 
303
- 2. **Always provide a label**: Every switch needs a visible text label or an `aria-label` so users understand what it controls.
427
+ ### Loading/Processing State
428
+
429
+ 처리 중일 때의 시각적 피드백을 제공할 수 있습니다.
304
430
 
305
431
  ```tsx
306
- // Clear label via FormControl
307
- <FormControl orientation="horizontal">
308
- <FormLabel>Email Notifications</FormLabel>
309
- <Switch checked={enabled} onChange={handleChange} />
310
- </FormControl>
432
+ function ProcessingSwitch() {
433
+ const [processing, setProcessing] = useState(false);
434
+ const [enabled, setEnabled] = useState(false);
435
+
436
+ const handleToggle = async (event: React.ChangeEvent<HTMLInputElement>) => {
437
+ setProcessing(true);
438
+ try {
439
+ // API 호출 시뮬레이션
440
+ await new Promise((resolve) => setTimeout(resolve, 1000));
441
+ setEnabled(event.target.checked);
442
+ } finally {
443
+ setProcessing(false);
444
+ }
445
+ };
311
446
 
312
- // ❌ No label -- unclear what the switch does
313
- <Switch checked={enabled} onChange={handleChange} />
447
+ return (
448
+ <Switch
449
+ checked={enabled}
450
+ onChange={handleToggle}
451
+ disabled={processing}
452
+ endDecorator={processing ? 'Processing...' : enabled ? 'On' : 'Off'}
453
+ />
454
+ );
455
+ }
314
456
  ```
315
457
 
316
- 3. **Use semantic colors to reinforce meaning**: Apply `color="success"` for active/enabled states and `color="danger"` for risky toggles. Avoid using color as the sole indicator -- pair it with text.
458
+ ## Best Practices
459
+
460
+ 1. **명확한 라벨**: 스위치가 무엇을 제어하는지 명확하게 표시하세요.
461
+
462
+ ```tsx
463
+ // ✅ 명확한 라벨
464
+ <Typography component="label" endDecorator={<Switch />}>
465
+ 이메일 알림 받기
466
+ </Typography>
467
+
468
+ // ❌ 모호한 라벨
469
+ <Typography component="label" endDecorator={<Switch />}>
470
+ 설정
471
+ </Typography>
472
+ ```
473
+
474
+ 2. **즉시 효과**: 스위치 토글은 즉시 효과가 나타나야 합니다.
475
+
476
+ 3. **적절한 색상 사용**:
477
+ - 일반적인 기능: `primary` 또는 기본 색상
478
+ - 성공/활성화: `success`
479
+ - 주의사항: `warning`
480
+ - 위험한 기능: `danger`
481
+
482
+ 4. **상태 표시**: 현재 상태를 명확히 보여주는 장식 요소를 활용하세요.
317
483
 
318
484
  ```tsx
319
- // ✅ Color + text indicator
320
485
  <Switch
321
486
  checked={enabled}
322
487
  onChange={handleChange}
488
+ endDecorator={enabled ? '켜짐' : '꺼짐'}
323
489
  color={enabled ? 'success' : 'neutral'}
324
- endDecorator={enabled ? 'On' : 'Off'}
325
490
  />
326
491
  ```
327
492
 
328
- 4. **Handle async operations gracefully**: If toggling triggers an API call, disable the switch and show a processing indicator until the operation completes.
493
+ 5. **그룹화**: 관련된 스위치들은 논리적으로 그룹화하세요.
329
494
 
330
- 5. **Group related switches logically**: Place related switches under a shared heading and use consistent spacing to create a scannable settings layout.
495
+ ```tsx
496
+ <Stack spacing={3}>
497
+ <Typography level="title-md">알림 설정</Typography>
498
+ <Stack spacing={1} sx={{ pl: 1 }}>
499
+ <Switch label="이메일 알림" />
500
+ <Switch label="SMS 알림" />
501
+ <Switch label="푸시 알림" />
502
+ </Stack>
503
+ </Stack>
504
+ ```
331
505
 
332
506
  ## Accessibility
333
507
 
334
- - **Role and state**: The Switch renders an `<input type="checkbox" role="switch">` with `aria-checked` reflecting the current state. Screen readers announce it as a switch, not a checkbox.
335
- - **Keyboard interaction**: `Tab` moves focus to the switch. `Space` toggles the state. No additional key bindings are needed.
336
- - **Labeling**: Use `FormLabel`, a `<label>` wrapper (via `Typography component="label"`), or `slotProps.input['aria-label']` to provide an accessible name. Use `aria-describedby` to connect supplementary descriptions.
337
- - **Visual indicators beyond color**: Do not rely solely on color to communicate state. Use `endDecorator` text (e.g., "On" / "Off") or track children to ensure the state is perceivable without color vision.
508
+ Switch 컴포넌트는 다음과 같은 접근성 기능을 제공합니다:
509
+
510
+ ### 키보드 탐색
511
+
512
+ - **Tab**: 스위치로 포커스 이동
513
+ - **Space**: 스위치 토글
514
+ - **Enter**: 스위치 토글 (라벨이 연결된 경우)
515
+
516
+ ### ARIA 속성
517
+
518
+ - `role="switch"`: 스위치 역할 정의
519
+ - `aria-checked`: 현재 상태 표시
520
+ - `aria-label` 또는 `aria-labelledby`: 접근 가능한 이름 제공
521
+
522
+ ### 추가 접근성 고려사항
523
+
524
+ ```tsx
525
+ <Switch
526
+ slotProps={{
527
+ input: {
528
+ 'aria-label': '다크 모드 활성화',
529
+ 'aria-describedby': 'dark-mode-description',
530
+ },
531
+ }}
532
+ />
533
+ <FormHelperText id="dark-mode-description">
534
+ 화면을 어둡게 표시하여 눈의 피로를 줄입니다.
535
+ </FormHelperText>
536
+ ```
537
+
538
+ ### 색상 대비 및 시각적 표시
539
+
540
+ ```tsx
541
+ // 색상에만 의존하지 않고 텍스트 표시도 함께 제공
542
+ <Switch
543
+ checked={enabled}
544
+ onChange={handleChange}
545
+ endDecorator={
546
+ <Typography level="body-xs" sx={{ minWidth: 32 }}>
547
+ {enabled ? 'ON' : 'OFF'}
548
+ </Typography>
549
+ }
550
+ />
551
+ ```
552
+
553
+ ## Performance Considerations
554
+
555
+ 1. **상태 최적화**: 불필요한 리렌더링을 방지하기 위해 상태를 적절히 관리하세요.
556
+
557
+ ```tsx
558
+ // ✅ 개별 상태 관리
559
+ const [emailNotify, setEmailNotify] = useState(false);
560
+ const [smsNotify, setSmsNotify] = useState(false);
561
+
562
+ // ❌ 전체 객체 업데이트로 인한 불필요한 리렌더링
563
+ const [settings, setSettings] = useState({ email: false, sms: false });
564
+ ```
565
+
566
+ 2. **비동기 처리**: API 호출이 필요한 경우 적절한 로딩 상태를 제공하세요.
567
+
568
+ 3. **메모이제이션**: 복잡한 핸들러는 useCallback으로 메모이제이션하세요.
569
+
570
+ Switch는 직관적이고 접근 가능한 토글 인터페이스를 제공하는 핵심 입력 컴포넌트입니다. 적절한 라벨링과 시각적 피드백을 통해 사용자 친화적인 설정 및 제어 인터페이스를 만들 수 있습니다.