@bento/checkbox 0.1.2 → 0.1.3

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 (2) hide show
  1. package/README.md +284 -0
  2. package/package.json +7 -6
package/README.md ADDED
@@ -0,0 +1,284 @@
1
+ # Checkbox
2
+
3
+ The `@bento/checkbox` package provides accessible and customizable checkbox inputs. It exports the **CheckboxGroup** and **Checkbox** primitives, enabling you to build individual or groups of checkboxes with consistent keyboard navigation, focus management, and ARIA support. React Aria is used to ensure that the checkboxes are accessible to all users.
4
+
5
+ The `CheckboxGroup` allows a user to select multiple items from a list of `Checkbox` components.
6
+
7
+ The `Checkbox` is a single checkbox option that can be selected by the user.
8
+
9
+ # Installation
10
+
11
+ ```bash
12
+ npm install --save @bento/checkbox
13
+ ```
14
+
15
+ ## Props
16
+
17
+ The following properties are available to be used on the `CheckboxGroup` and `Checkbox` primitives:
18
+
19
+ ### Checkbox
20
+
21
+ | Prop | Type | Required | Description |
22
+ |------|------|----------|------------|
23
+ | `value` | `string` | No | The value of the checkbox, used when submitting an HTML form. |
24
+ | `name` | `string` | No | The name of the checkbox. |
25
+ | `inputRef` | `Ref<HTMLInputElement>` | No | A ref for the HTML input element. |
26
+ | `children` | `ReactNode` | No | The label for the checkbox. Accepts any renderable node. |
27
+ | `isRequired` | `boolean` | No | Whether the checkbox is required or not. |
28
+ | `isReadOnly` | `boolean` | No | Whether the input can be selected but not changed by the user. |
29
+ | `isDisabled` | `boolean` | No | Whether the checkbox is disabled or not. Shows that a selection exists,
30
+ but is not available in that circumstance. |
31
+ | `autoFocus` | `boolean` | No | Whether the element should receive focus on render. |
32
+ | `isIndeterminate` | `boolean` | No | Whether the checkbox is in an indeterminate state. |
33
+ | `isSelected` | `boolean` | No | Whether the checkbox is in a selected state. |
34
+ | `label` | `ReactNode` | No | The label for the control. |
35
+ | `slot` | `string` | No | A named part of a component that can be customized. This is implemented by the consuming component.
36
+ The exposed slot names of a component are available in the components documentation. |
37
+ | `inputProps` | `DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>` | No | Props to pass to the underlying input element. |
38
+ | `labelProps` | `DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>` | No | Props to pass to the label element. |
39
+ | `slots` | `Record<string, object \| Function>` | No | An object that contains the customizations for the slots.
40
+ The main way you interact with the slot system as a consumer. |
41
+
42
+ ### CheckboxGroup
43
+
44
+ | Prop | Type | Required | Description |
45
+ |------|------|----------|------------|
46
+ | `value` | `string[]` | No | The current value of the checkbox group (controlled). |
47
+ | `defaultValue` | `string[]` | No | The default value of the checkbox group (uncontrolled). |
48
+ | `isDisabled` | `boolean` | No | Whether the input is disabled. |
49
+ | `isReadOnly` | `boolean` | No | Whether the input can be selected but not changed by the user. |
50
+ | `isRequired` | `boolean` | No | Whether user input is required on the input before form submission. |
51
+ | `isInvalid` | `boolean` | No | Whether the input value is invalid. |
52
+ | `name` | `string` | No | The name of the input element, used when submitting an HTML form. |
53
+ | `form` | `string` | No | The <form> element to associate the input with.
54
+ The value of this attribute must be the id of a <form> in the same document. |
55
+ | `description` | `string` | No | Description for the checkbox group. |
56
+ | `children` | `ReactNode` | No | Checkbox children. |
57
+ | `errorMessage` | `ReactNode \| ((val: ValidationResult) => ReactNode)` | No | Error message for the checkbox group. |
58
+ | `slot` | `string` | No | A named part of a component that can be customized. This is implemented by the consuming component.
59
+ The exposed slot names of a component are available in the components documentation. |
60
+ | `labelProps` | `DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>` | No | Props to pass to the label element. |
61
+ | `descriptionProps` | `DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>` | No | Props to pass to the description element. |
62
+ | `errorMessageProps` | `DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>` | No | Props to pass to the error message element. |
63
+ | `contentProps` | `DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>` | No | The props passed to the content element. |
64
+ | `slots` | `Record<string, object \| Function>` | No | An object that contains the customizations for the slots.
65
+ The main way you interact with the slot system as a consumer. |
66
+
67
+ ## Data Attributes, Slot Map and Props
68
+
69
+ ### Data Attributes
70
+
71
+ The following data attributes can be used to style and customize the `CheckboxGroup` and `Checkbox` primitives.
72
+
73
+ #### `CheckboxGroup` Data Attributes
74
+
75
+ | Attribute | Description |
76
+ | --------------- | ------------------------------- |
77
+ | `data-disabled` | Indicates the checkbox group is disabled |
78
+ | `data-read-only` | Indicates the checkbox group is readonly |
79
+ | `data-required` | Indicates the checkbox group is required |
80
+ | `data-invalid` | Indicates the checkbox group is invalid |
81
+
82
+ #### `Checkbox` Data Attributes
83
+
84
+ | Attribute | Description |
85
+ | --------------- | ------------------------------- |
86
+ | `data-disabled` | Indicates the checkbox is disabled |
87
+ | `data-read-only` | Indicates the checkbox is readonly |
88
+ | `data-required` | Indicates the checkbox is required |
89
+ | `data-invalid` | Indicates the checkbox is invalid |
90
+ | `data-indeterminate` | Indicates the checkbox is in an indeterminate state |
91
+ | `data-pressed` | Indicates the checkbox is being pressed |
92
+ | `data-hovered` | Indicates the checkbox is hovered |
93
+ | `data-focused` | Indicates the checkbox has focus |
94
+ | `data-focus-visible` | Indicates focus should be visible |
95
+ | `data-selected` | Indicates the checkbox is selected |
96
+
97
+ ### Slot Map
98
+
99
+ The `CheckboxGroup` and `Checkbox` primitives are built off of the `Control` and `ControlGroup` primitives, which provide a consisten set of slot values, as shown below.
100
+
101
+ #### `CheckboxGroup` Slot Map
102
+
103
+ | Slot Name | Description |
104
+ | ------------------- | ---------------------------- |
105
+ | `group.label` | Label for checkbox group |
106
+ | `group.description` | Description for checkbox group|
107
+ | `group.error` | Error message for checkbox group|
108
+
109
+ #### `Checkbox` Slot Map
110
+
111
+ | Slot Name | Description |
112
+ | --------------- | -------------- |
113
+ | `control.icon-checked` | Icon for checked checkbox |
114
+ | `control.icon-unchecked` | Icon for unchecked checkbox |
115
+ | `control.icon-indeterminate` | Icon for indeterminate checkbox |
116
+ | `control.label` | Text for checkbox |
117
+
118
+ ## Examples
119
+
120
+ ### Default Checkbox - Uncontrolled
121
+
122
+ The `Checkbox` primitive is uncontrolled by default, meaning it manages its own state internally. You can also use it in a controlled manner by providing the `checked` and `onChange` props.
123
+
124
+ ```tsx
125
+ /* v8 ignore next */
126
+ import React from 'react';
127
+ import { Checkbox } from '@bento/checkbox';
128
+
129
+ export function CheckboxExample(args: React.ComponentProps<typeof Checkbox>) {
130
+ return (
131
+ <Checkbox name="checkbox-example" value="checkbox-value" {...args}>
132
+ Checkbox Label
133
+ </Checkbox>
134
+ );
135
+ }
136
+ ```
137
+
138
+ ### Controlled Checkbox
139
+
140
+ The `Checkbox` can also be used in a controlled manner, where you manage its state externally with the `checked` and `onChange` props.
141
+
142
+ ```tsx
143
+ /* v8 ignore next */
144
+ import React, { useState } from 'react';
145
+ import { Checkbox } from '@bento/checkbox';
146
+
147
+ export function CheckboxControlledExample() {
148
+ const [checked, setChecked] = useState(false);
149
+
150
+ return (
151
+ <Checkbox
152
+ name="checkbox-controlled-example"
153
+ value="checkbox-controlled-value"
154
+ isSelected={checked}
155
+ onChange={setChecked}
156
+ >
157
+ Controlled Checkbox
158
+ </Checkbox>
159
+ );
160
+ }
161
+ ```
162
+
163
+ ### Checkbox Group
164
+
165
+ The `CheckboxGroup` allows a user to select multiple items from a list of `Checkbox` components.
166
+
167
+ ```tsx
168
+ /* v8 ignore next */
169
+ import React from 'react';
170
+ import { Checkbox, CheckboxGroup } from '@bento/checkbox';
171
+
172
+ export function CheckboxGroupExample(args: React.ComponentProps<typeof CheckboxGroup>) {
173
+ return (
174
+ <CheckboxGroup label="Checkbox Group" name="checkbox-group-example" {...args}>
175
+ <Checkbox value="checkbox-1">Checkbox 1</Checkbox>
176
+ <Checkbox value="checkbox-2">Checkbox 2</Checkbox>
177
+ </CheckboxGroup>
178
+ );
179
+ }
180
+ ```
181
+
182
+ ### Controlled Checkbox Group
183
+
184
+ The `CheckboxGroup` can also be used in a controlled manner, where you manage the state of the checkboxes externally with the `value` and `onChange` props.
185
+
186
+ ```tsx
187
+ /* v8 ignore next */
188
+ import React, { useState } from 'react';
189
+ import { Checkbox, CheckboxGroup } from '@bento/checkbox';
190
+
191
+ export function CheckboxGroupControlledExample() {
192
+ const [selectedValues, setSelectedValues] = useState<string[]>([]);
193
+
194
+ return (
195
+ <CheckboxGroup label="Checkbox Group" value={selectedValues} onChange={setSelectedValues}>
196
+ <Checkbox value="option1">Option 1</Checkbox>
197
+ <Checkbox value="option2">Option 2</Checkbox>
198
+ <Checkbox value="option3">Option 3</Checkbox>
199
+ </CheckboxGroup>
200
+ );
201
+ }
202
+ ```
203
+
204
+ ### Checkbox Group with Indeterminate State
205
+
206
+ The `CheckboxGroup` can also support an indeterminate state, which is useful when some but not all checkboxes are selected. The complex state management shown here is an example of how to handle indeterminate states in a checkbox group in a common way.
207
+
208
+ ```tsx
209
+ /* v8 ignore next */
210
+ import React, { useState } from 'react';
211
+ import { Checkbox, CheckboxGroup } from '@bento/checkbox';
212
+
213
+ export function CheckboxGroupIndeterminateExample() {
214
+ const [checkedItems, setCheckedItems] = useState<Set<string>>(new Set());
215
+
216
+ const items = [
217
+ { id: 'option1', label: 'Option 1' },
218
+ { id: 'option2', label: 'Option 2' },
219
+ { id: 'option3', label: 'Option 3' }
220
+ ];
221
+
222
+ const allItemIds = items.map(function getItemId(item) {
223
+ return item.id;
224
+ });
225
+ const isAllSelected = checkedItems.size === items.length;
226
+ const isIndeterminate = checkedItems.size > 0 && checkedItems.size < items.length;
227
+
228
+ function handleSelectAll(checked: boolean) {
229
+ if (checked) {
230
+ setCheckedItems(new Set([...allItemIds, 'select-all']));
231
+ } else {
232
+ setCheckedItems(new Set());
233
+ }
234
+ }
235
+
236
+ function handleItemChange(itemId: string, checked: boolean) {
237
+ setCheckedItems(function updateCheckedItems(prev) {
238
+ const newSet = new Set(prev);
239
+ if (checked) {
240
+ newSet.add(itemId);
241
+ if (
242
+ allItemIds.every(function checkItemInSet(id) {
243
+ return newSet.has(id);
244
+ })
245
+ ) {
246
+ newSet.add('select-all');
247
+ }
248
+ } else {
249
+ newSet.delete(itemId);
250
+ newSet.delete('select-all');
251
+ }
252
+ return newSet;
253
+ });
254
+ }
255
+
256
+ return (
257
+ <CheckboxGroup label="Select Items" value={Array.from(checkedItems)}>
258
+ <Checkbox
259
+ name="select-all"
260
+ value="select-all"
261
+ isSelected={isAllSelected}
262
+ isIndeterminate={isIndeterminate}
263
+ onChange={handleSelectAll}
264
+ >
265
+ Select All
266
+ </Checkbox>
267
+
268
+ {items.map((item) => (
269
+ <Checkbox
270
+ key={item.id}
271
+ name={item.id}
272
+ value={item.id}
273
+ isSelected={checkedItems.has(item.id)}
274
+ onChange={function handleItemChangeForItem(checked) {
275
+ return handleItemChange(item.id, checked);
276
+ }}
277
+ >
278
+ {item.label}
279
+ </Checkbox>
280
+ ))}
281
+ </CheckboxGroup>
282
+ );
283
+ }
284
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bento/checkbox",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Checkbox component",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -9,6 +9,7 @@
9
9
  "build": "tsup-node",
10
10
  "lint": "biome lint && tsc",
11
11
  "posttest": "npm run lint",
12
+ "prepublishOnly": "node ../../scripts/compile-readme.ts",
12
13
  "pretest": "npm run build",
13
14
  "test": "vitest --run",
14
15
  "test:watch": "vitest"
@@ -39,11 +40,11 @@
39
40
  "package.json"
40
41
  ],
41
42
  "dependencies": {
42
- "@bento/control": "^0.1.1",
43
- "@bento/icon": "^0.1.1",
44
- "@bento/slots": "^0.1.2",
45
- "@bento/use-data-attributes": "^0.1.0",
46
- "@bento/use-props": "^0.1.0",
43
+ "@bento/control": "^0.1.2",
44
+ "@bento/icon": "^0.1.2",
45
+ "@bento/slots": "^0.1.3",
46
+ "@bento/use-data-attributes": "^0.1.1",
47
+ "@bento/use-props": "^0.1.1",
47
48
  "@react-aria/utils": "^3.30.0",
48
49
  "react-aria": "^3.44.0",
49
50
  "react-stately": "^3.42.0"