@ceed/ads 1.30.0 → 1.30.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.
- package/dist/Overview.md +5 -5
- package/dist/components/data-display/Avatar.md +85 -74
- package/dist/components/data-display/Badge.md +23 -5
- package/dist/components/data-display/Chip.md +49 -35
- package/dist/components/data-display/DataTable.md +93 -0
- package/dist/components/data-display/InfoSign.md +15 -5
- package/dist/components/data-display/Markdown.md +22 -26
- package/dist/components/data-display/Table.md +63 -53
- package/dist/components/data-display/Tooltip.md +70 -58
- package/dist/components/data-display/Typography.md +28 -11
- package/dist/components/feedback/Alert.md +86 -74
- package/dist/components/feedback/CircularProgress.md +20 -5
- package/dist/components/feedback/Dialog.md +8 -12
- package/dist/components/feedback/Modal.md +12 -16
- package/dist/components/feedback/Skeleton.md +20 -5
- package/dist/components/inputs/Autocomplete.md +8 -10
- package/dist/components/inputs/Button.md +107 -87
- package/dist/components/inputs/ButtonGroup.md +20 -5
- package/dist/components/inputs/Calendar.md +25 -5
- package/dist/components/inputs/Checkbox.md +171 -450
- package/dist/components/inputs/CurrencyInput.md +25 -5
- package/dist/components/inputs/DatePicker.md +39 -5
- package/dist/components/inputs/DateRangePicker.md +29 -5
- package/dist/components/inputs/FilterMenu.md +85 -9
- package/dist/components/inputs/FilterableCheckboxGroup.md +23 -8
- package/dist/components/inputs/FormControl.md +34 -6
- package/dist/components/inputs/IconButton.md +21 -5
- package/dist/components/inputs/Input.md +254 -68
- package/dist/components/inputs/MonthPicker.md +28 -5
- package/dist/components/inputs/MonthRangePicker.md +26 -5
- package/dist/components/inputs/PercentageInput.md +28 -5
- package/dist/components/inputs/RadioButton.md +26 -5
- package/dist/components/inputs/RadioList.md +23 -6
- package/dist/components/inputs/RadioTileGroup.md +40 -8
- package/dist/components/inputs/Select.md +59 -5
- package/dist/components/inputs/Slider.md +26 -5
- package/dist/components/inputs/Switch.md +23 -5
- package/dist/components/inputs/Textarea.md +27 -5
- package/dist/components/inputs/Uploader/Uploader.md +24 -5
- package/dist/components/layout/Box.md +66 -58
- package/dist/components/layout/Container.md +9 -13
- package/dist/components/layout/Grid.md +91 -75
- package/dist/components/layout/Stack.md +85 -70
- package/dist/components/navigation/Breadcrumbs.md +23 -14
- package/dist/components/navigation/Dropdown.md +29 -20
- package/dist/components/navigation/IconMenuButton.md +24 -11
- package/dist/components/navigation/InsetDrawer.md +16 -5
- package/dist/components/navigation/Link.md +30 -14
- package/dist/components/navigation/Menu.md +33 -20
- package/dist/components/navigation/MenuButton.md +26 -12
- package/dist/components/navigation/NavigationGroup.md +7 -11
- package/dist/components/navigation/NavigationItem.md +8 -12
- package/dist/components/navigation/Navigator.md +5 -9
- package/dist/components/navigation/Pagination.md +21 -12
- package/dist/components/navigation/ProfileMenu.md +17 -5
- package/dist/components/navigation/Stepper.md +18 -5
- package/dist/components/navigation/Tabs.md +37 -14
- package/dist/components/surfaces/Accordions.md +12 -16
- package/dist/components/surfaces/Card.md +59 -47
- package/dist/components/surfaces/Divider.md +70 -61
- package/dist/components/surfaces/Sheet.md +18 -5
- package/package.json +1 -1
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
# Input
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Introduction
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
>
|
|
7
|
-
> 이 컴포넌트는 `label`, `helperText` 등의 Form 요소를 자체적으로 지원합니다.
|
|
8
|
-
> Form을 구성할 때 Typography로 별도의 label이나 helperText를 만드는 대신, 컴포넌트의 내장 prop을 사용하세요.
|
|
5
|
+
Input is a single-line text field component for capturing user input. Built on Joy UI's Input with Framer Motion animation support, it includes built-in form field composition (`label`, `helperText`, `error`) so you can build complete form fields without manual `FormControl` wrappers. It supports clearable inputs, password visibility toggling, and start/end decorators.
|
|
9
6
|
|
|
10
7
|
```tsx
|
|
11
8
|
<Input />
|
|
@@ -34,17 +31,33 @@ Input 컴포넌트는 사용자로부터 텍스트 입력을 받기 위한 기
|
|
|
34
31
|
| sx | — | — |
|
|
35
32
|
| className | — | — |
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
> **Use built-in form props**
|
|
35
|
+
>
|
|
36
|
+
> This component natively supports `label` and `helperText` props.
|
|
37
|
+
> When building forms, use these built-in props instead of manually composing labels and helper text with Typography.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
## Usage
|
|
40
40
|
|
|
41
41
|
```tsx
|
|
42
|
-
|
|
42
|
+
import { Input } from '@ceed/ads';
|
|
43
|
+
|
|
44
|
+
function MyComponent() {
|
|
45
|
+
const [value, setValue] = useState('');
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Input
|
|
49
|
+
label="Name"
|
|
50
|
+
placeholder="Enter your name"
|
|
51
|
+
value={value}
|
|
52
|
+
onChange={(e) => setValue(e.target.value)}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
43
56
|
```
|
|
44
57
|
|
|
45
|
-
##
|
|
58
|
+
## Variants
|
|
46
59
|
|
|
47
|
-
Input
|
|
60
|
+
Input supports four visual styles: `outlined` (default), `solid`, `soft`, and `plain`.
|
|
48
61
|
|
|
49
62
|
```tsx
|
|
50
63
|
<>
|
|
@@ -55,9 +68,9 @@ Input은 네 가지 변형을 지원합니다: `solid`, `soft`, `outlined`, `pla
|
|
|
55
68
|
</>
|
|
56
69
|
```
|
|
57
70
|
|
|
58
|
-
##
|
|
71
|
+
## Sizes
|
|
59
72
|
|
|
60
|
-
|
|
73
|
+
Three sizes are available: `sm`, `md` (default), and `lg`.
|
|
61
74
|
|
|
62
75
|
```tsx
|
|
63
76
|
<>
|
|
@@ -67,13 +80,11 @@ Input은 세 가지 크기를 지원합니다: `sm`, `md`, `lg`
|
|
|
67
80
|
</>
|
|
68
81
|
```
|
|
69
82
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자에게 추가 정보를 제공할 수 있습니다.
|
|
83
|
+
## Label and Helper Text
|
|
73
84
|
|
|
74
|
-
###
|
|
85
|
+
### Label
|
|
75
86
|
|
|
76
|
-
`label`
|
|
87
|
+
The `label` prop renders a form label above the input.
|
|
77
88
|
|
|
78
89
|
```tsx
|
|
79
90
|
<>
|
|
@@ -81,9 +92,9 @@ Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자
|
|
|
81
92
|
</>
|
|
82
93
|
```
|
|
83
94
|
|
|
84
|
-
###
|
|
95
|
+
### Helper Text
|
|
85
96
|
|
|
86
|
-
`helperText`
|
|
97
|
+
The `helperText` prop renders descriptive text below the input.
|
|
87
98
|
|
|
88
99
|
```tsx
|
|
89
100
|
<>
|
|
@@ -91,19 +102,19 @@ Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자
|
|
|
91
102
|
</>
|
|
92
103
|
```
|
|
93
104
|
|
|
94
|
-
##
|
|
105
|
+
## States
|
|
95
106
|
|
|
96
|
-
###
|
|
107
|
+
### Disabled
|
|
97
108
|
|
|
98
|
-
|
|
109
|
+
A disabled input cannot be focused or interacted with.
|
|
99
110
|
|
|
100
111
|
```tsx
|
|
101
112
|
<Input disabled />
|
|
102
113
|
```
|
|
103
114
|
|
|
104
|
-
###
|
|
115
|
+
### Error
|
|
105
116
|
|
|
106
|
-
`error`
|
|
117
|
+
Set `error` to visually indicate a validation failure. Combine with `helperText` to display an error message.
|
|
107
118
|
|
|
108
119
|
```tsx
|
|
109
120
|
<>
|
|
@@ -111,9 +122,9 @@ Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자
|
|
|
111
122
|
</>
|
|
112
123
|
```
|
|
113
124
|
|
|
114
|
-
###
|
|
125
|
+
### Required
|
|
115
126
|
|
|
116
|
-
`required`
|
|
127
|
+
Set `required` to mark the field as required. An asterisk is added to the label automatically.
|
|
117
128
|
|
|
118
129
|
```tsx
|
|
119
130
|
<Input
|
|
@@ -124,9 +135,9 @@ Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자
|
|
|
124
135
|
/>
|
|
125
136
|
```
|
|
126
137
|
|
|
127
|
-
##
|
|
138
|
+
## Decorators
|
|
128
139
|
|
|
129
|
-
|
|
140
|
+
Use `startDecorator` and `endDecorator` to add icons, buttons, or other elements at the start or end of the input field.
|
|
130
141
|
|
|
131
142
|
```tsx
|
|
132
143
|
<Stack spacing={3}>
|
|
@@ -166,7 +177,7 @@ width: 300
|
|
|
166
177
|
</Stack>
|
|
167
178
|
```
|
|
168
179
|
|
|
169
|
-
`endDecorator
|
|
180
|
+
When using `endDecorator` together with `enableClearable`, both elements are displayed side by side:
|
|
170
181
|
|
|
171
182
|
```tsx
|
|
172
183
|
<Input
|
|
@@ -177,9 +188,9 @@ width: 300
|
|
|
177
188
|
/>
|
|
178
189
|
```
|
|
179
190
|
|
|
180
|
-
##
|
|
191
|
+
## Clearable Input
|
|
181
192
|
|
|
182
|
-
`enableClearable`
|
|
193
|
+
Set `enableClearable` to show a clear button when the input has a value. Clicking the button clears the input content.
|
|
183
194
|
|
|
184
195
|
```tsx
|
|
185
196
|
<>
|
|
@@ -187,9 +198,16 @@ width: 300
|
|
|
187
198
|
</>
|
|
188
199
|
```
|
|
189
200
|
|
|
190
|
-
|
|
201
|
+
```tsx
|
|
202
|
+
<Input
|
|
203
|
+
enableClearable
|
|
204
|
+
placeholder="Type something and clear it"
|
|
205
|
+
/>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Password Input
|
|
191
209
|
|
|
192
|
-
`type="password"`
|
|
210
|
+
Setting `type="password"` creates a password field with an automatic visibility toggle button.
|
|
193
211
|
|
|
194
212
|
```tsx
|
|
195
213
|
<Stack spacing={3}>
|
|
@@ -204,26 +222,17 @@ width: 300
|
|
|
204
222
|
</Stack>
|
|
205
223
|
```
|
|
206
224
|
|
|
207
|
-
###
|
|
225
|
+
### Disabling the Password Toggle
|
|
208
226
|
|
|
209
|
-
|
|
227
|
+
Use `disableTogglePasswordButton` to hide the visibility toggle button on password inputs.
|
|
210
228
|
|
|
211
229
|
```tsx
|
|
212
|
-
<
|
|
213
|
-
<Typography level="body-md">Default password input with toggle button:</Typography>
|
|
214
|
-
<Input {...args} placeholder="Enter password" type="password" label="Password" />
|
|
215
|
-
|
|
216
|
-
<Typography level="body-md">Disabled password input:</Typography>
|
|
217
|
-
<Input {...args} placeholder="Enter password" type="password" label="Disabled Password" disabled />
|
|
218
|
-
|
|
219
|
-
<Typography level="body-md">Password input with toggle button disabled:</Typography>
|
|
220
|
-
<Input {...args} placeholder="Enter password" type="password" label="No Toggle" disableTogglePasswordButton />
|
|
221
|
-
</Stack>
|
|
230
|
+
<Input type="password" disableTogglePasswordButton placeholder="Password" />
|
|
222
231
|
```
|
|
223
232
|
|
|
224
|
-
###
|
|
233
|
+
### Password Input Limitations
|
|
225
234
|
|
|
226
|
-
|
|
235
|
+
Password inputs (`type="password"`) do not support custom `endDecorator` because the password toggle button occupies that slot. If you provide `endDecorator` with a password input, the component logs a warning and ignores it.
|
|
227
236
|
|
|
228
237
|
```tsx
|
|
229
238
|
<Stack spacing={3}>
|
|
@@ -235,9 +244,9 @@ width: 300
|
|
|
235
244
|
</Stack>
|
|
236
245
|
```
|
|
237
246
|
|
|
238
|
-
##
|
|
247
|
+
## Form Control
|
|
239
248
|
|
|
240
|
-
|
|
249
|
+
Combining `label`, `helperText`, and `error` produces a complete form field.
|
|
241
250
|
|
|
242
251
|
```tsx
|
|
243
252
|
<>
|
|
@@ -246,11 +255,25 @@ Input 컴포넌트는 `label`, `helperText`, `error` 속성을 조합하여 완
|
|
|
246
255
|
</>
|
|
247
256
|
```
|
|
248
257
|
|
|
249
|
-
|
|
258
|
+
```tsx
|
|
259
|
+
<Input
|
|
260
|
+
label="Email"
|
|
261
|
+
helperText="We'll never share your email"
|
|
262
|
+
required
|
|
263
|
+
/>
|
|
264
|
+
|
|
265
|
+
<Input
|
|
266
|
+
label="Email"
|
|
267
|
+
error
|
|
268
|
+
helperText="Invalid email address"
|
|
269
|
+
/>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Controlled / Uncontrolled
|
|
250
273
|
|
|
251
|
-
###
|
|
274
|
+
### Controlled
|
|
252
275
|
|
|
253
|
-
|
|
276
|
+
Use `value` and `onChange` for controlled behavior.
|
|
254
277
|
|
|
255
278
|
```tsx
|
|
256
279
|
<>
|
|
@@ -258,31 +281,194 @@ Input은 React의 제어 컴포넌트로 사용할 수 있습니다. `value`와
|
|
|
258
281
|
</>
|
|
259
282
|
```
|
|
260
283
|
|
|
261
|
-
|
|
284
|
+
```tsx
|
|
285
|
+
const [value, setValue] = useState('');
|
|
286
|
+
|
|
287
|
+
<Input
|
|
288
|
+
value={value}
|
|
289
|
+
onChange={(e) => setValue(e.target.value)}
|
|
290
|
+
placeholder="Controlled input"
|
|
291
|
+
/>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Uncontrolled
|
|
295
|
+
|
|
296
|
+
Use `defaultValue` for uncontrolled behavior.
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
<Input defaultValue="Initial value" placeholder="Uncontrolled input" />
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Search Field
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import { Input } from '@ceed/ads';
|
|
306
|
+
import SearchIcon from '@mui/icons-material/Search';
|
|
307
|
+
|
|
308
|
+
function SearchField({ onSearch }) {
|
|
309
|
+
const [query, setQuery] = useState('');
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<Input
|
|
313
|
+
placeholder="Search..."
|
|
314
|
+
startDecorator={<SearchIcon />}
|
|
315
|
+
enableClearable
|
|
316
|
+
value={query}
|
|
317
|
+
onChange={(e) => {
|
|
318
|
+
setQuery(e.target.value);
|
|
319
|
+
onSearch(e.target.value);
|
|
320
|
+
}}
|
|
321
|
+
/>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Login Form
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { Input, Button, Stack } from '@ceed/ads';
|
|
330
|
+
|
|
331
|
+
function LoginForm({ onSubmit }) {
|
|
332
|
+
return (
|
|
333
|
+
<form onSubmit={onSubmit}>
|
|
334
|
+
<Stack spacing={2}>
|
|
335
|
+
<Input
|
|
336
|
+
label="Email"
|
|
337
|
+
type="email"
|
|
338
|
+
required
|
|
339
|
+
placeholder="Enter your email"
|
|
340
|
+
/>
|
|
341
|
+
<Input
|
|
342
|
+
label="Password"
|
|
343
|
+
type="password"
|
|
344
|
+
required
|
|
345
|
+
placeholder="Enter your password"
|
|
346
|
+
/>
|
|
347
|
+
<Button type="submit">Sign In</Button>
|
|
348
|
+
</Stack>
|
|
349
|
+
</form>
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Form with Validation
|
|
262
355
|
|
|
263
|
-
|
|
356
|
+
```tsx
|
|
357
|
+
import { useState } from 'react';
|
|
358
|
+
import { Input, Button, Stack } from '@ceed/ads';
|
|
359
|
+
|
|
360
|
+
function ValidatedForm() {
|
|
361
|
+
const [email, setEmail] = useState('');
|
|
362
|
+
const [submitted, setSubmitted] = useState(false);
|
|
363
|
+
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<form onSubmit={(e) => { e.preventDefault(); setSubmitted(true); }}>
|
|
367
|
+
<Stack spacing={2}>
|
|
368
|
+
<Input
|
|
369
|
+
label="Email"
|
|
370
|
+
required
|
|
371
|
+
value={email}
|
|
372
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
373
|
+
error={submitted && !isValid}
|
|
374
|
+
helperText={submitted && !isValid ? 'Please enter a valid email' : undefined}
|
|
375
|
+
placeholder="user@example.com"
|
|
376
|
+
/>
|
|
377
|
+
<Button type="submit">Submit</Button>
|
|
378
|
+
</Stack>
|
|
379
|
+
</form>
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
```
|
|
264
383
|
|
|
265
|
-
##
|
|
384
|
+
## Props and Customization
|
|
385
|
+
|
|
386
|
+
### Key Props
|
|
387
|
+
|
|
388
|
+
| Prop | Type | Default | Description |
|
|
389
|
+
| ----------------------------- | -------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------- |
|
|
390
|
+
| `label` | `ReactNode` | - | Label text displayed above the input |
|
|
391
|
+
| `helperText` | `ReactNode` | - | Helper text displayed below the input |
|
|
392
|
+
| `error` | `boolean` | `false` | Applies danger color to indicate validation error |
|
|
393
|
+
| `enableClearable` | `boolean` | `false` | Shows a clear button when the input has a value |
|
|
394
|
+
| `disableTogglePasswordButton` | `boolean` | `false` | Hides the password visibility toggle (only applies when `type="password"`) |
|
|
395
|
+
| `value` | `string` | - | Input value for controlled mode |
|
|
396
|
+
| `defaultValue` | `string` | - | Initial value for uncontrolled mode |
|
|
397
|
+
| `onChange` | `(event: ChangeEvent<HTMLInputElement>) => void` | - | Callback when the input value changes |
|
|
398
|
+
| `placeholder` | `string` | - | Placeholder text when the input is empty |
|
|
399
|
+
| `type` | `string` | `'text'` | HTML input type (`text`, `password`, `email`, `number`, etc.) |
|
|
400
|
+
| `disabled` | `boolean` | `false` | Disables the input |
|
|
401
|
+
| `readOnly` | `boolean` | `false` | Makes the input read-only (focusable but not editable) |
|
|
402
|
+
| `required` | `boolean` | `false` | Marks the field as required (adds asterisk to label) |
|
|
403
|
+
| `name` | `string` | - | HTML name attribute for form submission |
|
|
404
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input size |
|
|
405
|
+
| `variant` | `'outlined' \| 'solid' \| 'soft' \| 'plain'` | `'outlined'` | Visual style variant |
|
|
406
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color scheme |
|
|
407
|
+
| `startDecorator` | `ReactNode` | - | Content rendered at the start of the input |
|
|
408
|
+
| `endDecorator` | `ReactNode` | - | Content rendered at the end of the input (not supported with `type="password"`) |
|
|
409
|
+
| `sx` | `SxProps` | - | Custom styles using the MUI system |
|
|
410
|
+
|
|
411
|
+
> **Note**: Input also accepts all Joy UI Input props and Framer Motion props.
|
|
412
|
+
|
|
413
|
+
## Best Practices
|
|
414
|
+
|
|
415
|
+
1. **Use built-in `label` and `helperText`** instead of wrapping with FormControl manually.
|
|
266
416
|
|
|
267
|
-
|
|
417
|
+
```tsx
|
|
418
|
+
// ✅ Good
|
|
419
|
+
<Input label="Email" helperText="Enter your work email" />
|
|
420
|
+
|
|
421
|
+
// ❌ Bad
|
|
422
|
+
<FormControl>
|
|
423
|
+
<FormLabel>Email</FormLabel>
|
|
424
|
+
<Input />
|
|
425
|
+
<FormHelperText>Enter your work email</FormHelperText>
|
|
426
|
+
</FormControl>
|
|
427
|
+
```
|
|
268
428
|
|
|
269
|
-
|
|
270
|
-
- 키보드 탐색이 가능합니다.
|
|
271
|
-
- 오류 상태는 시각적으로 명확하게 표시됩니다.
|
|
429
|
+
2. **Choose the right input type** for the data being captured.
|
|
272
430
|
|
|
273
|
-
|
|
431
|
+
```tsx
|
|
432
|
+
// ✅ Good: Appropriate types
|
|
433
|
+
<Input type="email" label="Email" />
|
|
434
|
+
<Input type="password" label="Password" />
|
|
435
|
+
<Input type="tel" label="Phone" />
|
|
274
436
|
|
|
275
|
-
|
|
437
|
+
// ❌ Bad: Generic text for everything
|
|
438
|
+
<Input type="text" label="Email" />
|
|
439
|
+
```
|
|
276
440
|
|
|
277
|
-
|
|
278
|
-
- 이는 ARIA 명세에 따라 `password` 입력이 특별한 role을 갖지 않고 기본적으로 `textbox` role을 사용하기 때문입니다.
|
|
441
|
+
3. **Always provide labels** for accessibility. If a visible label is not appropriate, use `aria-label`.
|
|
279
442
|
|
|
280
443
|
```tsx
|
|
281
|
-
//
|
|
282
|
-
|
|
444
|
+
// ✅ Good: Visible label
|
|
445
|
+
<Input label="Search" />
|
|
446
|
+
|
|
447
|
+
// ✅ Good: Hidden label for icon-only inputs
|
|
448
|
+
<Input aria-label="Search" startDecorator={<SearchIcon />} />
|
|
449
|
+
|
|
450
|
+
// ❌ Bad: No label at all
|
|
451
|
+
<Input placeholder="Search..." />
|
|
283
452
|
```
|
|
284
453
|
|
|
285
|
-
|
|
454
|
+
4. **Use `enableClearable` for search and filter inputs** where users frequently need to clear and re-enter values.
|
|
455
|
+
|
|
456
|
+
5. **Do not use `endDecorator` with password inputs.** The password toggle button occupies the end slot. Use `startDecorator` instead for additional icons.
|
|
457
|
+
|
|
458
|
+
## Accessibility
|
|
459
|
+
|
|
460
|
+
- **Label association**: The `label` prop automatically connects the label to the input via `htmlFor`/`id` pairing.
|
|
461
|
+
- **Keyboard navigation**: Standard keyboard support — Tab to focus, type to input, Escape to blur (when applicable).
|
|
462
|
+
- **Error announcement**: When `error` is set, `aria-invalid` is applied. Pair with `helperText` so assistive technology announces the error.
|
|
463
|
+
- **Required state**: The `required` prop adds `aria-required` and a visible asterisk to the label.
|
|
464
|
+
- **Password toggle**: The visibility toggle button is keyboard-accessible and includes an appropriate `aria-label`.
|
|
465
|
+
|
|
466
|
+
## Testing Notes
|
|
467
|
+
|
|
468
|
+
When using Testing Library, always query password inputs by `textbox` role:
|
|
469
|
+
|
|
470
|
+
```tsx
|
|
471
|
+
const passwordInput = screen.getByRole('textbox', { name: /password/i });
|
|
472
|
+
```
|
|
286
473
|
|
|
287
|
-
|
|
288
|
-
- [Testing Library: How to find password inputs](https://github.com/testing-library/dom-testing-library/issues/567)
|
|
474
|
+
This is because the ARIA specification does not define a `password` role — password inputs use the default `textbox` role.
|
|
@@ -248,9 +248,7 @@ A controlled example with an external reset button to clear the selected value.
|
|
|
248
248
|
</div>
|
|
249
249
|
```
|
|
250
250
|
|
|
251
|
-
##
|
|
252
|
-
|
|
253
|
-
### Billing Period Selection
|
|
251
|
+
## Billing Period Selection
|
|
254
252
|
|
|
255
253
|
```tsx
|
|
256
254
|
function BillingPeriodSelector() {
|
|
@@ -268,7 +266,7 @@ function BillingPeriodSelector() {
|
|
|
268
266
|
}
|
|
269
267
|
```
|
|
270
268
|
|
|
271
|
-
|
|
269
|
+
## Report Month Filter with Display Format
|
|
272
270
|
|
|
273
271
|
```tsx
|
|
274
272
|
function ReportFilter() {
|
|
@@ -286,7 +284,7 @@ function ReportFilter() {
|
|
|
286
284
|
}
|
|
287
285
|
```
|
|
288
286
|
|
|
289
|
-
|
|
287
|
+
## Credit Card Expiry
|
|
290
288
|
|
|
291
289
|
```tsx
|
|
292
290
|
function CreditCardExpiry() {
|
|
@@ -359,6 +357,31 @@ const handleChange = (e) => {
|
|
|
359
357
|
};
|
|
360
358
|
```
|
|
361
359
|
|
|
360
|
+
## Props and Customization
|
|
361
|
+
|
|
362
|
+
### Key Props
|
|
363
|
+
|
|
364
|
+
| Prop | Type | Default | Description |
|
|
365
|
+
| --------------- | ------------------------------------------------------- | -------------- | --------------------------------------------------- |
|
|
366
|
+
| `value` | `string` | - | Selected month string in `format` (controlled mode) |
|
|
367
|
+
| `defaultValue` | `string` | `''` | Initial month string (uncontrolled mode) |
|
|
368
|
+
| `onChange` | `(event: { target: { name?, value: string } }) => void` | - | Callback when the month changes |
|
|
369
|
+
| `format` | `string` | `'YYYY/MM/DD'` | Format of the `value` and `onChange` value |
|
|
370
|
+
| `displayFormat` | `string` | `'YYYY/MM'` | Format displayed in the input field |
|
|
371
|
+
| `label` | `ReactNode` | - | Form label displayed above the input |
|
|
372
|
+
| `helperText` | `ReactNode` | - | Helper text displayed below the input |
|
|
373
|
+
| `error` | `boolean` | `false` | Applies danger color to indicate validation error |
|
|
374
|
+
| `required` | `boolean` | `false` | Marks the field as required |
|
|
375
|
+
| `disabled` | `boolean` | `false` | Disables the entire component |
|
|
376
|
+
| `name` | `string` | - | HTML name attribute for form submission |
|
|
377
|
+
| `minDate` | `string` | - | Minimum selectable month (in `format`) |
|
|
378
|
+
| `maxDate` | `string` | - | Maximum selectable month (in `format`) |
|
|
379
|
+
| `disableFuture` | `boolean` | `false` | Disables all future months |
|
|
380
|
+
| `disablePast` | `boolean` | `false` | Disables all past months |
|
|
381
|
+
| `locale` | `string` | `'default'` | Locale for month names (BCP 47 format) |
|
|
382
|
+
|
|
383
|
+
> **Note**: MonthPicker also accepts all Input props (e.g., `size`, `variant`, `color`, `sx`).
|
|
384
|
+
|
|
362
385
|
## Accessibility
|
|
363
386
|
|
|
364
387
|
- The input has `role="textbox"` and the calendar toggle button has `aria-label="Toggle Calendar"` for screen reader identification.
|
|
@@ -217,9 +217,7 @@ A controlled example with an external reset button to clear the selected range.
|
|
|
217
217
|
</div>
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
##
|
|
221
|
-
|
|
222
|
-
### Fiscal Period Report
|
|
220
|
+
## Fiscal Period Report
|
|
223
221
|
|
|
224
222
|
```tsx
|
|
225
223
|
function FiscalReportSelector() {
|
|
@@ -248,7 +246,7 @@ function FiscalReportSelector() {
|
|
|
248
246
|
}
|
|
249
247
|
```
|
|
250
248
|
|
|
251
|
-
|
|
249
|
+
## Subscription Duration with Month Count
|
|
252
250
|
|
|
253
251
|
```tsx
|
|
254
252
|
function SubscriptionForm() {
|
|
@@ -279,7 +277,7 @@ function SubscriptionForm() {
|
|
|
279
277
|
}
|
|
280
278
|
```
|
|
281
279
|
|
|
282
|
-
|
|
280
|
+
## Year-over-Year Comparison
|
|
283
281
|
|
|
284
282
|
```tsx
|
|
285
283
|
function YearOverYearComparison() {
|
|
@@ -363,6 +361,29 @@ const handleSubmit = () => {
|
|
|
363
361
|
<MonthRangePicker format="YYYY-MM" />
|
|
364
362
|
```
|
|
365
363
|
|
|
364
|
+
## Props and Customization
|
|
365
|
+
|
|
366
|
+
### Key Props
|
|
367
|
+
|
|
368
|
+
| Prop | Type | Default | Description |
|
|
369
|
+
| --------------- | ------------------------------------------------------- | ----------- | --------------------------------------------------------- |
|
|
370
|
+
| `value` | `string` | - | Selected month range string in `format` (controlled mode) |
|
|
371
|
+
| `defaultValue` | `string` | `''` | Initial month range string (uncontrolled mode) |
|
|
372
|
+
| `onChange` | `(event: { target: { name?, value: string } }) => void` | - | Callback when the month range changes |
|
|
373
|
+
| `format` | `string` | `'YYYY/MM'` | Format of the `value` and `onChange` value |
|
|
374
|
+
| `label` | `ReactNode` | - | Form label displayed above the input |
|
|
375
|
+
| `helperText` | `ReactNode` | - | Helper text displayed below the input |
|
|
376
|
+
| `error` | `boolean` | `false` | Applies danger color to indicate validation error |
|
|
377
|
+
| `required` | `boolean` | `false` | Marks the field as required |
|
|
378
|
+
| `disabled` | `boolean` | `false` | Disables the entire component |
|
|
379
|
+
| `name` | `string` | - | HTML name attribute for form submission |
|
|
380
|
+
| `minDate` | `string` | - | Minimum selectable month (in `format`) |
|
|
381
|
+
| `maxDate` | `string` | - | Maximum selectable month (in `format`) |
|
|
382
|
+
| `disableFuture` | `boolean` | `false` | Disables all future months |
|
|
383
|
+
| `disablePast` | `boolean` | `false` | Disables all past months |
|
|
384
|
+
|
|
385
|
+
> **Note**: MonthRangePicker also accepts all Input props (e.g., `size`, `variant`, `color`, `sx`).
|
|
386
|
+
|
|
366
387
|
## Accessibility
|
|
367
388
|
|
|
368
389
|
- The input has `role="textbox"` and the calendar toggle button has `aria-label="Toggle Calendar"` for screen reader identification.
|
|
@@ -194,9 +194,7 @@ When `useMinorUnit` is `true`, the component converts between display values and
|
|
|
194
194
|
<PercentageInput useMinorUnit={false} maxDecimalScale={2} value={20.12} />
|
|
195
195
|
```
|
|
196
196
|
|
|
197
|
-
##
|
|
198
|
-
|
|
199
|
-
### Discount Configuration
|
|
197
|
+
## Discount Configuration
|
|
200
198
|
|
|
201
199
|
```tsx
|
|
202
200
|
function DiscountSetting() {
|
|
@@ -215,7 +213,7 @@ function DiscountSetting() {
|
|
|
215
213
|
}
|
|
216
214
|
```
|
|
217
215
|
|
|
218
|
-
|
|
216
|
+
## Tax Rate Settings
|
|
219
217
|
|
|
220
218
|
```tsx
|
|
221
219
|
function TaxRateForm() {
|
|
@@ -240,7 +238,7 @@ function TaxRateForm() {
|
|
|
240
238
|
}
|
|
241
239
|
```
|
|
242
240
|
|
|
243
|
-
|
|
241
|
+
## Progress / Completion Tracker
|
|
244
242
|
|
|
245
243
|
```tsx
|
|
246
244
|
function CompletionTracker({ value, onChange }) {
|
|
@@ -277,6 +275,31 @@ function CompletionTracker({ value, onChange }) {
|
|
|
277
275
|
|
|
278
276
|
5. **Handle edge cases**: Consider what happens at boundary values (0%, 100%) and negative percentages if allowed.
|
|
279
277
|
|
|
278
|
+
## Props and Customization
|
|
279
|
+
|
|
280
|
+
### Key Props
|
|
281
|
+
|
|
282
|
+
| Prop | Type | Default | Description |
|
|
283
|
+
| ----------------- | -------------------------------------------------------- | ------- | ------------------------------------------------------ |
|
|
284
|
+
| `value` | `number` | - | Percentage value (controlled mode) |
|
|
285
|
+
| `defaultValue` | `number` | - | Initial percentage value (uncontrolled mode) |
|
|
286
|
+
| `onChange` | `(event: { target: { name?, value?: number } }) => void` | - | Callback when the value changes |
|
|
287
|
+
| `useMinorUnit` | `boolean` | `false` | When true, value is in basis points (e.g., 1000 = 10%) |
|
|
288
|
+
| `maxDecimalScale` | `number` | `0` | Maximum number of decimal places |
|
|
289
|
+
| `min` | `number` | - | Minimum allowed percentage value |
|
|
290
|
+
| `max` | `number` | - | Maximum allowed percentage value |
|
|
291
|
+
| `label` | `ReactNode` | - | Form label displayed above the input |
|
|
292
|
+
| `helperText` | `ReactNode` | - | Helper text displayed below the input |
|
|
293
|
+
| `error` | `boolean` | `false` | Applies danger color to indicate validation error |
|
|
294
|
+
| `required` | `boolean` | `false` | Marks the field as required |
|
|
295
|
+
| `disabled` | `boolean` | `false` | Disables the input |
|
|
296
|
+
| `name` | `string` | - | HTML name attribute for form submission |
|
|
297
|
+
| `placeholder` | `string` | - | Placeholder text when the input is empty |
|
|
298
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input size |
|
|
299
|
+
| `sx` | `SxProps` | - | Custom styles using the MUI system |
|
|
300
|
+
|
|
301
|
+
> **Note**: PercentageInput also accepts all Input props and Framer Motion props.
|
|
302
|
+
|
|
280
303
|
## Accessibility
|
|
281
304
|
|
|
282
305
|
- The input has proper labeling via the `label` prop, linked with `aria-labelledby`.
|