@ceed/ads 1.29.1 → 1.30.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 (62) 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/ProfileMenu/ProfileMenu.d.ts +1 -1
  4. package/dist/components/SearchBar/SearchBar.d.ts +21 -0
  5. package/dist/components/SearchBar/index.d.ts +3 -0
  6. package/dist/components/data-display/Badge.md +39 -71
  7. package/dist/components/data-display/DataTable.md +1 -1
  8. package/dist/components/data-display/InfoSign.md +98 -74
  9. package/dist/components/data-display/Typography.md +97 -363
  10. package/dist/components/feedback/Dialog.md +62 -76
  11. package/dist/components/feedback/Modal.md +44 -259
  12. package/dist/components/feedback/llms.txt +0 -2
  13. package/dist/components/index.d.ts +2 -0
  14. package/dist/components/inputs/Autocomplete.md +107 -356
  15. package/dist/components/inputs/ButtonGroup.md +106 -115
  16. package/dist/components/inputs/Calendar.md +459 -98
  17. package/dist/components/inputs/CurrencyInput.md +5 -183
  18. package/dist/components/inputs/DatePicker.md +431 -108
  19. package/dist/components/inputs/DateRangePicker.md +492 -131
  20. package/dist/components/inputs/FilterMenu.md +19 -169
  21. package/dist/components/inputs/FilterableCheckboxGroup.md +23 -123
  22. package/dist/components/inputs/IconButton.md +88 -137
  23. package/dist/components/inputs/Input.md +0 -5
  24. package/dist/components/inputs/MonthPicker.md +422 -95
  25. package/dist/components/inputs/MonthRangePicker.md +466 -89
  26. package/dist/components/inputs/PercentageInput.md +16 -185
  27. package/dist/components/inputs/RadioButton.md +35 -163
  28. package/dist/components/inputs/RadioTileGroup.md +61 -150
  29. package/dist/components/inputs/SearchBar.md +44 -0
  30. package/dist/components/inputs/Select.md +326 -222
  31. package/dist/components/inputs/Switch.md +376 -136
  32. package/dist/components/inputs/Textarea.md +10 -213
  33. package/dist/components/inputs/Uploader/Uploader.md +66 -145
  34. package/dist/components/inputs/llms.txt +1 -3
  35. package/dist/components/navigation/Breadcrumbs.md +322 -80
  36. package/dist/components/navigation/Dropdown.md +221 -92
  37. package/dist/components/navigation/IconMenuButton.md +502 -40
  38. package/dist/components/navigation/InsetDrawer.md +738 -68
  39. package/dist/components/navigation/Link.md +298 -39
  40. package/dist/components/navigation/Menu.md +285 -92
  41. package/dist/components/navigation/MenuButton.md +448 -55
  42. package/dist/components/navigation/Pagination.md +338 -47
  43. package/dist/components/navigation/ProfileMenu.md +268 -45
  44. package/dist/components/navigation/Stepper.md +28 -160
  45. package/dist/components/navigation/Tabs.md +316 -57
  46. package/dist/components/surfaces/Sheet.md +334 -151
  47. package/dist/index.browser.js +15 -13
  48. package/dist/index.browser.js.map +4 -4
  49. package/dist/index.cjs +289 -288
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.js +426 -369
  52. package/dist/llms.txt +1 -8
  53. package/framer/index.js +1 -1
  54. package/package.json +16 -15
  55. package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
  56. package/dist/components/feedback/CircularProgress.md +0 -257
  57. package/dist/components/feedback/Skeleton.md +0 -280
  58. package/dist/components/inputs/FormControl.md +0 -361
  59. package/dist/components/inputs/RadioList.md +0 -241
  60. package/dist/components/inputs/Slider.md +0 -334
  61. package/dist/guides/ThemeProvider.md +0 -116
  62. package/dist/guides/llms.txt +0 -9
@@ -2,12 +2,6 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- PercentageInput is a specialized numeric input for entering percentage values. It automatically appends a `%` suffix, formats numbers with thousand separators, and supports min/max validation with built-in error states. Use it for any field where users need to enter a percentage, such as tax rates, discounts, or commission rates.
6
-
7
- > **Tip: Use built-in form props**
8
- >
9
- > This component supports `label` and `helperText` props directly. Use these instead of wrapping with FormControl + FormLabel + FormHelperText for simpler forms.
10
-
11
5
  ```tsx
12
6
  <PercentageInput placeholder="Enter a percentage" />
13
7
  ```
