@ceed/ads 1.23.3 β†’ 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 (43) 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/Skeleton.md +280 -0
  6. package/dist/components/feedback/llms.txt +2 -0
  7. package/dist/components/inputs/ButtonGroup.md +115 -106
  8. package/dist/components/inputs/Calendar.md +98 -459
  9. package/dist/components/inputs/CurrencyInput.md +181 -8
  10. package/dist/components/inputs/DatePicker.md +108 -436
  11. package/dist/components/inputs/DateRangePicker.md +130 -496
  12. package/dist/components/inputs/FilterMenu.md +169 -19
  13. package/dist/components/inputs/FilterableCheckboxGroup.md +119 -24
  14. package/dist/components/inputs/FormControl.md +368 -0
  15. package/dist/components/inputs/IconButton.md +137 -88
  16. package/dist/components/inputs/MonthPicker.md +95 -427
  17. package/dist/components/inputs/MonthRangePicker.md +89 -471
  18. package/dist/components/inputs/PercentageInput.md +183 -19
  19. package/dist/components/inputs/RadioButton.md +163 -35
  20. package/dist/components/inputs/RadioList.md +241 -0
  21. package/dist/components/inputs/RadioTileGroup.md +146 -62
  22. package/dist/components/inputs/Select.md +219 -328
  23. package/dist/components/inputs/Slider.md +334 -0
  24. package/dist/components/inputs/Switch.md +136 -376
  25. package/dist/components/inputs/Textarea.md +209 -11
  26. package/dist/components/inputs/Uploader/Uploader.md +145 -66
  27. package/dist/components/inputs/llms.txt +3 -0
  28. package/dist/components/navigation/Breadcrumbs.md +80 -322
  29. package/dist/components/navigation/Dropdown.md +92 -221
  30. package/dist/components/navigation/IconMenuButton.md +40 -502
  31. package/dist/components/navigation/InsetDrawer.md +68 -738
  32. package/dist/components/navigation/Link.md +39 -298
  33. package/dist/components/navigation/Menu.md +92 -285
  34. package/dist/components/navigation/MenuButton.md +55 -448
  35. package/dist/components/navigation/Pagination.md +47 -338
  36. package/dist/components/navigation/ProfileMenu.md +45 -268
  37. package/dist/components/navigation/Stepper.md +160 -28
  38. package/dist/components/navigation/Tabs.md +57 -316
  39. package/dist/components/surfaces/Sheet.md +150 -333
  40. package/dist/guides/ThemeProvider.md +116 -0
  41. package/dist/guides/llms.txt +9 -0
  42. package/dist/llms.txt +8 -0
  43. package/package.json +1 -1
@@ -2,11 +2,19 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- > πŸ’‘ **Use built-in form props**
5
+ The Textarea component provides a multi-line text input field for collecting longer-form user input such as comments, descriptions, and notes. It is built on top of Joy UI's Textarea and automatically adjusts its height between `minRows` (default 2) and `maxRows` (default 4) as the user types.
6
+
7
+ Textarea integrates with the form system by wrapping itself in a FormControl, supporting built-in `label`, `helperText`, and `error` props. It also supports decorators, multiple visual variants, sizes, and color themes to fit a wide range of admin UI use cases.
8
+
9
+ > **Use built-in form props**
6
10
  >
7
11
  > This component natively supports form elements such as `label` and `helperText` props.
8
12
  > When building forms, use these built-in props instead of manually composing labels and helper text with Typography.
9
13
 
14
+ ## Playground
15
+
16
+ Interact with the Textarea component using the controls below.
17
+
10
18
  ```tsx
11
19
  <Textarea name="Textarea" />
12
20
  ```
@@ -25,7 +33,26 @@
25
33
  | error | β€” | β€” |
26
34
  | onChange | β€” | β€” |
27
35
 
