@ceed/ads 1.23.2 → 1.23.4

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 (45) hide show
  1. package/dist/components/data-display/Badge.md +71 -39
  2. package/dist/components/data-display/InfoSign.md +74 -98
  3. package/dist/components/data-display/Typography.md +310 -61
  4. package/dist/components/feedback/CircularProgress.md +257 -0
  5. package/dist/components/feedback/Dialog.md +8 -4
  6. package/dist/components/feedback/Modal.md +7 -3
  7. package/dist/components/feedback/Skeleton.md +280 -0
  8. package/dist/components/feedback/llms.txt +2 -0
  9. package/dist/components/inputs/ButtonGroup.md +115 -106
  10. package/dist/components/inputs/Calendar.md +98 -459
  11. package/dist/components/inputs/CurrencyInput.md +181 -8
  12. package/dist/components/inputs/DatePicker.md +108 -436
  13. package/dist/components/inputs/DateRangePicker.md +130 -496
  14. package/dist/components/inputs/FilterMenu.md +169 -19
  15. package/dist/components/inputs/FilterableCheckboxGroup.md +119 -24
  16. package/dist/components/inputs/FormControl.md +368 -0
  17. package/dist/components/inputs/IconButton.md +137 -88
  18. package/dist/components/inputs/MonthPicker.md +95 -427
  19. package/dist/components/inputs/MonthRangePicker.md +89 -471
  20. package/dist/components/inputs/PercentageInput.md +183 -19
  21. package/dist/components/inputs/RadioButton.md +163 -35
  22. package/dist/components/inputs/RadioList.md +241 -0
  23. package/dist/components/inputs/RadioTileGroup.md +146 -62
  24. package/dist/components/inputs/Select.md +219 -328
  25. package/dist/components/inputs/Slider.md +334 -0
  26. package/dist/components/inputs/Switch.md +136 -376
  27. package/dist/components/inputs/Textarea.md +209 -11
  28. package/dist/components/inputs/Uploader/Uploader.md +145 -66
  29. package/dist/components/inputs/llms.txt +3 -0
  30. package/dist/components/navigation/Breadcrumbs.md +80 -322
  31. package/dist/components/navigation/Dropdown.md +92 -221
  32. package/dist/components/navigation/IconMenuButton.md +40 -502
  33. package/dist/components/navigation/InsetDrawer.md +68 -738
  34. package/dist/components/navigation/Link.md +39 -298
  35. package/dist/components/navigation/Menu.md +92 -285
  36. package/dist/components/navigation/MenuButton.md +55 -448
  37. package/dist/components/navigation/Pagination.md +47 -338
  38. package/dist/components/navigation/ProfileMenu.md +45 -268
  39. package/dist/components/navigation/Stepper.md +160 -28
  40. package/dist/components/navigation/Tabs.md +57 -316
  41. package/dist/components/surfaces/Sheet.md +150 -333
  42. package/dist/guides/ThemeProvider.md +116 -0
  43. package/dist/guides/llms.txt +9 -0
  44. package/dist/llms.txt +8 -0
  45. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ # RadioList