@@ -28,29 +22,7 @@ PercentageInput is a specialized numeric input for entering percentage values. I
28
22
  | min | — | — |
29
23
  | max | — | — |
30
24
 
31
- ## Usage
32
-
33
- ```tsx
34
- import { PercentageInput } from '@ceed/ads';
35
-
36
- function MyComponent() {
37
- const [rate, setRate] = React.useState(0);
38
-
39
- return (
40
- <PercentageInput
41
- label="Tax Rate"
42
- value={rate}
43
- onChange={(e) => setRate(e.target.value)}
44
- min={0}
45
- max={100}
46
- />
47
- );
48
- }
49
- ```
50
-
51
- ## Sizes
52
-
53
- PercentageInput supports three sizes: `sm`, `md` (default), and `lg`.
25
+ ### Sizes
54
26
 
55
27
  ```tsx
56
28
  <Stack gap={2}>
@@ -60,80 +32,66 @@ PercentageInput supports three sizes: `sm`, `md` (default), and `lg`.
60
32
  </Stack>
61
33
  ```
62
34
 
63
- ## Form Features
64
-
65
- ### With Label
35
+ ### Disabled
66
36
 
67
37
  ```tsx
68
38
  <PercentageInput
69
39
  placeholder="Enter a percentage"
70
- label="Percentage Input"
40
+ disabled
71
41
  />
72
42
  ```
73
43
 
74
- ```tsx
75
- <PercentageInput label="Discount Rate" />
76
- ```
77
-
78
- ### With Helper Text
44
+ ### Error
79
45
 
80
46
  ```tsx
81
47
  <PercentageInput
82
48
  placeholder="Enter a percentage"
83
- label="Percentage Input"
84
- helperText="Please enter a percentage"
49
+ error
85
50
  />
86
51
  ```
87
52
 
88
- ```tsx
89
- <PercentageInput label="Commission" helperText="Enter the commission percentage." />
90
- ```
91
-
92
- ### Error State
53
+ ### WithLabel
93
54
 
94
55
  ```tsx
95
56
  <PercentageInput
96
57
  placeholder="Enter a percentage"
97
- error
58
+ label="Percentage Input"
98
59
  />
99
60
  ```
100
61
 
101
- ### With Error Text
62
+ ### WithHelperText
102
63
 
103
64
  ```tsx
104
65
  <PercentageInput
105
66
  placeholder="Enter a percentage"
106
67
  label="Percentage Input"
107
68
  helperText="Please enter a percentage"
108
- error
109
69
  />
110
70
  ```
111
71
 
112
- ### Required
72
+ ### WithErrorText
113
73
 
114
74
  ```tsx
115
75
  <PercentageInput
116
76
  placeholder="Enter a percentage"
117
77
  label="Percentage Input"
118
78
  helperText="Please enter a percentage"
119
- required
79
+ error
120
80
  />
121
81
  ```
122
82
 
123
- ### Disabled
83
+ ### Required
124
84
 
125
85
  ```tsx
126
86
  <PercentageInput
127
87
  placeholder="Enter a percentage"
128
- disabled
88
+ label="Percentage Input"
89
+ helperText="Please enter a percentage"
90
+ required
129
91
  />
130
92
  ```
131
93
 
132
- ## Min / Max Validation
133
-
134
- Set `min` and `max` to enforce value boundaries. When the entered value is outside the range, the input automatically shows an error state.
135
-
136
- ### Minimum Value
94
+ ### Min
137
95
 
138
96
  ```tsx
139
97
  <PercentageInput
@@ -145,12 +103,7 @@ Set `min` and `max` to enforce value boundaries. When the entered value is outsi
145
103
  />
146
104
  ```
147
105
 
148
- ```tsx
149
- <PercentageInput min={10} defaultValue={5} />
150
- {/* Shows error because 5 < 10 */}
151
- ```
152
-
153
- ### Maximum Value
106
+ ### Max
154
107
 