28
- ### Variants
36
+ ## Usage
37
+
38
+ ```tsx
39
+ import { Textarea } from '@ceed/ads';
40
+
41
+ function MyComponent() {
42
+ return (
43
+ <Textarea
44
+ name="description"
45
+ label="Description"
46
+ placeholder="Enter a description..."
47
+ helperText="Provide a brief summary."
48
+ />
49
+ );
50
+ }
51
+ ```
52
+
53
+ ## Variants
54
+
55
+ Textarea supports four visual variants: `solid`, `soft`, `outlined`, and `plain`. The default variant is `outlined`.
29
56
 
30
57
  ```tsx
31
58
  <>
@@ -36,7 +63,16 @@
36
63
  </>
37
64
  ```
38
65
 
39
- ### Sizes
66
+ ```tsx
67
+ <Textarea variant="solid" placeholder="Solid" />
68
+ <Textarea variant="soft" placeholder="Soft" />
69
+ <Textarea variant="outlined" placeholder="Outlined" />
70
+ <Textarea variant="plain" placeholder="Plain" />
71
+ ```
72
+
73
+ ## Sizes
74
+
75
+ Textarea comes in three sizes: `sm`, `md`, and `lg`. The default size is `md`.
40
76
 
41
77
  ```tsx
42
78
  <>
@@ -46,7 +82,15 @@
46
82
  </>
47
83
  ```
48
84
 
49
- ### Colors
85
+ ```tsx
86
+ <Textarea size="sm" placeholder="Small" />
87
+ <Textarea size="md" placeholder="Medium" />
88
+ <Textarea size="lg" placeholder="Large" />
89
+ ```
90
+
91
+ ## Colors
92
+
93
+ Textarea supports semantic colors via the `color` prop: `primary`, `neutral`, `danger`, and `warning`.
50
94
 
51
95
  ```tsx
52
96
  <>
@@ -57,13 +101,167 @@
57
101
  </>
58
102
  ```
59
103
 
60
- ### Variants
104
+ ```tsx
105
+ <Textarea color="primary" placeholder="Primary" />
106
+ <Textarea color="neutral" placeholder="Neutral" />
107
+ <Textarea color="danger" placeholder="Danger" />
108
+ <Textarea color="warning" placeholder="Warning" />
109
+ ```
110
+
111
+ ## Required with Label and Helper Text
112
+
113
+ Use the `required`, `label`, and `helperText` props together to build complete form fields. The `required` prop adds an asterisk indicator to the label.
61
114
 
62
115
  ```tsx
63
- <>
64
- <Textarea name="Solid" placeholder="Type in here…" variant="solid" />
65
- <Textarea name="Soft" placeholder="Type in here…" variant="soft" />
66
- <Textarea name="Outlined" placeholder="Type in here…" variant="outlined" />
67
- <Textarea name="Plain" placeholder="Type in here…" variant="plain" />
68
- </>
116
+ <Textarea
117
+ name="Textarea"
118
+ placeholder="Type in here..."
119
+ helperText="I'm helper text"
120
+ label="Label"
121
+ required
122
+ />
69
123
  ```