2
+
3
+ ## Introduction
4
+
5
+ RadioList is a convenience component that renders a group of radio buttons from a data array. It wraps RadioGroup and Radio internally, providing a simpler API for the common pattern of rendering a list of options. Pass an array of `{ label, value }` items and the component handles the rest.
6
+
7
+ ```tsx
8
+ <RadioList
9
+ items={defaultItems}
10
+ defaultValue="option1"
11
+ />
12
+ ```
13
+
14
+ | Field | Description | Default |
15
+ | ----------- | ----------- | ------- |
16
+ | size | — | — |
17
+ | color | — | — |
18
+ | orientation | — | — |
19
+ | disabled | — | — |
20
+
21
+ ## Usage
22
+
23
+ ```tsx
24
+ import { RadioList } from '@ceed/ads';
25
+
26
+ function MyComponent() {
27
+ return (
28
+ <RadioList
29
+ items={[
30
+ { label: 'Small', value: 'sm' },
31
+ { label: 'Medium', value: 'md' },
32
+ { label: 'Large', value: 'lg' },
33
+ ]}
34
+ defaultValue="md"
35
+ />
36
+ );
37
+ }
38
+ ```
39
+
40
+ ## Basic List
41
+
42
+ A simple radio list with three options and a default selection.
43
+
44
+ ```tsx
45
+ <RadioList items={[{
46
+ label: 'Small',
47
+ value: 'sm'
48
+ }, {
49
+ label: 'Medium',
50
+ value: 'md'
51
+ }, {
52
+ label: 'Large',
53
+ value: 'lg'
54
+ }]} defaultValue="md" />
55
+ ```
56
+
57
+ ## Controlled
58
+
59
+ Use `value` and `onChange` for controlled state management.
60
+
61
+ ```tsx
62
+ <Stack gap={2}>
63
+ <Typography level="body-sm">Selected: {value}</Typography>
64
+ <RadioList items={defaultItems} value={value} onChange={e => setValue((e.target as HTMLInputElement).value)} />
65
+ </Stack>
66
+ ```
67
+
68
+ ```tsx
69
+ function ControlledExample() {
70
+ const [value, setValue] = React.useState('option1');
71
+ return (
72
+ <RadioList
73
+ items={items}
74
+ value={value}
75
+ onChange={(e) => setValue((e.target as HTMLInputElement).value)}
76
+ />
77
+ );
78
+ }
79
+ ```
80
+
81
+ ## With Default Value
82
+
83
+ Use `defaultValue` for uncontrolled usage with an initial selection.
84
+
85
+ ```tsx
86
+ <RadioList items={defaultItems} defaultValue="option2" />
87
+ ```
88
+
89
+ ## Disabled
90
+
91
+ Set `disabled` to prevent all radio buttons from being interacted with.
92
+
93
+ ```tsx
94
+ <RadioList items={defaultItems} defaultValue="option1" disabled />
95
+ ```
96
+
97
+ ## Horizontal Layout
98
+
99
+ Set `orientation="horizontal"` to display options in a row.
100
+
101
+ ```tsx
102
+ <RadioList items={defaultItems} defaultValue="option1" orientation="horizontal" />
103
+ ```
104
+
105
+ ```tsx
106
+ <RadioList
107
+ items={items}
108
+ defaultValue="option1"
109
+ orientation="horizontal"
110
+ />
111
+ ```
112
+
113
+ ## Sizes
114
+
115
+ RadioList supports `sm`, `md` (default), and `lg` sizes. The size is applied to all radio buttons in the group.
116
+
117
+ ```tsx
118
+ <Stack gap={3}>
119
+ <Box>
120
+ <Typography level="body-sm" sx={{
121
+ mb: 1
122
+ }}>Small</Typography>
123
+ <RadioList items={defaultItems} defaultValue="option1" size="sm" />
124
+ </Box>
125
+ <Box>
126
+ <Typography level="body-sm" sx={{
127
+ mb: 1
128
+ }}>Medium</Typography>
129
+ <RadioList items={defaultItems} defaultValue="option1" size="md" />
130
+ </Box>
131
+ <Box>
132
+ <Typography level="body-sm" sx={{
133
+ mb: 1
134
+ }}>Large</Typography>
135
+ <RadioList items={defaultItems} defaultValue="option1" size="lg" />
136
+ </Box>
137
+ </Stack>
138
+ ```
139
+
140
+ ## Colors
141
+
142
+ Five semantic colors are available via the `color` prop.
143
+
144
+ ```tsx
145
+ <Stack gap={3}>
146
+ <RadioList items={defaultItems} defaultValue="option1" color="primary" />
147
+ <RadioList items={defaultItems} defaultValue="option1" color="neutral" />
148
+ <RadioList items={defaultItems} defaultValue="option1" color="danger" />
149
+ <RadioList items={defaultItems} defaultValue="option1" color="success" />
150
+ <RadioList items={defaultItems} defaultValue="option1" color="warning" />
151
+ </Stack>
152
+ ```
153
+
154
+ ## Common Use Cases
155
+
156
+ ### Settings Selection
157
+
158
+ ```tsx
159
+ function LanguageSetting() {
160
+ const [language, setLanguage] = React.useState('en');
161
+
162
+ return (
163
+ <FormControl>
164
+ <FormLabel>Language</FormLabel>
165
+ <RadioList
166
+ items={[
167
+ { label: 'English', value: 'en' },
168
+ { label: '한국어', value: 'ko' },
169
+ { label: '日本語', value: 'ja' },
170
+ ]}
171
+ value={language}
172
+ onChange={(e) => setLanguage((e.target as HTMLInputElement).value)}
173
+ />
174
+ </FormControl>
175
+ );
176
+ }
177
+ ```
178
+
179
+ ### Survey Options
180
+
181
+ ```tsx
182
+ function SatisfactionSurvey() {
183
+ return (
184
+ <FormControl>
185
+ <FormLabel>How satisfied are you?</FormLabel>
186
+ <RadioList
187
+ orientation="horizontal"
188
+ items={[
189
+ { label: 'Very Unsatisfied', value: '1' },
190
+ { label: 'Unsatisfied', value: '2' },
191
+ { label: 'Neutral', value: '3' },
192
+ { label: 'Satisfied', value: '4' },
193
+ { label: 'Very Satisfied', value: '5' },
194
+ ]}
195
+ />
196
+ </FormControl>
197
+ );
198
+ }
199
+ ```
200
+
201
+ ### Dynamic Options from API
202
+
203
+ ```tsx
204
+ function RoleSelector({ roles }: { roles: { id: string; name: string }[] }) {
205
+ return (
206
+ <RadioList
207
+ items={roles.map((role) => ({
208
+ label: role.name,
209
+ value: role.id,
210
+ }))}
211
+ />
212
+ );
213
+ }
214
+ ```
215
+
216
+ ## Best Practices
217
+
218
+ 1. **Use for mutually exclusive choices**: RadioList is for selecting exactly one option from a set. For multiple selections, use Checkbox or FilterableCheckboxGroup.
219
+
220
+ ```tsx
221
+ // ✅ Mutually exclusive — only one role allowed
222
+ <RadioList items={roles} />
223
+
224
+ // ❌ Multiple selections needed — use Checkbox instead
225
+ <RadioList items={permissions} />
226
+ ```
227
+
228
+ 2. **Provide a default value**: Pre-select the most common or recommended option to reduce user effort.
229
+
230
+ 3. **Keep labels concise**: Radio button labels should be short and scannable. Use descriptions elsewhere if more context is needed.
231
+
232
+ 4. **Limit visible options**: For more than 7 options, consider using a Select dropdown instead to save space.
233
+
234
+ 5. **Use horizontal layout sparingly**: Horizontal orientation works well for 2–4 short options. For longer lists, vertical is more readable.
235
+
236
+ ## Accessibility
237
+
238
+ - RadioList renders a `<RadioGroup>` with `role="radiogroup"`, and each option is a `<Radio>` with `role="radio"`.
239
+ - Keyboard navigation: Arrow keys move between options, Space selects the focused option.
240
+ - Wrap in a FormControl with FormLabel to provide an accessible group label.
241
+ - The `disabled` prop sets `aria-disabled` on all radio buttons in the group.
@@ -1,8 +1,12 @@
1
1
  # RadioTileGroup
