@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,9 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- FilterMenu is a comprehensive filtering component that supports multiple filter types within a single dropdown panel. It enables users to apply, combine, and reset various filters -- including checkboxes, radio buttons, date ranges, currency inputs, percentage inputs, and autocomplete fields -- through a consistent, organized interface.
6
-
7
- FilterMenu is ideal for data-heavy admin interfaces such as tables, lists, and dashboards where users need to narrow down results based on multiple criteria. It supports both controlled and uncontrolled state management, allowing flexible integration with different state architectures.
5
+ FilterMenu 다양한 필터 타입을 지원하는 모달 형태의 필터 컴포넌트입니다. 여러 종류의 필터를 조합하여 복잡한 필터링 UI를 쉽게 구성할 있습니다.
8
6
 
9
7
  ```tsx
10
8
  <FilterMenu {...args} defaultValues={values} onChange={newValues => {
@@ -59,11 +57,11 @@ function MyComponent() {
59
57
 
60
58
  ## Filter Types
61
59
 
62
- FilterMenu supports the following filter types. Each type is configured through the `filters` array prop.
60
+ FilterMenu 다음과 같은 필터 타입을 지원합니다:
63
61
 
64
62
  ### Checkbox Group
65
63
 
66
- Multi-select filter with checkboxes. The selected values are stored as an array.
64
+ 다중 선택이 가능한 체크박스 그룹 필터입니다.
67
65
 
68
66
  ```tsx