155
108
  ```tsx
156
109
  <PercentageInput
@@ -161,125 +114,3 @@ Set `min` and `max` to enforce value boundaries. When the entered value is outsi
161
114
  defaultValue={5000}
162
115
  />
163
116
  ```
164
-
165
- ```tsx
166
- <PercentageInput max={500} defaultValue={5000} />
167
- {/* Shows error because 5000 > 500 */}
168
- ```
169
-
170
- ## Decimal Scale
171
-
172
- Use `maxDecimalScale` to control the number of decimal places allowed. The default is `0` (integers only).
173
-
174
- ```tsx
175
- // Integer only (default)
176
- <PercentageInput maxDecimalScale={0} />
177
-
178
- // Up to 2 decimal places: 12.34%
179
- <PercentageInput maxDecimalScale={2} />
180
-
181
- // Up to 3 decimal places: 12.345%
182
- <PercentageInput maxDecimalScale={3} />
183
- ```
184
-
185
- ## Minor Unit Mode
186
-
187
- When `useMinorUnit` is `true`, the component converts between display values and minor units based on `maxDecimalScale`. This is useful when your API stores percentages in integer form.
188
-
189
- ```tsx
190
- // Display shows "20.12%", onChange returns 20120
191
- <PercentageInput useMinorUnit maxDecimalScale={3} value={20120} />
192
-
193
- // Display shows "20.12%", onChange returns 20.12
194
- <PercentageInput useMinorUnit={false} maxDecimalScale={2} value={20.12} />
195
- ```
196
-
197
- ## Common Use Cases
198
-
199
- ### Discount Configuration
200
-
201
- ```tsx
202
- function DiscountSetting() {
203
- const [discount, setDiscount] = React.useState(0);
204
-
205
- return (
206
- <PercentageInput
207
- label="Discount"
208
- helperText="Enter 0-100%"
209
- value={discount}
210
- onChange={(e) => setDiscount(e.target.value)}
211
- min={0}
212
- max={100}
213
- />
214
- );
215
- }
216
- ```
217
-
218
- ### Tax Rate Settings
219
-
220
- ```tsx
221
- function TaxRateForm() {
222
- return (
223
- <Stack gap={2}>
224
- <PercentageInput
225
- label="VAT Rate"
226
- defaultValue={10}
227
- maxDecimalScale={2}
228
- min={0}
229
- max={100}
230
- />
231
- <PercentageInput
232
- label="Local Tax Rate"
233
- defaultValue={2.5}
234
- maxDecimalScale={2}
235
- min={0}
236
- max={50}
237
- />
238
- </Stack>
239
- );
240
- }
241
- ```
242
-
243
- ### Progress / Completion Tracker
244
-
245
- ```tsx
246
- function CompletionTracker({ value, onChange }) {
247
- return (
248
- <PercentageInput
249
- label="Completion"
250
- value={value}
251
- onChange={(e) => onChange(e.target.value)}
252
- min={0}
253
- max={100}
254
- helperText={value >= 100 ? 'Task is complete!' : `${100 - value}% remaining`}
255
- />
256
- );
257
- }
258
- ```
259
-
260
- ## Best Practices
261
-
262
- 1. **Always set min and max**: Bound the valid range to prevent unreasonable values.
263
-
264
- ```tsx
265
- // ✅ Clear bounds
266
- <PercentageInput min={0} max={100} />
267
-
268
- // ❌ Unbounded — user could enter 99999%
269
- <PercentageInput />
270
- ```
271
-
272
- 2. **Use `maxDecimalScale` appropriately**: Set it to `0` for whole percentages (discounts, progress), or `2`–`3` for precise rates (tax, interest).
273
-
274
- 3. **Use `useMinorUnit` for API compatibility**: When your backend stores percentages as integers (e.g., 1050 for 10.50%), enable `useMinorUnit` with the appropriate `maxDecimalScale`.
275
-
276
- 4. **Provide context via labels and helper text**: Clarify what the percentage represents and what range is valid.
277
-
278
- 5. **Handle edge cases**: Consider what happens at boundary values (0%, 100%) and negative percentages if allowed.
279
-
280
- ## Accessibility
281
-
282
- - The input has proper labeling via the `label` prop, linked with `aria-labelledby`.
283
- - Error states trigger `aria-invalid` with associated error messages via `aria-describedby`.
284
- - The `%` suffix is a visual decoration — ensure labels clarify that the field expects a percentage for screen readers.
285
- - Min/max validation errors are communicated visually; add descriptive `helperText` to make the valid range clear.
@@ -2,9 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- The Radio component provides a single-selection interface where users can choose exactly one option from a set of mutually exclusive choices. When one radio button is selected, any previously selected option in the same group is automatically deselected.
6
-
7
- Radio buttons are built on Joy UI's Radio and RadioGroup components, supporting multiple visual variants, sizes, colors, and advanced customization such as custom icons, overlay interactions, and icon-free designs. They are ideal for settings forms, preference panels, and any UI where a user must commit to a single option from a predefined list.
5
+ Radio 컴포넌트는 사용자가 여러 옵션 하나만 선택할 있는 단일 선택 인터페이스를 제공합니다. 라디오 버튼은 그룹으로 사용되어야 하며, 하나가 선택되면 다른 옵션들은 자동으로 해제됩니다.
8
6
 