2
2
 
3
- RadioTileGroup 컴포넌트는 타일 형태의 라디오 옵션을 표시하는 컴포넌트입니다. 각 옵션이 타일 형태로 나타나며, 사용자가 선택할 수 있습니다.
3
+ ## Introduction
4
4
 
5
- > 💡 **Form 구성 내장 prop 사용을 권장합니다**
5
+ RadioTileGroup is a selection component that displays radio options as visually distinct tiles. Unlike a standard radio button list, each option occupies a tile card, making selections more prominent and scannable. This is especially useful for choices that benefit from visual emphasis, such as plan selection, category picking, or preference surveys.
6
+
7
+ The component supports flexible layouts (horizontal, grid, vertical), icons via `startDecorator`, three sizes, and built-in form integration with `label`, `helperText`, `error`, and `required` props. It works in both controlled and uncontrolled modes.
8
+
9
+ > **Form 구성 시 내장 prop 사용을 권장합니다**
6
10
  >
7
11
  > 이 컴포넌트는 `label`, `helperText` 등의 Form 요소를 자체적으로 지원합니다.
8
12
  > Form을 구성할 때 Typography로 별도의 label이나 helperText를 만드는 대신, 컴포넌트의 내장 prop을 사용하세요.
@@ -33,18 +37,36 @@ RadioTileGroup 컴포넌트는 타일 형태의 라디오 옵션을 표시하는
33
37
  | error | — | — |