124
+
125
+ ```tsx
126
+ <Textarea
127
+ label="Label"
128
+ helperText="I'm helper text"
129
+ placeholder="Type in here..."
130
+ required
131
+ />
132
+ ```
133
+
134
+ ## Common Use Cases
135
+
136
+ ### Feedback Form
137
+
138
+ ```tsx
139
+ import { Textarea, Button, Stack } from '@ceed/ads';
140
+
141
+ function FeedbackForm() {
142
+ const [value, setValue] = React.useState('');
143
+
144
+ return (
145
+ <Stack spacing={2}>
146
+ <Textarea
147
+ name="feedback"
148
+ label="Feedback"
149
+ placeholder="Tell us what you think..."
150
+ helperText="Your feedback helps us improve the service."
151
+ minRows={3}
152
+ maxRows={6}
153
+ value={value}
154
+ onChange={(e) => setValue(e.target.value)}
155
+ required
156
+ />
157
+ <Button disabled={!value.trim()}>Submit</Button>
158
+ </Stack>
159
+ );
160
+ }
161
+ ```
162
+
163
+ ### Error State with Validation
164
+
165
+ ```tsx
166
+ import { Textarea } from '@ceed/ads';
167
+
168
+ function ValidatedTextarea() {
169
+ const [value, setValue] = React.useState('');
170
+ const isError = value.length > 0 && value.length < 10;
171
+
172
+ return (
173
+ <Textarea
174
+ name="notes"
175
+ label="Notes"
176
+ placeholder="Write at least 10 characters..."
177
+ helperText={isError ? 'Must be at least 10 characters.' : 'Optional notes for this record.'}
178
+ error={isError}
179
+ value={value}
180
+ onChange={(e) => setValue(e.target.value)}
181
+ />
182
+ );
183
+ }
184
+ ```
185
+
186
+ ### Disabled Read-Only Display
187
+
188
+ ```tsx
189
+ import { Textarea } from '@ceed/ads';
190
+
191
+ function ReadOnlyNotes() {
192
+ return (
193
+ <Textarea
194
+ name="archived-notes"
195
+ label="Archived Notes"
196
+ value="This record has been archived and cannot be edited."
197
+ disabled
198
+ />
199
+ );
200
+ }
201
+ ```
202
+
203
+ ## Best Practices
204
+
205
+ 1. **Use built-in form props instead of manual composition.**
206
+
207
+ ```tsx
208
+ // βœ… Recommended
209
+ <Textarea label="Description" helperText="Keep it brief." />
210
+
211
+ // ❌ Avoid
212
+ <FormControl>
213
+ <Typography level="title-sm" component="label">Description</Typography>
214
+ <Textarea />
215
+ <Typography level="body-xs" color="neutral">Keep it brief.</Typography>
216
+ </FormControl>
217
+ ```
218
+
219
+ 2. **Set appropriate `minRows` and `maxRows` for the expected content length.**
220
+
221
+ ```tsx
222
+ // βœ… Short comment field
223
+ <Textarea minRows={2} maxRows={4} placeholder="Add a comment..." />
224
+
225
+ // βœ… Long description field
226
+ <Textarea minRows={4} maxRows={10} placeholder="Write a detailed description..." />
227
+ ```
228
+
229
+ 3. **Always provide a `name` prop for form submission.**
230
+
231
+ ```tsx
232
+ // βœ… Named textarea for form data
233
+ <Textarea name="description" label="Description" />
234
+
235
+ // ❌ Missing name β€” value won't be included in form data
236
+ <Textarea label="Description" />
237
+ ```
238
+
239
+ 4. **Use `error` and `helperText` together for validation feedback.**
240
+
241
+ ```tsx
242
+ // βœ… Clear error feedback
243
+ <Textarea
244
+ error={hasError}
245
+ helperText={hasError ? 'This field is required.' : 'Optional description.'}
246
+ />
247
+
248
+ // ❌ Error state without explanation
249
+ <Textarea error />
250
+ ```
251
+
252
+ 5. **Use a descriptive `placeholder` to guide user input.**
253
+
254
+ ```tsx
255
+ // βœ… Descriptive placeholder
256
+ <Textarea placeholder="Describe the issue in detail..." />
257
+
258
+ // ❌ Vague placeholder
259
+ <Textarea placeholder="Type here" />
260
+ ```
261
+
262
+ ## Accessibility
263
+
264
+ - The component automatically associates the `label` with the textarea element through FormControl, ensuring screen readers announce the label when the field receives focus.
265
+ - When `required` is set, the field is marked with `aria-required` and a visual asterisk indicator is added to the label.
266
+ - When `error` is set, the `helperText` is associated with the textarea via `aria-describedby`, allowing screen readers to announce the error message.
267
+ - Use a clear and descriptive `label` for every Textarea in a form. Avoid relying solely on `placeholder` text, as it disappears once the user starts typing and is not reliably announced by all screen readers.
@@ -1,6 +1,10 @@
1
1
  # Uploader
2
2
 