9
7
  ```tsx
10
8
  <Radio />
@@ -30,28 +28,35 @@ Radio buttons are built on Joy UI's Radio and RadioGroup components, supporting
30
28
  ## Usage
31
29
 
32
30
  ```tsx
33
- import { Radio, RadioGroup } from '@ceed/ads';
31
+ import { Radio } from '@ceed/ads';
34
32
 
35
33
  function MyComponent() {
36
34
  const [selectedValue, setSelectedValue] = useState('option1');
37
35
 
38
36
  return (
39
- <RadioGroup
40
- name="example"
41
- value={selectedValue}
42
- onChange={(e) => setSelectedValue(e.target.value)}
43
- >
44
- <Radio value="option1" label="Option 1" />
45
- <Radio value="option2" label="Option 2" />
46
- <Radio value="option3" label="Option 3" />
47
- </RadioGroup>
37
+ <div>
38
+ <Radio
39
+ name="example"
40
+ value="option1"
41
+ checked={selectedValue === 'option1'}
42
+ onChange={(e) => setSelectedValue(e.target.value)}
43
+ label="옵션 1"
44
+ />
45
+ <Radio
46
+ name="example"
47
+ value="option2"
48
+ checked={selectedValue === 'option2'}
49
+ onChange={(e) => setSelectedValue(e.target.value)}
50
+ label="옵션 2"
51
+ />
52
+ </div>
48
53
  );
49
54
  }
50
55
  ```
51
56
 
52
- ## Variants
57
+ ## Examples
53
58
 
54
- Radio supports four visual variants: `outlined` (default), `soft`, `solid`, and `plain`. Choose a variant that fits the visual context of your form.
59
+ ### Variants
55
60
 
56
61
  ```tsx
57
62
  <FormControl>
@@ -65,9 +70,7 @@ Radio supports four visual variants: `outlined` (default), `soft`, `solid`, and
65
70
  </FormControl>
66
71
  ```
67
72
 
68
- ## Sizes
69
-
70
- Three size presets are available: `sm`, `md` (default), and `lg`. Use smaller sizes for compact layouts and larger sizes for touch-friendly interfaces.
73
+ ### Sizes
71
74
 
72
75
  ```tsx
73
76
  <FormControl>
@@ -80,9 +83,7 @@ Three size presets are available: `sm`, `md` (default), and `lg`. Use smaller si
80
83
  </FormControl>
81
84
  ```
82
85
 
83
- ## Colors
84
-
85
- Radio supports five semantic colors: `primary`, `neutral`, `danger`, `success`, and `warning`. Use semantic colors to convey meaning -- for example, `danger` for destructive options or `success` for confirmed selections.
86
+ ### Colors
86
87
 
87
88
  ```tsx
88
89
  <FormControl>
@@ -97,9 +98,9 @@ Radio supports five semantic colors: `primary`, `neutral`, `danger`, `success`,
97
98
  </FormControl>
98
99
  ```
99
100
 
100
- ## Custom Icons
101
+ ### Custom Icons
101
102
 
102
- Replace the default radio indicator with custom icons using the `checkedIcon` prop. This is useful for card-style selectors where the selection state needs a distinctive visual treatment.
103
+ 아이콘을 커스터마이징하여 특별한 용도로 사용할 있습니다.
103
104
 
104
105
  ```tsx