34
38
  | required | — | — |
35
39
 
36
- ## 기본형
37
-
38
- RadioTileGroup의 기본 형태입니다. 필수 속성 값으로 `options`를 받으며, 각 옵션은 `value`와 `label`을 포함해야 합니다.
40
+ ## Usage
39
41
 
40
42
  ```tsx
41
- <RadioTileGroup
42
- options={simpleOptions}
43
- useIndicator
44
- />
43
+ import { RadioTileGroup } from '@ceed/ads';
44
+
45
+ function MyComponent() {
46
+ const [value, setValue] = useState('');
47
+
48
+ const options = [
49
+ { value: 'option1', label: 'Option 1' },
50
+ { value: 'option2', label: 'Option 2' },
51
+ { value: 'option3', label: 'Option 3' },
52
+ ];
53
+
54
+ return (
55
+ <RadioTileGroup
56
+ label="Choose an option"
57
+ helperText="Select one of the options below"
58
+ options={options}
59
+ value={value}
60
+ onChange={(e) => setValue(e.target.value)}
61
+ useIndicator
62
+ />
63
+ );
64
+ }
45
65
  ```
46
66
 
47
- `label`과 `helperText`를 함께 사용하면 아래와 같은 모습입니다.
67
+ ## Label and Helper Text
68
+
69
+ Use the `label` and `helperText` props to add descriptive text above and below the tile group. The `required` prop appends a required indicator to the label.
48
70
 
49
71
  ```tsx
50
72
  <RadioTileGroup
@@ -55,10 +77,6 @@ RadioTileGroup의 기본 형태입니다. 필수 속성 값으로 `options`를
55
77
  />
56
78
  ```
57
79
 
58
- ## 필수 값 표시
59
-
60
- `required` 속성을 사용하여 필수 입력 필드임을 표시할 수 있습니다.
61
-
62
80
  ```tsx
63
81
  <RadioTileGroup
64
82
  options={simpleOptions}
@@ -69,11 +87,11 @@ RadioTileGroup의 기본 형태입니다. 필수 속성 값으로 `options`를
69
87
  />
70
88
  ```
71
89
 
72
- ## 레이아웃 옵션
90
+ ## Layout Options
73
91
 
74
92
  ### Flex
75
93
 
76
- `flex` 속성을 활성화하면 RadioTileGroup이 사용 가능한 공간을 균등하게 채웁니다.
94
+ Enable the `flex` prop to make tiles stretch and fill all available horizontal space equally.
77
95
 
78
96
  ```tsx
79
97
  <RadioTileGroup
@@ -85,7 +103,7 @@ RadioTileGroup의 기본 형태입니다. 필수 속성 값으로 `options`를
85
103
 
86
104
  ### Columns
87
105
 
88
- `columns` 속성을 사용하여 타일을 특정 수로 배치할 있습니다.
106
+ Use the `columns` prop to arrange tiles in a specific number of columns using a grid layout.
89
107
 
90
108
  ```tsx
91
109
  <RadioTileGroup
@@ -95,9 +113,9 @@ RadioTileGroup의 기본 형태입니다. 필수 속성 값으로 `options`를
95
113
  />
96
114
  ```
97
115
 
98
- ### Flex Columns 함께 사용
116
+ ### Flex with Columns
99
117
 
100
- `flex`와 `columns` 속성을 함께 사용하여 타일이 균등하게 공간을 채우면서 특정 수로 배치할 있습니다.
118
+ Combine `flex` and `columns` to create a grid where each tile stretches to fill its column width evenly.
101
119
 
102
120
  ```tsx