3
- Uploader μ»΄ν¬λ„ŒνŠΈλŠ” 파일 μ—…λ‘œλ“œλ₯Ό μœ„ν•œ μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. [κ΄€λ ¨ κ°€μ΄λ“œ](https://www.figma.com/design/NoAOnaPiP2H2lzvRhkBnGZ/CDS-v1.1?node-id=2600-3701\&t=WLh4JrGHlzDGMeV4-0)λŠ” figmaμ—μ„œλ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
3
+ ## Introduction
4
+
5
+ Uploader is a file upload component that provides a drag-and-drop zone along with a file browser for selecting files. It handles file type validation, individual and total file size limits, minimum and maximum file count constraints, and displays uploaded file previews with delete capabilities. The component automatically generates helper text based on its configuration and surfaces clear error messages when validation rules are violated.
6
+
7
+ Uploader is designed for forms where users need to attach documents, images, or other files. It supports both controlled error states via the `error` prop and internal validation that triggers automatically when files are added. A [Figma design guide](https://www.figma.com/design/NoAOnaPiP2H2lzvRhkBnGZ/CDS-v1.1?node-id=2600-3701\&t=WLh4JrGHlzDGMeV4-0) is available for reference.
4
8
 
5
9
  ```tsx
6
10
  <Uploader
@@ -23,10 +27,28 @@ Uploader μ»΄ν¬λ„ŒνŠΈλŠ” 파일 μ—…λ‘œλ“œλ₯Ό μœ„ν•œ μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. [κ΄€
23
27
  | onChange | β€” | β€” |
24
28
  | onDelete | β€” | β€” |
25
29
 
26
- ## κΈ°λ³Έν˜•
30
+ ## Usage
27
31
 
28
- ν•„μˆ˜ 속성 κ°’μœΌλ‘œ `accept`, `maxFileTotalSize`λ₯Ό λ°›κ³ , ν•΄λ‹Ή 속성 값듀을 λ°”νƒ•μœΌλ‘œ κΈ°λ³Έ `helperText`κ°€ μ„€μ •λ©λ‹ˆλ‹€.\
29
- μƒμ„±λœ `helperText`λŠ” File dropzone ν•˜λ‹¨μ— λ…ΈμΆœλ©λ‹ˆλ‹€.
32
+ ```tsx
33
+ import { Uploader } from '@ceed/ads';
34
+
35
+ function MyForm() {
36
+ return (
37
+ <Uploader
38
+ accept=".png,.jpg,.pdf"
39
+ maxFileTotalSize={10 * 1024 * 1024}
40
+ maxCount={5}
41
+ label="Attachments"
42
+ onChange={(files) => console.log('Files added:', files)}
43
+ onDelete={(fileId) => console.log('File removed:', fileId)}
44
+ />
45
+ );
46
+ }
47
+ ```
48
+
49
+ ## Default
50
+
51
+ The most basic Uploader requires `accept` and `maxFileTotalSize` props. Helper text is automatically generated from these values.
30
52
 
31
53
  ```tsx
32
54
  <Uploader
@@ -35,7 +57,9 @@ Uploader μ»΄ν¬λ„ŒνŠΈλŠ” 파일 μ—…λ‘œλ“œλ₯Ό μœ„ν•œ μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. [κ΄€
35
57
  />
36
58
  ```
37
59
 
38
- `label`κ³Ό ν•¨κ»˜ 쓰이면 μ•„λž˜μ™€ 같은 λͺ¨μŠ΅μž…λ‹ˆλ‹€.
60
+ ## With Label
61
+
62
+ Adding a `label` prop displays a title above the dropzone.
39
63
 
40
64
  ```tsx
41
65
  <Uploader
@@ -45,9 +69,9 @@ Uploader μ»΄ν¬λ„ŒνŠΈλŠ” 파일 μ—…λ‘œλ“œλ₯Ό μœ„ν•œ μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. [κ΄€
45
69
  />
46
70
  ```
47
71
 
48
- ## Size
72
+ ## Sizes
49
73
 
50
- SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
74
+ Two sizes are available: `sm` and `md`. Use the smaller size for compact form layouts.
51
75
 
52
76
  ```tsx
53
77
  <Stack gap={4}>
@@ -62,11 +86,20 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
62
86
  </Stack>
63
87
  ```
64
88
 
65
- ## Internal validation
89
+ ## File Type Restriction (Accepts)
90
+
91
+ The `accept` prop controls which file types are allowed. You can specify individual extensions (`.png,.jpg`) or use wildcards (`image/*`, `video/*`, `audio/*`) that map to predefined extension sets.
92
+
93
+ ```tsx
94
+ <Uploader
95
+ accept="image/png, image/jpeg, .pdf,.word,.txt,.doc,.docx"
96
+ maxFileTotalSize={31457280}
97
+ />
98
+ ```
66
99
 
67
- ### Min Count
100
+ ## Min Count Validation
68
101
 
69
- `minCount` κ°’κ³Ό ν˜„μž¬ μ—…λ‘œλ“œλœ μƒνƒœμ— λ”°λΌμ„œ λ‚΄λΆ€μ μœΌλ‘œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
102
+ The `minCount` prop sets a minimum number of required files. Validation triggers on form submission.
70
103
 
71
104
  ```tsx
72
105
  <>
@@ -82,10 +115,9 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
82
115
  </>
83
116
  ```
84
117
 
85
- ### Max Count
118
+ ## With Uploaded Files
86
119
 
87
- `maxCount` κ°’κ³Ό ν˜„μž¬ μ—…λ‘œλ“œλœ μƒνƒœμ— λ”°λΌμ„œ λ‚΄λΆ€μ μœΌλ‘œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.\
88
- μ•„λž˜μ˜ μƒν™©μ—μ„œ 두 개 μ΄μƒμ˜ νŒŒμΌμ„ μ—…λ‘œλ“œ ν•΄λ³΄μ„Έμš”.
120
+ Display pre-existing uploaded files and enforce `maxCount` limits. Try uploading additional files to trigger the limit error.
89
121
 
90
122
  ```tsx
91
123
  <Uploader
@@ -105,30 +137,9 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
105
137
  />
106
138
  ```
107
139
 
108
- ### Accepts
109
-
110
- `accept` 속성을 μ΄μš©ν•΄ νŠΉμ • 파일 ν˜•μ‹λ§Œ μ—…λ‘œλ“œν•  수 μžˆλ„λ‘ μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€.\
111
- 파일 ν™•μž₯자 μ œν•œμ„ μœ„ν•œ `accept`값은 ν•„μˆ˜μ μœΌλ‘œ λ°›κ³  있으며, ν™•μž₯자λ₯Ό νŠΉμ •ν•΄μ„œ μ‚¬μš©ν•˜κ±°λ‚˜(`.png,.jpeg,.txt`) `image/*`, `video/*`, `audio/*`와 같은 값을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
112
-
113
- 일뢀 λ””λ°”μ΄μŠ€μ—μ„  MIME type을 μ‚¬μš©ν•΄μ„œ 받을 νŒŒμΌμ„ μ œν•œν•˜λŠ” 것이 μ˜λ„μ™€ λ‹€λ₯Έ λ™μž‘μ„ μΌμœΌν‚¬ 수 있기 λ•Œλ¬Έμ— `image/*`, `video/*`, `audio/*`λ₯Ό μ‚¬μš©ν•˜λ©΄ λ‚΄λΆ€μ μœΌλ‘œ νŠΉμ • ν™•μž₯자 μ§‘ν•©κ³Ό λ§΅ν•‘λ©λ‹ˆλ‹€.
140
+ ## Total File Size Limit
114
141
 
115
- `image/*` = `.jpeg,.jpg,.png,.gif,.bmp,.tiff,.svg,.webp,.heic,.ico`\
116
- `video/*` = `.mp4,.avi,.mkv,.mov,.wmv,.flv,.webm,.mpeg,.3gp,.m4v`\
117
- `audio/*` = `.mp3,.wav,.flac,.aac,.ogg,.m4a,.wma,.aiff,.alac,.midi,.mp4`
118
-
119
- ```tsx
120
- <Uploader
121
- accept="image/png, image/jpeg, .pdf,.word,.txt,.doc,.docx"
122
- maxFileTotalSize={31457280}
123
- />
124
- ```
125
-
126
- ### File Size
127
-
128
- #### Total File Size
129
-
130
- `maxFileTotalSize`κ°’μœΌλ‘œ μ—…λ‘œλ“œ κ°€λŠ₯ν•œ 파일의 총 크기λ₯Ό μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€. `maxFileTotalSize`λŠ” ν•„μˆ˜ 속성 κ°’μž…λ‹ˆλ‹€.\
131
- μ•„λž˜μ˜ μƒν™©μ—μ„œ 1MB μ΄μƒμœΌλ‘œ νŒŒμΌμ„ μ—…λ‘œλ“œ ν•΄λ³΄μ„Έμš”.
142
+ The `maxFileTotalSize` prop limits the combined size of all uploaded files.
132
143
 
133
144
  ```tsx
134
145
  <Uploader
@@ -139,10 +150,9 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
139
150
  />
140
151
  ```
141
152
 
142
- #### Indivisual File Size
153
+ ## Individual File Size Limit
143
154
 
144
- `maxFileSize`κ°’μœΌλ‘œ 파일 ν•˜λ‚˜μ˜ μ΅œλŒ€ 크기λ₯Ό μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€.\
145
- μ•„λž˜μ˜ μƒν™©μ—μ„œ Total 1MB μ΄μƒμ˜ νŒŒμΌλ„ μ—…λ‘œλ“œ 해보고, 1MBκ°€ λ„˜λŠ” 단일 νŒŒμΌλ„ μ—…λ‘œλ“œ ν•΄λ³΄μ„Έμš”.
155
+ The `maxFileSize` prop limits the size of each individual file, independent of the total size limit.
146
156
 
147
157
  ```tsx
148
158
  <Uploader
@@ -156,9 +166,7 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
156
166
 
157
167
  ## Error State
158
168
 
159
- ### External Error
160
-
161
- `error` prop을 톡해 μ™ΈλΆ€μ—μ„œ μ—λŸ¬ μƒνƒœλ₯Ό μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ—λŸ¬ μƒνƒœμΌ λ•Œ Uploader의 λ“œλ‘­μ‘΄ ν…Œλ‘λ¦¬κ°€ λΉ¨κ°„μƒ‰μœΌλ‘œ λ³€κ²½λ©λ‹ˆλ‹€.
169
+ Use the `error` prop to externally control the error state, and `helperText` to display a custom error message.
162
170
 
163
171
  ```tsx
164
172
  <Uploader
@@ -170,9 +178,9 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
170
178
  />
171
179
  ```
172
180
 
173
- ### Validation Errors
181
+ ## Validation Errors
174
182
 
175
- λ‹€μ–‘ν•œ 검증 κ·œμΉ™μ„ μœ„λ°˜ν–ˆμ„ λ•Œ μžλ™μœΌλ‘œ λ°œμƒν•˜λŠ” μ—λŸ¬λ“€μ„ ν™•μΈν•΄λ³΄μ„Έμš”:
183
+ Demonstrates automatic validation error messages for various rule violations (file type, size, count).
176
184
 
177
185
  ```tsx
178
186
  <Stack gap={4}>
@@ -187,12 +195,9 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
187
195
  </Stack>
188
196
  ```
189
197
 
190
- ## Helper Text
198
+ ## Helper Text Variations
191
199
 
192
- ### Custom Helper Text
193
-
194
- `helperText` prop을 μ‚¬μš©ν•˜λ©΄ κΈ°λ³Έ μ•ˆλ‚΄ λ©”μ‹œμ§€ λŒ€μ‹  μ‚¬μš©μž μ •μ˜ λ©”μ‹œμ§€λ₯Ό ν‘œμ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€.\
195
- `helperText`κ°€ 제곡되면 λͺ¨λ“  κΈ°λ³Έ μ•ˆλ‚΄ λ©”μ‹œμ§€μ™€ μ—λŸ¬ λ©”μ‹œμ§€λ³΄λ‹€ μš°μ„ μ μœΌλ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€.
200
+ Comparison of auto-generated helper text, custom helper text, and error-state helper text.
196
201
 
197
202
  ```tsx
198
203
  <Stack gap={4}>
@@ -211,28 +216,102 @@ SizeλŠ” `sm`, `md` 두 μ‚¬μ΄μ¦ˆλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
211
216
  </Stack>
212
217
  ```
213
218
 
214
- ## Validation
219
+ ## Disabled State
220
+
221
+ The Uploader can be disabled to prevent file selection and drag-and-drop interactions.
222
+
223
+ ```tsx
224
+ <Uploader
225
+ accept=".png"
226
+ maxFileTotalSize={31457280}
227
+ label="Click to Upload or drag file"
228
+ disabled
229
+ />
230
+ ```
231
+
232
+ ## Common Use Cases
233
+
234
+ ### Profile Photo Upload
235
+
236
+ ```tsx
237
+ import { Uploader } from '@ceed/ads';
238
+
239
+ function ProfilePhotoUpload() {
240
+ return (
241
+ <Uploader
242
+ label="Profile Photo"
243
+ accept="image/*"
244
+ maxFileTotalSize={5 * 1024 * 1024}
245
+ maxCount={1}
246
+ maxFileSize={5 * 1024 * 1024}
247
+ helperText="Upload a profile photo (JPG, PNG, max 5MB)"
248
+ />
249
+ );
250
+ }
251
+ ```
252
+
253
+ ### Document Attachment in a Form
254
+
255
+ ```tsx
256
+ import { Uploader, Stack, Button } from '@ceed/ads';
257
+
258
+ function DocumentForm() {
259
+ return (
260
+ <form onSubmit={(e) => { e.preventDefault(); }}>
261
+ <Stack gap={3}>
262
+ <Uploader
263
+ label="Supporting Documents"
264
+ accept=".pdf,.doc,.docx"
265
+ maxFileTotalSize={30 * 1024 * 1024}
266
+ maxCount={10}
267
+ minCount={1}
268
+ maxFileSize={10 * 1024 * 1024}
269
+ />
270
+ <Button type="submit">Submit</Button>
271
+ </Stack>
272
+ </form>
273
+ );
274
+ }
275
+ ```
276
+
277
+ ### Multi-Image Gallery Upload
278
+
279
+ ```tsx
280
+ import { Uploader } from '@ceed/ads';
281
+
282
+ function GalleryUpload({ existingImages }) {
283
+ return (
284
+ <Uploader
285
+ label="Gallery Images"
286
+ accept="image/*"
287
+ maxFileTotalSize={50 * 1024 * 1024}
288
+ maxCount={20}
289
+ maxFileSize={10 * 1024 * 1024}
290
+ uploaded={existingImages}
291
+ onChange={(files) => console.log('New files:', files)}
292
+ onDelete={(id) => console.log('Removed:', id)}
293
+ />
294
+ );
295
+ }
296
+ ```
215
297
 
216
- Uploader μ»΄ν¬λ„ŒνŠΈλŠ” λ‹€μ–‘ν•œ λ‚΄λΆ€ 검증 κΈ°λŠ₯을 μ œκ³΅ν•˜λ©°, 검증 μ‹€νŒ¨ μ‹œ μžλ™μœΌλ‘œ μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€.
298
+ ## Best Practices
217
299
 
218
- ### Error Messages
300
+ - **Always set `maxFileTotalSize`.** This is a required prop that protects against excessively large uploads and informs users of the limit via auto-generated helper text.
219
301
 
220
- λ‚΄λΆ€ κ²€μ¦μ—μ„œ λ°œμƒν•˜λŠ” μ—λŸ¬ λ©”μ‹œμ§€λ“€:
302
+ - **Be specific with `accept`.** Use explicit extensions (`.png,.jpg,.pdf`) rather than wildcards when possible, as wildcard-to-extension mapping may vary across devices.
303
+ - βœ” `accept=".png,.jpg,.pdf"` -- clear and predictable
304
+ - ✘ `accept="*"` -- allows any file type with no validation
221
305
 
222
- - **파일 νƒ€μž… 였λ₯˜**: "Please upload the correct file type."
223
- - **파일 크기 초과**: "One or more files exceeded the maximum file size. Each file size must be \[크기] or less."
224
- - **총 파일 크기 초과**: "The total file size exceeds the maximum limit."
225
- - **파일 개수 초과**: "Exceeded the maximum number of files."
226
- - **μ΅œμ†Œ 파일 개수 미달**: "Please choose \[개수] files to upload." (form validation μ‹œ)
306
+ - **Provide meaningful labels.** Use the `label` prop to clearly indicate what type of files the user should upload and in what context.
227
307
 
228
- ### Helper Text Generation
308
+ - **Set `maxFileSize` for individual limits.** Even if `maxFileTotalSize` is set, large individual files can cause upload failures. Use `maxFileSize` to catch oversized files early.
229
309
 
230
- `helperText` prop이 μ œκ³΅λ˜μ§€ μ•ŠμœΌλ©΄ λ‹€μŒ 정보λ₯Ό 기반으둜 μžλ™ μƒμ„±λ©λ‹ˆλ‹€:
310
+ - **Use `minCount` with form validation.** The minimum count check triggers on form submission, not on file selection. Make sure the Uploader is inside a `<form>` element for this validation to work.
231
311
 
232
- 1. **ν—ˆμš© 파일 νƒ€μž…**: `accept` prop 기반
233
- - `image/*`, `video/*`, `audio/*` β†’ "Any image file", "Any video file", "Any audio file"
234
- - νŠΉμ • ν™•μž₯자 β†’ λŒ€λ¬Έμž ν™•μž₯자λͺ… λ‚˜μ—΄
235
- 2. **μ΅œλŒ€ 파일 크기**: `maxFileTotalSize` prop 기반
236
- 3. **파일 개수 μ œν•œ**: `maxCount` prop 기반 (μžˆλŠ” 경우)
312
+ ## Accessibility
237
313
 
238
- **μ˜ˆμ‹œ**: "PNG, Maximum 30MB, Up to 3 files"
314
+ - The dropzone is keyboard-accessible and can be activated via **Enter** or **Space** to open the file browser.
315
+ - Error messages and helper text are associated with the dropzone via ARIA attributes, ensuring screen readers announce validation feedback.
316
+ - Uploaded file items include accessible delete buttons with descriptive labels.
317
+ - The `label` prop renders as a visible label associated with the upload control for screen reader identification.
@@ -12,14 +12,17 @@
12
12
  - [DateRangePicker](./DateRangePicker.md)
13
13
  - [FilterableCheckboxGroup](./FilterableCheckboxGroup.md)
14
14
  - [FilterMenu](./FilterMenu.md)
15
+ - [FormControl](./FormControl.md)
15
16
  - [IconButton](./IconButton.md)
16
17
  - [Input](./Input.md)
17
18
  - [MonthPicker](./MonthPicker.md)
18
19
  - [MonthRangePicker](./MonthRangePicker.md)
19
20
  - [PercentageInput](./PercentageInput.md)
20
21
  - [Radio](./RadioButton.md)
22
+ - [RadioList](./RadioList.md)
21
23
  - [RadioTileGroup](./RadioTileGroup.md)
22
24
  - [Select](./Select.md)
25
+ - [Slider](./Slider.md)
23
26
  - [Switch](./Switch.md)
24
27
  - [Textarea](./Textarea.md)
25
28