69
67
  {
@@ -79,7 +77,7 @@ Multi-select filter with checkboxes. The selected values are stored as an array.
79
77
 
80
78
  ### Filterable Checkbox Group
81
79
 
82
- A searchable checkbox group for long option lists. Includes a text input to filter visible options.
80
+ 검색 기능이 포함된 체크박스 그룹 필터입니다. 옵션이 많을 유용합니다.
83
81
 
84
82
  ```tsx
85
83
  {
@@ -89,6 +87,7 @@ A searchable checkbox group for long option lists. Includes a text input to filt
89
87
  options: [
90
88
  { label: 'Electronics', value: 'electronics' },
91
89
  { label: 'Clothing', value: 'clothing' },
90
+ { label: 'Food', value: 'food' },
92
91
  { label: 'Books', value: 'books' },
93
92
  ],
94
93
  placeholder: 'Search categories...',
@@ -98,7 +97,7 @@ A searchable checkbox group for long option lists. Includes a text input to filt
98
97
 
99
98
  ### Radio Group
100
99
 
101
- Single-select filter with radio buttons. The selected value is stored as a single string.
100
+ 단일 선택이 가능한 라디오 버튼 그룹 필터입니다.
102
101
 
103
102
  ```tsx
104
103
  {
@@ -115,7 +114,7 @@ Single-select filter with radio buttons. The selected value is stored as a singl
115
114
 
116
115
  ### Date Range
117
116
 
118
- A date range picker filter. The value is stored as a two-element array of date strings.
117
+ 날짜 범위를 선택할 있는 필터입니다.
119
118
 
120
119
  ```tsx
121
120
  {
@@ -130,7 +129,7 @@ A date range picker filter. The value is stored as a two-element array of date s
130
129
 
131
130
  ### Currency Input
132
131
 
133
- A single currency value input field.
132
+ 단일 통화 값을 입력할 있는 필터입니다.
134
133
 
135
134
  ```tsx
136
135
  {
@@ -144,7 +143,7 @@ A single currency value input field.
144
143
 
145
144
  ### Currency Range
146
145
 
147
- A currency range filter with min and max inputs.
146
+ 통화 범위를 입력할 있는 필터입니다.
148
147
 
149
148
  ```tsx
150
149
  {
@@ -158,7 +157,7 @@ A currency range filter with min and max inputs.
158
157
 
159
158
  ### Percentage Input
160
159
 
161
- A single percentage value input field.
160
+ 단일 퍼센트 값을 입력할 있는 필터입니다.
162
161
 
163
162
  ```tsx
164
163
  {
@@ -173,7 +172,7 @@ A single percentage value input field.
173
172
 
174
173
  ### Percentage Range
175
174
 
176
- A percentage range filter with min and max inputs.
175
+ 퍼센트 범위를 입력할 있는 필터입니다.
177
176
 
178
177
  ```tsx
179
178
  {
@@ -187,7 +186,7 @@ A percentage range filter with min and max inputs.
187
186
 
188
187
  ### Autocomplete
189
188
 
190
- A searchable single-select filter with autocomplete support.
189
+ 자동완성을 지원하는 선택 필터입니다.
191
190
 
192
191
  ```tsx
193
192
  {
@@ -203,8 +202,6 @@ A searchable single-select filter with autocomplete support.
203
202
 
204
203
  ### Controlled Mode
205
204
 
206
- In controlled mode, you manage the filter state externally using `values` (or `defaultValues` with an `onChange` handler).
207
-
208
205
  ```tsx
209
206
  <FilterMenu {...args} defaultValues={values} onChange={newValues => {
210
207
  setValues(newValues);
@@ -214,167 +211,20 @@ In controlled mode, you manage the filter state externally using `values` (or `d
214
211
 
215
212
  ### Uncontrolled Mode
216
213
 
217
- In uncontrolled mode, FilterMenu manages its own internal state. This is useful when you only need the final filter values on submission.
218
-
219
214
  ```tsx
220
215
  <FilterMenu />
221
216
  ```
222
217
 
223
- ## Common Use Cases
224
-
225
- ### Table Filters
226
-
227
- ```tsx
228
- function DataTable() {
229
- const [filters, setFilters] = useState({});
230
- const { data } = useQuery(['items', filters], () => fetchItems(filters));
231
-
232
- return (
233
- <Box>
234
- <FilterMenu
235
- filters={[
236
- {
237
- id: 'status',
238
- type: 'checkbox-group',
239
- label: 'Status',
240
- options: [
241
- { label: 'Active', value: 'active' },
242
- { label: 'Pending', value: 'pending' },
243
- { label: 'Archived', value: 'archived' },
244
- ],
245
- },
246
- {
247
- id: 'dateRange',
248
- type: 'date-range',
249
- label: 'Created Date',
250
- displayFormat: 'MM/DD/YYYY',
251
- },
252
- {
253
- id: 'amount',
254
- type: 'currency-range',
255
- label: 'Amount',
256
- currency: 'USD',
257
- },
258
- ]}
259
- defaultValues={filters}
260
- onChange={setFilters}
261
- useReset
262
- />
263
- <Table data={data} />
264
- </Box>
265
- );
266
- }
267
- ```
268
-
269
- ### Dashboard Filters
270
-
271
- ```tsx
272
- function DashboardFilters({ onFilterChange }) {
273
- return (
274
- <FilterMenu
275
- filters={[
276
- {
277
- id: 'region',
278
- type: 'filterable-checkbox-group',
279
- label: 'Region',
280
- options: regions.map((r) => ({ label: r.name, value: r.id })),
281
- placeholder: 'Search regions...',
282
- maxHeight: 200,
283
- },
284
- {
285
- id: 'period',
286
- type: 'radio-group',
287
- label: 'Time Period',
288
- options: [
289
- { label: 'Last 7 days', value: '7d' },
290
- { label: 'Last 30 days', value: '30d' },
291
- { label: 'Last 90 days', value: '90d' },
292
- { label: 'Custom', value: 'custom' },
293
- ],
294
- },
295
- ]}
296
- onChange={onFilterChange}
297
- useReset
298
- />
299
- );
300
- }
301
- ```
302
-
303
- ### Invoice Filters
304
-
305
- ```tsx
306
- function InvoiceFilters({ onFilterChange }) {
307
- return (
308
- <FilterMenu
309
- filters={[
310
- {
311
- id: 'status',
312
- type: 'checkbox-group',
313
- label: 'Invoice Status',
314
- options: [
315
- { label: 'Paid', value: 'paid' },
316
- { label: 'Pending', value: 'pending' },
317
- { label: 'Overdue', value: 'overdue' },
318
- ],
319
- },
320
- {
321
- id: 'amount',
322
- type: 'currency-range',
323
- label: 'Amount Range',
324
- currency: 'USD',
325
- useMinorUnit: true,
326
- },
327
- {
328
- id: 'date',
329
- type: 'date-range',
330
- label: 'Invoice Date',
331
- displayFormat: 'MM/DD/YYYY',
332
- },
333
- ]}
334
- onChange={onFilterChange}
335
- useReset
336
- />
337
- );
338
- }
339
- ```
340
-
341
218
  ## Best Practices
342
219
 
343
- 1. **Use unique filter IDs**: Each filter's `id` must be unique since it serves as the key for state management.
344
-
345
- ```tsx
346
- // ✅ Good: Unique IDs
347
- filters={[
348
- { id: 'status', type: 'checkbox-group', ... },
349
- { id: 'priority', type: 'radio-group', ... },
350
- ]}
351
-
352
- // ❌ Bad: Duplicate IDs cause state conflicts
353
- filters={[
354
- { id: 'filter1', type: 'checkbox-group', ... },
355
- { id: 'filter1', type: 'radio-group', ... },
356
- ]}
357
- ```
358
-
359
- 2. **Choose the right reset strategy**: Use `useReset` when the FilterMenu contains multiple filters that users may want to clear all at once. Use `useClear` for single-filter scenarios.
360
-
361
- 3. **Provide descriptive labels**: Each filter should have a clear `label` that tells users what they are filtering. Avoid generic names like "Filter 1".
362
-
363
- ```tsx
364
- // ✅ Good: Descriptive labels
365
- { id: 'invoiceStatus', type: 'checkbox-group', label: 'Invoice Status', ... }
366
-
367
- // ❌ Bad: Vague labels
368
- { id: 'filter1', type: 'checkbox-group', label: 'Options', ... }
369
- ```
220
+ 1. **필터 ID 관리**: 필터의 `id`는 고유해야 하며, 상태 관리의 키로 사용됩니다.
370
221
 
371
- 4. **Use filterable checkbox groups for long lists**: When an option list exceeds 8-10 items, switch from `checkbox-group` to `filterable-checkbox-group` so users can search rather than scroll.
222
+ 2. **타입 안전성**: TypeScript를 사용할 FilterItem 타입을 활용하여 타입 안전성을 보장하세요.
372
223
 
373
- 5. **Prefer controlled mode for complex state**: When filter values need to be synced with URL parameters, API requests, or other UI elements, use the controlled pattern with `values` and `onChange`.
224
+ 3. **Reset vs Clear**:
225
+ - `useReset`: 여러 필터가 있을 때 모든 필터를 초기화
226
+ - `useClear`: 단일 필터만 있을 때 해당 필터를 초기화
374
227
 
375
- ## Accessibility
228
+ 4. **상태 관리**: 제어 모드(`values` prop 사용) 또는 비제어 모드(`defaultValues` prop 사용) 중 하나를 선택하여 사용하세요.
376
229
 
377
- - Each filter section is labeled with its `label` prop, providing clear context for screen readers.
378
- - Checkbox and radio groups follow standard form control patterns with proper labeling.
379
- - The reset button is keyboard-accessible and clearly labeled, allowing users to quickly clear all filters.
380
- - Use the `placeholder` prop on filterable checkbox groups and autocomplete filters to provide instructional text for assistive technology users.
230
+ 5. **접근성**: 필터에는 적절한 `label`을 제공하여 접근성을 보장하세요.
@@ -2,14 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- FilterableCheckboxGroup is a multi-select component that combines a search input with a scrollable list of checkboxes. It is designed for scenarios where users need to select multiple items from a potentially large dataset. The built-in search filter narrows down visible options in real time, and virtual scrolling ensures smooth performance even with hundreds of items.
6
-
7
- Key capabilities include a "Select all" toggle for bulk selection, automatic sorting (selected items first, then alphabetical), customizable list height, and built-in form integration via `label`, `helperText`, and `required` props. The component accepts options as either simple strings or `{ value, label }` objects.
8
-
9
- > **Form 구성 시 내장 prop 사용을 권장합니다**
10
- >
11
- > 이 컴포넌트는 `label`, `helperText` 등의 Form 요소를 자체적으로 지원합니다.
12
- > Form을 구성할 때 Typography로 별도의 label이나 helperText를 만드는 대신, 컴포넌트의 내장 prop을 사용하세요.
5
+ FilterableCheckboxGroup 컴포넌트는 대량의 옵션 중에서 여러 항목을 선택할 있는 검색 가능한 체크박스 그룹입니다. 검색 필터링과 가상 스크롤링을 통해 많은 수의 옵션을 효율적으로 처리할 있으며, "Select all" 기능으로 일괄 선택이 가능합니다. 필터링, 다중 선택 폼, 설정 화면 등에서 유용하게 사용됩니다.
13
6
 
14
7
  ```tsx
15
8
  <FilterableCheckboxGroup
@@ -57,9 +50,11 @@ function MyComponent() {
57
50
  }
58
51
  ```
59
52
 
60
- ## Sizes
53
+ ## Examples
54
+
55
+ ### Sizes
61
56
 
62
- Three sizes are available: `sm`, `md`, and `lg`. The size affects the search input, checkboxes, and overall spacing.
57
+ 다양한 크기의 FilterableCheckboxGroup을 사용할 있습니다.
63
58
 
64
59
  ```tsx
65
60
  <Stack spacing={3}>
@@ -69,11 +64,9 @@ Three sizes are available: `sm`, `md`, and `lg`. The size affects the search inp
69
64
  </Stack>
70
65
  ```
71
66
 
72
- ## Label and Helper Text
73
-
74
67
  ### With Label
75
68
 
76
- Use the `label` prop to describe the purpose of the checkbox group.
69
+ 라벨을 추가할 있습니다.
77
70
 
78
71
  ```tsx
79
72
  <FilterableCheckboxGroup
@@ -85,7 +78,7 @@ Use the `label` prop to describe the purpose of the checkbox group.
85
78
 
86
79
  ### With Helper Text
87
80
 
88
- Add a `helperText` prop to provide additional guidance below the component.
81
+ 도움말 텍스트를 추가할 있습니다.
89
82
 
90
83
  ```tsx
91
84
  <FilterableCheckboxGroup
@@ -98,7 +91,7 @@ Add a `helperText` prop to provide additional guidance below the component.
98
91
 
99
92
  ### Required Field
100
93
 
101
- Set `required` to append a required indicator to the label.
94
+ 필수 입력 필드로 표시할 있습니다.
102
95
 
103
96
  ```tsx
104
97
  <FilterableCheckboxGroup
@@ -110,9 +103,9 @@ Set `required` to append a required indicator to the label.
110
103
  />
111
104
  ```
112
105
 
113
- ## Custom Max Height
106
+ ### Custom Max Height
114
107
 
115
- Control the visible height of the options list with the `maxHeight` prop (default: 300px). A smaller height is useful when screen space is limited.
108
+ 목록의 최대 높이를 커스터마이징할 있습니다.
116
109
 
117
110
  ```tsx
118
111
  <Stack spacing={3}>
@@ -121,9 +114,9 @@ Control the visible height of the options list with the `maxHeight` prop (defaul
121
114
  </Stack>
122
115
  ```
123
116
 
124
- ## Long List with Virtual Scrolling
117
+ ### Long List
125
118
 
126
- When the options list is large, the component uses virtual scrolling to render only the visible items. This keeps the UI performant regardless of the total number of options.
119
+ 많은 수의 옵션을 가상 스크롤링으로 효율적으로 표시합니다.
127
120
 
128
121
  ```tsx
129
122
  <FilterableCheckboxGroup
@@ -136,9 +129,9 @@ When the options list is large, the component uses virtual scrolling to render o
136
129
  />
137
130
  ```
138
131
 
139
- ## Empty State
132
+ ### No Options
140
133
 
141
- When no options are provided, the component displays an empty state. This is useful for dynamically loaded option lists that may start empty.
134
+ 옵션이 없을 때의 상태입니다.
142
135
 
143
136
  ```tsx
144
137
  <FilterableCheckboxGroup
@@ -148,9 +141,9 @@ When no options are provided, the component displays an empty state. This is use
148
141
  />
149
142
  ```
150
143
 
151
- ## Controlled Mode
144
+ ### Controlled
152
145
 
153
- Pass `value` and `onChange` to manage the selection state externally. This is the recommended approach when the component is part of a form or when the selected values need to be used by other parts of the UI.
146
+ 외부에서 값을 제어하는 예제입니다.
154
147
 
155
148
  ```tsx
156
149
  <Stack spacing={2}>
@@ -162,9 +155,9 @@ Pass `value` and `onChange` to manage the selection state externally. This is th
162
155
  </Stack>
163
156
  ```
164
157
 
165
- ## Sorting Behavior
158
+ ### Sorting
166
159
 
167
- The component automatically sorts options on initial render: selected items appear first, followed by unselected items in alphabetical order. When new options are added dynamically, they are inserted in the correct sorted position.
160
+ 정렬 동작을 확인할 있는 예제입니다. 초기 렌더링 선택된 항목이 먼저 표시되고, 다음 알파벳 순으로 정렬됩니다.
168
161
 
169
162
  ```tsx
170
163
  <Stack spacing={2}>
@@ -198,13 +191,13 @@ The component automatically sorts options on initial render: selected items appe
198
191
  </Stack>
199
192
  ```
200
193
 
201
- ## Disabled State
194
+ ### Disabled
202
195
 
203
- The component supports both full and partial disabling.
196
+ 컴포넌트 전체 또는 특정 옵션을 비활성화할 있습니다.
204
197
 
205
- - **Full disable**: Set `disabled` on the component to disable the search input, "Select all" toggle, and all checkboxes.
206
- - **Partial disable**: Set `disabled: true` on individual option objects to disable specific items while keeping the rest interactive.
207
- - **"Select all" behavior**: Disabled options are excluded from the "Select all" toggle. Their selected state is preserved regardless of bulk actions.
198
+ - **컴포넌트 전체 비활성화**: `disabled` prop을 사용하여 검색 input, "Select all", 모든 옵션을 비활성화합니다.
199
+ - **특정 옵션 비활성화**: 옵션 객체의 `disabled` 속성을 사용하여 개별 옵션을 비활성화합니다.
200
+ - **"Select all" 동작**: 비활성화된 옵션은 "Select all" 영향을 받지 않으며, 선택 상태가 유지됩니다.
208
201
 
209
202
  ```tsx
210
203
  <Stack spacing={3}>
@@ -223,96 +216,3 @@ The component supports both full and partial disabling.
223
216
  </Stack>
224
217
  </Stack>
225
218
  ```
226
-
227
- ## Common Use Cases
228
-
229
- ### Filter Panel
230
-
231
- Use FilterableCheckboxGroup in a sidebar or panel to let users filter a data table or list by multiple criteria.
232
-
233
- ```tsx
234
- import { FilterableCheckboxGroup } from '@ceed/ads';
235
-
236
- function FilterPanel({ categories, onFilterChange }) {
237
- const [selected, setSelected] = useState<string[]>([]);
238
-
239
- const handleChange = (values: string[]) => {
240
- setSelected(values);
241
- onFilterChange(values);
242
- };
243
-
244
- return (
245
- <FilterableCheckboxGroup
246
- label="Categories"
247
- placeholder="Search categories..."
248
- options={categories}
249
- value={selected}
250
- onChange={handleChange}
251
- maxHeight={200}
252
- />
253
- );
254
- }
255
- ```
256
-
257
- ### User Role Assignment
258
-
259
- Assign multiple roles to a user from a searchable list.
260
-
261
- ```tsx
262
- <FilterableCheckboxGroup
263
- label="Assign Roles"
264
- placeholder="Search roles..."
265
- helperText="Select all roles that apply to this user"
266
- options={[
267
- { value: 'admin', label: 'Administrator' },
268
- { value: 'editor', label: 'Editor' },
269
- { value: 'viewer', label: 'Viewer' },
270
- { value: 'moderator', label: 'Moderator' },
271
- { value: 'billing', label: 'Billing Manager' },
272
- ]}
273
- required
274
- value={selectedRoles}
275
- onChange={setSelectedRoles}
276
- />
277
- ```
278
-
279
- ### Region / Country Selection
280
-
281
- When dealing with a large set of options like countries, the search filter and virtual scrolling work together for fast selection.
282
-
283
- ```tsx
284
- <FilterableCheckboxGroup
285
- label="Service Regions"
286
- placeholder="Search countries..."
287
- options={allCountries.map((c) => ({ value: c.code, label: c.name }))}
288
- value={selectedCountries}
289
- onChange={setSelectedCountries}
290
- />
291
- ```
292
-
293
- ## Best Practices
294
-
295
- 1. **Provide a meaningful placeholder.** The search input placeholder should hint at the type of content being filtered (e.g., "Search countries..." instead of a generic "Search...").
296
-
297
- ```tsx
298
- // ✅ Specific and helpful
299
- <FilterableCheckboxGroup placeholder="Search countries..." />
300
-
301
- // ❌ Too generic
302
- <FilterableCheckboxGroup placeholder="Type here..." />
303
- ```
304
-
305
- 2. **Use `maxHeight` to fit the layout.** In tight spaces like sidebars or modals, set a smaller `maxHeight` to prevent the component from dominating the layout.
306
-
307
- 3. **Prefer controlled mode for form integration.** Always pass `value` and `onChange` when the selected values participate in form submission or affect other UI state.
308
-
309
- 4. **Leverage individual `disabled` for permissions.** When some options should be visible but not selectable (e.g., due to user permissions), disable them individually rather than hiding them. This communicates availability without surprising users.
310
-
311
- 5. **Keep option labels concise.** Long labels will be truncated with an ellipsis. If detailed descriptions are needed, consider using a tooltip or a separate detail view.
312
-
313
- ## Accessibility
314
-
315
- - The search input is labeled by the component's `label` prop, ensuring screen readers announce its purpose.
316
- - Each checkbox option uses a native `<input type="checkbox">` with an associated `<label>`, enabling click-on-label and proper screen reader announcements.
317
- - The "Select all" toggle clearly communicates its tri-state behavior (all, none, indeterminate) to assistive technologies.
318
- - Keyboard navigation is fully supported: Tab to move between the search input and the checkbox list, Space to toggle individual checkboxes, and standard arrow keys to navigate within the list.