103
121
  <Box sx={{
@@ -113,9 +131,9 @@ Flex with Columns
113
131
  </Box>
114
132
  ```
115
133
 
116
- ### 수직 레이아웃
134
+ ### Vertical Layout
117
135
 
118
- `columns: 1`로 설정하면 타일이 수직으로 쌓이는 레이아웃을 만들 있습니다.
136
+ Set `columns={1}` to stack tiles vertically. This layout is well-suited for list-style selections like pricing plans or step-by-step options.
119
137
 
120
138
  ```tsx
121
139
  <Box sx={{
@@ -131,9 +149,9 @@ Vertical Layout (columns: 1)
131
149
  </Box>
132
150
  ```
133
151
 
134
- ## 정렬 옵션
152
+ ## Text Alignment
135
153
 
136
- `textAlign` 속성을 사용하여 타일 내부의 콘텐츠 정렬 방식을 설정할 있습니다. 기본값은 `center`이며, `start`로 설정하면 텍스트가 왼쪽으로 정렬됩니다.
154
+ The `textAlign` prop controls the alignment of content inside each tile. The default is `center`. Set it to `start` for left-aligned content.
137
155
 
138
156
  ```tsx
139
157
  <Box sx={{
@@ -162,9 +180,9 @@ Vertical Layout (columns: 1)
162
180
  </Box>
163
181
  ```
164
182
 
165
- ## Size
183
+ ## Sizes
166
184
 
167
- RadioTileGroup 가지 크기를 지원합니다: `sm`, `md`, `lg`. 기본값은 `sm`입니다.
185
+ RadioTileGroup supports three sizes: `sm` (default), `md`, and `lg`. Choose the size that best fits the density of your layout.
168
186
 
169
187
  ```tsx
170
188
  <Box sx={{
@@ -201,9 +219,9 @@ RadioTileGroup은 세 가지 크기를 지원합니다: `sm`, `md`, `lg`. 기본
201
219
  </Box>
202
220
  ```
203
221
 
204
- ## 아이콘 사용
222
+ ## Icons
205
223
 
206
- 옵션에 `startDecorator` 속성을 사용하여 아이콘을 추가할 있습니다.
224
+ Add icons to tiles using the `startDecorator` property on each option. Icons help users visually distinguish between choices at a glance.
207
225
 
208
226
  ```tsx
209
227
  <RadioTileGroup
@@ -224,11 +242,11 @@ RadioTileGroup은 세 가지 크기를 지원합니다: `sm`, `md`, `lg`. 기본
224
242
  />
225
243
  ```
226
244
 
227
- ## 상태 관리
245
+ ## State Management
228
246
 
229
- ### Controlled Component
247
+ ### Controlled
230
248
 
231
- RadioTileGroup은 상태 관리를 위한 제어 컴포넌트(Controlled Component)로 사용할 있습니다.
249
+ Pass `value` and `onChange` to fully control the selected state from the parent component. This is recommended when the selection participates in form state or triggers side effects.
232
250
 
233
251
  ```tsx
234
252
  <Box sx={{
@@ -244,9 +262,9 @@ Selected value: {selectedValue}
244
262
  </Box>
245
263
  ```
246
264
 
247
- ### Uncontrolled Component
265
+ ### Uncontrolled
248
266
 
249
- 또한 비제어 컴포넌트(Uncontrolled Component)로도 사용 가능합니다.
267
+ Use `defaultValue` to set an initial selection without managing state externally. The component tracks its own selection internally.
250
268
 
251
269
  ```tsx
252
270
  <Box sx={{
@@ -279,11 +297,11 @@ Uncontrolled Example (without Indicator)
279
297
  </Box>
280
298
  ```
281
299
 
282
- ## 비활성화 상태
300
+ ## Disabled State
283
301
 
284
- ### 전체 비활성화
302
+ ### Fully Disabled
285
303
 
286
- `disabled` 속성을 사용하여 모든 옵션을 비활성화할 있습니다.
304
+ Set the `disabled` prop on the group to disable all tiles.
287
305
 
288
306
  ```tsx
289
307
  <RadioTileGroup
@@ -292,9 +310,9 @@ Uncontrolled Example (without Indicator)
292
310
  />
293
311
  ```
294
312
 
295
- ### 개별 옵션 비활성화
313
+ ### Individual Disabled
296
314
 
297
- 옵션별로 `disabled` 속성을 설정하여 특정 옵션만 비활성화할 있습니다.
315
+ Set `disabled: true` on specific option objects to disable only those tiles while keeping the rest interactive.
298
316
 
299
317
  ```tsx
300
318
  <RadioTileGroup
@@ -312,11 +330,9 @@ Uncontrolled Example (without Indicator)
312
330
  />
313
331
  ```
314
332
 
315
- ## 상태 표시
333
+ ## Error State
316
334
 
317
- ### 오류 상태
318
-
319
- `error` 속성을 사용하여 오류 상태를 표시할 수 있습니다.
335
+ Use the `error` prop to indicate validation errors. Pair it with `helperText` to communicate the issue to the user.
320
336
 
321
337
  ```tsx
322
338
  <RadioTileGroup
@@ -328,9 +344,9 @@ Uncontrolled Example (without Indicator)
328
344
  />
329
345
  ```
330
346
 
331
- ### 필수 검증 예제
347
+ ### Form Validation Example
332
348
 
333
- `required` 속성과 함께 오류 상태를 활용하여 필수 검증을 있습니다. 아래는 제출 유효성 검사를 포함한 예제입니다.
349
+ Combine `required`, `error`, and `helperText` to build a complete form validation flow. The example below validates that the user has made a selection before submitting.
334
350
 
335
351
  ```tsx
336
352
  <Stack spacing={2} sx={{
@@ -347,11 +363,32 @@ Uncontrolled Example (without Indicator)
347
363
  </Stack>
348
364
  ```
349
365
 
350
- ## 활용 사례
366
+ ## Common Use Cases
367
+
368
+ ### Shipping Method Selection
369
+
370
+ Display delivery options with icons so users can choose intuitively.
351
371
 
352
- ### 배송 방법 선택
372
+ ```tsx
373
+ import { RadioTileGroup } from '@ceed/ads';
374
+ import HomeIcon from '@mui/icons-material/Home';
375
+ import LocalShippingIcon from '@mui/icons-material/LocalShipping';
376
+ import BusinessIcon from '@mui/icons-material/Business';
353
377
 
354
- RadioTileGroup은 배송 방법을 시각적으로 선택할 수 있는 인터페이스로 활용할 수 있습니다. 각 타일에 아이콘과 함께 배송 방법 정보를 표시하여 사용자가 직관적으로 선택할 수 있도록 합니다.
378
+ <RadioTileGroup
379
+ label="Shipping Method"
380
+ helperText="Delivery fees may vary by method."
381
+ options={[
382
+ { value: 'standard', label: 'Standard', startDecorator: <HomeIcon /> },
383
+ { value: 'express', label: 'Express', startDecorator: <LocalShippingIcon /> },
384
+ { value: 'business', label: 'Business', startDecorator: <BusinessIcon /> },
385
+ ]}
386
+ value={selected}
387
+ onChange={(e) => setSelected(e.target.value)}
388
+ size="md"
389
+ useIndicator
390
+ />
391
+ ```
355
392
 
356
393
  ```tsx
357
394
  <Box sx={{
@@ -374,9 +411,25 @@ RadioTileGroup은 배송 방법을 시각적으로 선택할 수 있는 인터
374
411
  </Box>
375
412
  ```
376
413
 
377
- ### 설문조사
414
+ ### Survey / Preference Selection
378
415
 
379
- 설문조사나 선호도 조사에서 다양한 선택지를 제공하는 활용할 있습니다. 타일에 선택지를 시각적으로 표현하여 사용자가 직관적으로 응답할 수 있도록 합니다.
416
+ Present survey options with icons in a multi-column grid for a clear, scannable layout.
417
+
418
+ ```tsx
419
+ <RadioTileGroup
420
+ label="What type of exercise do you prefer?"
421
+ options={[
422
+ { value: 'cardio', label: 'Cardio', startDecorator: <DirectionsRunIcon /> },
423
+ { value: 'strength', label: 'Strength', startDecorator: <FitnessCenterIcon /> },
424
+ { value: 'flexibility', label: 'Flexibility', startDecorator: <SelfImprovementIcon /> },
425
+ { value: 'balance', label: 'Balance', startDecorator: <BalanceIcon /> },
426
+ ]}
427
+ columns={2}
428
+ size="md"
429
+ value={selected}
430
+ onChange={(e) => setSelected(e.target.value)}
431
+ />
432
+ ```
380
433
 
381
434
  ```tsx
382
435
  <Box sx={{
@@ -403,21 +456,52 @@ RadioTileGroup은 배송 방법을 시각적으로 선택할 수 있는 인터
403
456
  </Box>
404
457
  ```
405
458
 
406
- ### 검증과 함께 사용
459
+ ### Pricing Plan Picker
407
460
 
408
- 검증 기능과 함께 사용하여 사용자가 필수 항목을 선택했는지 확인할 수 있습니다.
461
+ Use a vertical layout with `columns={1}` for plan or tier selection.
409
462
 
410
463
  ```tsx
411
- <Stack spacing={2} sx={{
412
- width: '100%',
413
- maxWidth: 500
414
- }}>
415
- <RadioTileGroup options={simpleOptions} value={selectedValue} onChange={handleChange} label="Choose your preferred option" helperText={error ? 'Please select an option' : 'This selection is required'} error={error} useIndicator={true} required={true} />
416
- <Box sx={{
417
- display: 'flex',
418
- justifyContent: 'flex-end'
419
- }}>
420
- <Button onClick={handleSubmit}>Submit</Button>
421
- </Box>
422
- </Stack>
464
+ <RadioTileGroup
465
+ label="Subscription Plan"
466
+ helperText="Select your preferred plan"
467
+ options={[
468
+ { value: 'basic', label: 'Basic Plan', startDecorator: <AttachMoneyIcon /> },
469
+ { value: 'pro', label: 'Pro Plan', startDecorator: <AttachMoneyIcon /> },
470
+ { value: 'premium', label: 'Premium Plan', startDecorator: <StarIcon /> },
471
+ ]}
472
+ columns={1}
473
+ size="md"
474
+ useIndicator
475
+ value={selected}
476
+ onChange={(e) => setSelected(e.target.value)}
477
+ />
423
478
  ```
479
+
480
+ ## Best Practices
481
+
482
+ 1. **Use built-in form props instead of external labels.** The component's `label`, `helperText`, `required`, and `error` props ensure consistent layout and accessibility. Avoid wrapping with separate Typography elements.
483
+
484
+ ```tsx
485
+ // ✅ Recommended
486
+ <RadioTileGroup label="Select option" helperText="Required field" required />
487
+
488
+ // ❌ Avoid
489
+ <Typography>Select option</Typography>
490
+ <RadioTileGroup options={options} />
491
+ <Typography color="danger">Required field</Typography>
492
+ ```
493
+
494
+ 2. **Choose the right layout for the number of options.** Use the default horizontal flow for 2-4 options. Use `columns` for 5+ options. Use `columns={1}` when each option has long labels or descriptions.
495
+
496
+ 3. **Prefer controlled mode in forms.** When RadioTileGroup is part of a form with validation or submission logic, use `value` and `onChange` for predictable state management.
497
+
498
+ 4. **Add icons only when they aid comprehension.** Icons via `startDecorator` are helpful for visually distinct categories (e.g., shipping methods). Avoid decorating every option if icons do not add meaning.
499
+
500
+ 5. **Always provide an error message.** When `error` is true, update `helperText` to explain the validation issue so users know how to fix it.
501
+
502
+ ## Accessibility
503
+
504
+ - RadioTileGroup renders a `<fieldset>` with a `<legend>` derived from the `label` prop, providing proper grouping for screen readers.
505
+ - Each tile is backed by a native `<input type="radio">`, ensuring full keyboard navigation (arrow keys to move between options, Space/Enter to select).
506
+ - The `disabled` prop correctly applies `aria-disabled` semantics to prevent interaction while keeping elements discoverable by assistive technologies.
507
+ - When `error` is set, pair it with descriptive `helperText` so that screen readers can announce the validation message via `aria-describedby`.