105
106
  <RadioGroup aria-label="platform" defaultValue="Website" overlay name="platform" sx={{
@@ -141,9 +142,9 @@ Replace the default radio indicator with custom icons using the `checkedIcon` pr
141
142
  </RadioGroup>
142
143
  ```
143
144
 
144
- ## No Icon
145
+ ### No Icon
145
146
 
146
- Use the `disableIcon` prop to hide the radio indicator entirely. This pattern is commonly used for card-style selectors where the entire card acts as the selectable target, and the selection state is conveyed through border or background styling.
147
+ 아이콘 없이 텍스트만으로 구성할 있습니다.
147
148
 
148
149
  ```tsx
149
150
  <Box sx={{
@@ -194,9 +195,9 @@ Storage
194
195
  </Box>
195
196
  ```
196
197
 
197
- ## Segmented Controls
198
+ ### Segmented Controls
198
199
 
199
- Radio buttons can be styled as segmented controls for compact, inline option switching. This pattern works well for toolbar-style controls where horizontal space is limited.
200
+ 세그먼트 컨트롤 스타일로 사용할 있습니다.
200
201
 
201
202
  ```tsx
202
203
  <Box sx={{
@@ -237,9 +238,9 @@ Radio buttons can be styled as segmented controls for compact, inline option swi
237
238
  </Box>
238
239
  ```
239
240
 
240
- ## Product Attributes
241
+ ### Product Attributes
241
242
 
242
- Radio groups can be customized to represent product attributes such as colors and sizes. Using `overlay`, `disableIcon`, and custom `Sheet` containers, you can create rich visual selectors.
243
+ 제품 속성 선택 등의 용도로 활용할 있습니다.
243
244
 
244
245
  ```tsx
245
246
  <Box sx={{
@@ -336,143 +337,14 @@ Size
336
337
  </Box>
337
338
  ```
338
339
 
339
- ## Common Use Cases
340
-
341
- ### Survey / Questionnaire Form
342
-
343
- ```tsx
344
- function SurveyQuestion() {
345
- const [answer, setAnswer] = useState('');
346
-
347
- return (
348
- <FormControl>
349
- <FormLabel>How satisfied are you with our service?</FormLabel>
350
- <RadioGroup
351
- name="satisfaction"
352
- value={answer}
353
- onChange={(e) => setAnswer(e.target.value)}
354
- >
355
- <Radio value="very-satisfied" label="Very Satisfied" color="success" />
356
- <Radio value="satisfied" label="Satisfied" />
357
- <Radio value="neutral" label="Neutral" />
358
- <Radio value="dissatisfied" label="Dissatisfied" color="warning" />
359
- <Radio value="very-dissatisfied" label="Very Dissatisfied" color="danger" />
360
- </RadioGroup>
361
- </FormControl>
362
- );
363
- }
364
- ```
365
-
366
- ### Payment Method Selection
367
-
368
- ```tsx
369
- function PaymentMethodSelector() {
370
- const [method, setMethod] = useState('credit-card');
371
-
372
- return (
373
- <FormControl>
374
- <FormLabel>Payment Method</FormLabel>
375
- <RadioGroup
376
- name="payment"
377
- value={method}
378
- onChange={(e) => setMethod(e.target.value)}
379
- sx={{ gap: 1.5 }}
380
- >
381
- {[
382
- { value: 'credit-card', label: 'Credit Card' },
383
- { value: 'bank-transfer', label: 'Bank Transfer' },
384
- { value: 'paypal', label: 'PayPal' },
385
- ].map((option) => (
386
- <Sheet key={option.value} variant="outlined" sx={{ p: 2, borderRadius: 'md' }}>
387
- <Radio
388
- overlay
389
- value={option.value}
390
- label={option.label}
391
- slotProps={{
392
- action: ({ checked }) => ({
393
- sx: {
394
- ...(checked && {
395
- '--variant-borderWidth': '2px',
396
- borderColor: 'primary.500',
397
- }),
398
- },
399
- }),
400
- }}
401
- />
402
- </Sheet>
403
- ))}
404
- </RadioGroup>
405
- </FormControl>
406
- );
407
- }
408
- ```
409
-
410
- ### Shipping Speed Selection
411
-
412
- ```tsx
413
- function ShippingOptions() {
414
- const [shipping, setShipping] = useState('standard');
415
-
416
- return (
417
- <FormControl>
418
- <FormLabel>Shipping Speed</FormLabel>
419
- <RadioGroup
420
- name="shipping"
421
- value={shipping}
422
- onChange={(e) => setShipping(e.target.value)}
423
- >
424
- <Radio value="standard" label="Standard (5-7 business days) - Free" />
425
- <Radio value="express" label="Express (2-3 business days) - $9.99" />
426
- <Radio value="overnight" label="Overnight (next day) - $24.99" />
427
- </RadioGroup>
428
- </FormControl>
429
- );
430
- }
431
- ```
432
-
433
340
  ## Best Practices
434
341
 
435
- 1. **Always use RadioGroup**: Wrap Radio buttons in a `RadioGroup` to ensure proper grouping, keyboard navigation, and mutual exclusivity.
436
-
437
- ```tsx
438
- // ✅ Wrapped in RadioGroup
439
- <RadioGroup name="options" value={value} onChange={handleChange}>
440
- <Radio value="a" label="Option A" />
441
- <Radio value="b" label="Option B" />
442
- </RadioGroup>
443
-
444
- // ❌ Standalone radios without a group
445
- <Radio name="options" value="a" label="Option A" />
446
- <Radio name="options" value="b" label="Option B" />
447
- ```
448
-
449
- 2. **Provide clear labels**: Every radio button must have a visible label or an `aria-label` to describe its purpose.
450
-
451
- ```tsx
452
- // ✅ Descriptive label
453
- <Radio value="monthly" label="Monthly billing ($10/month)" />
454
-
455
- // ❌ Vague label
456
- <Radio value="monthly" label="Option 1" />
457
- ```
458
-
459
- 3. **Set a default selection**: Pre-select the most common or recommended option using `defaultValue` or a controlled `value` to reduce user effort.
460
-
461
- ```tsx
462
- // ✅ Sensible default
463
- <RadioGroup defaultValue="standard" name="shipping">
464
- <Radio value="standard" label="Standard Shipping" />
465
- <Radio value="express" label="Express Shipping" />
466
- </RadioGroup>
467
- ```
342
+ 1. **그룹 사용**: Radio 버튼들은 반드시 동일한 `name` 속성을 가진 그룹으로 사용해야 합니다.
468
343
 
469
- 4. **Limit options to 2-7 items**: If more than 7 options exist, consider using a Select or Autocomplete component instead.
344
+ 2. **레이블 제공**: 접근성을 위해 항상 의미 있는 `label`을 제공하세요.
470
345
 
471
- 5. **Use vertical layout by default**: Vertical lists are easier to scan. Only use horizontal (`orientation="horizontal"`) when options are very short (e.g., segmented controls).
346
+ 3. **초기값 설정**: 사용자 경험을 위해 적절한 초기값을 설정하는 것이 좋습니다.
472
347
 
473
- ## Accessibility
348
+ 4. **적절한 간격**: 여러 라디오 버튼 간에는 충분한 간격을 두어 선택하기 쉽게 만드세요.
474
349
 
475
- - **Keyboard navigation**: Users can move between options using `Arrow Up` / `Arrow Down` (vertical) or `Arrow Left` / `Arrow Right` (horizontal). `Space` selects the focused option.
476
- - **ARIA roles**: `RadioGroup` renders with `role="radiogroup"`, and each `Radio` renders with `role="radio"` and `aria-checked` reflecting its state.
477
- - **Labeling**: Always connect a `FormLabel` to the `RadioGroup` via `aria-labelledby`, or provide an `aria-label` directly on the group so screen readers can announce the group purpose.
478
- - **Focus management**: When using `overlay` or `disableIcon` patterns, ensure the interactive area is clearly communicated -- the `overlay` prop extends the clickable area to the parent container, which is also reflected in focus styling.
350
+ 5. **상태 관리**: 제어 컴포넌트로 사용하여 상태를 명확히 관리하세요.