@fpkit/acss 5.0.0 → 6.0.0
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/libs/components/form/checkbox.css +1 -1
- package/libs/components/form/checkbox.css.map +1 -1
- package/libs/components/form/checkbox.min.css +2 -2
- package/libs/components/form/form.css +1 -1
- package/libs/components/form/form.css.map +1 -1
- package/libs/components/form/form.min.css +2 -2
- package/libs/index.cjs +13 -13
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +69 -20
- package/libs/index.d.ts +69 -20
- package/libs/index.js +3 -3
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/form/CHECKBOX-STYLES.mdx +766 -0
- package/src/components/form/CHECKBOX.mdx +665 -0
- package/src/components/form/checkbox.scss +28 -0
- package/src/components/form/checkbox.tsx +72 -22
- package/src/components/form/form.scss +7 -0
- package/src/components/form/input.stories.tsx +71 -22
- package/src/styles/form/checkbox.css +19 -0
- package/src/styles/form/checkbox.css.map +1 -1
- package/src/styles/form/form.css +25 -0
- package/src/styles/form/form.css.map +1 -1
- package/src/styles/index.css +25 -0
- package/src/styles/index.css.map +1 -1
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="FP.REACT Forms/Checkbox/Styles" />
|
|
4
|
+
|
|
5
|
+
# Checkbox CSS Documentation
|
|
6
|
+
|
|
7
|
+
Comprehensive CSS customization guide for the Checkbox component using CSS
|
|
8
|
+
custom properties (CSS variables).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
1. [Size & Spacing](#size--spacing)
|
|
15
|
+
2. [Colors & Backgrounds](#colors--backgrounds)
|
|
16
|
+
3. [States (Hover, Focus, Disabled)](#states)
|
|
17
|
+
4. [Typography](#typography)
|
|
18
|
+
5. [Borders & Radius](#borders--radius)
|
|
19
|
+
6. [Advanced Customization](#advanced-customization)
|
|
20
|
+
7. [CSS Variable Reference](#css-variable-reference)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Size & Spacing
|
|
25
|
+
|
|
26
|
+
### Checkbox Dimensions
|
|
27
|
+
|
|
28
|
+
Control the checkbox input size using predefined tokens or custom values:
|
|
29
|
+
|
|
30
|
+
```css
|
|
31
|
+
/* Use predefined size tokens (recommended) */
|
|
32
|
+
:root {
|
|
33
|
+
--checkbox-size-xs: 0.875rem; /* 14px */
|
|
34
|
+
--checkbox-size-sm: 1rem; /* 16px */
|
|
35
|
+
--checkbox-size-md: 1.25rem; /* 20px - default */
|
|
36
|
+
--checkbox-size-lg: 1.5rem; /* 24px */
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Or override the base size directly */
|
|
40
|
+
.custom-checkbox {
|
|
41
|
+
--checkbox-size: 2rem; /* 32px */
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Via React Component:**
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
{/* Semantic size prop */}
|
|
49
|
+
<Checkbox size="lg" ... />
|
|
50
|
+
|
|
51
|
+
{/* Custom CSS variable */}
|
|
52
|
+
<Checkbox
|
|
53
|
+
styles={{ '--checkbox-size': '2rem' }}
|
|
54
|
+
...
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Gap Between Checkbox and Label
|
|
59
|
+
|
|
60
|
+
Control spacing between the checkbox input and label text:
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
:root {
|
|
64
|
+
--checkbox-gap-xs: 0.375rem; /* 6px */
|
|
65
|
+
--checkbox-gap-sm: 0.5rem; /* 8px */
|
|
66
|
+
--checkbox-gap-md: 0.5rem; /* 8px - default */
|
|
67
|
+
--checkbox-gap-lg: 0.625rem; /* 10px */
|
|
68
|
+
|
|
69
|
+
/* Base gap variable */
|
|
70
|
+
--checkbox-gap: var(--checkbox-gap-md);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Override per component:**
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<Checkbox
|
|
78
|
+
styles={{
|
|
79
|
+
'--checkbox-gap': '1rem' /* 16px */
|
|
80
|
+
}}
|
|
81
|
+
...
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Colors & Backgrounds
|
|
88
|
+
|
|
89
|
+
### Checkbox Background
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
:root {
|
|
93
|
+
/* Default unchecked background */
|
|
94
|
+
--checkbox-bg: var(--color-surface);
|
|
95
|
+
|
|
96
|
+
/* Checked state background */
|
|
97
|
+
--checkbox-checked-bg: var(--color-success);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Example: Brand colored checkbox**
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<Checkbox
|
|
105
|
+
styles={{
|
|
106
|
+
'--checkbox-checked-bg': '#0066cc',
|
|
107
|
+
'--checkbox-checked-outline-color': '#0066cc'
|
|
108
|
+
}}
|
|
109
|
+
...
|
|
110
|
+
/>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Border Colors
|
|
114
|
+
|
|
115
|
+
```css
|
|
116
|
+
:root {
|
|
117
|
+
/* Default border color */
|
|
118
|
+
--checkbox-border-color: var(--color-neutral-600);
|
|
119
|
+
|
|
120
|
+
/* Border width */
|
|
121
|
+
--checkbox-border: 0.125rem solid var(--checkbox-border-color);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Checked State Outline
|
|
126
|
+
|
|
127
|
+
```css
|
|
128
|
+
:root {
|
|
129
|
+
/* Outline color when checked */
|
|
130
|
+
--checkbox-checked-outline-color: var(--color-success);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Example: Custom checked state**
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<Checkbox
|
|
138
|
+
styles={{
|
|
139
|
+
'--checkbox-checked-bg': '#10b981',
|
|
140
|
+
'--checkbox-checked-outline-color': '#10b981'
|
|
141
|
+
}}
|
|
142
|
+
defaultChecked
|
|
143
|
+
...
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## States
|
|
150
|
+
|
|
151
|
+
### Hover State
|
|
152
|
+
|
|
153
|
+
Style the label when hovering over the checkbox wrapper:
|
|
154
|
+
|
|
155
|
+
```css
|
|
156
|
+
:root {
|
|
157
|
+
--checkbox-hover-label-color: currentColor;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Applied via CSS :has() selector */
|
|
161
|
+
div:has(> input[type="checkbox"]):not(
|
|
162
|
+
:has(> input[aria-disabled="true"])
|
|
163
|
+
):hover {
|
|
164
|
+
.checkbox-label {
|
|
165
|
+
color: var(--checkbox-hover-label-color, currentColor);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Example: Highlighted hover state**
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<Checkbox
|
|
174
|
+
styles={{
|
|
175
|
+
'--checkbox-hover-label-color': '#0066cc'
|
|
176
|
+
}}
|
|
177
|
+
...
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Focus State
|
|
182
|
+
|
|
183
|
+
Customize focus ring for keyboard navigation (WCAG 2.4.7 compliant):
|
|
184
|
+
|
|
185
|
+
```css
|
|
186
|
+
:root {
|
|
187
|
+
/* Focus ring color */
|
|
188
|
+
--checkbox-focus-ring-color: var(--color-focus-ring);
|
|
189
|
+
|
|
190
|
+
/* Focus ring width */
|
|
191
|
+
--checkbox-focus-ring-width: 0.125rem; /* 2px */
|
|
192
|
+
|
|
193
|
+
/* Focus ring offset (space between checkbox and ring) */
|
|
194
|
+
--checkbox-focus-ring-offset: 0.125rem;
|
|
195
|
+
|
|
196
|
+
/* Focus ring radius */
|
|
197
|
+
--checkbox-focus-radius: 0.125rem;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Example: High contrast focus indicator**
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
<Checkbox
|
|
205
|
+
styles={{
|
|
206
|
+
'--checkbox-focus-ring-color': '#ff0000',
|
|
207
|
+
'--checkbox-focus-ring-width': '0.1875rem',
|
|
208
|
+
'--checkbox-focus-ring-offset': '0.25rem'
|
|
209
|
+
}}
|
|
210
|
+
...
|
|
211
|
+
/>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Keyboard Navigation:**
|
|
215
|
+
|
|
216
|
+
- Focus ring only appears with `:focus-visible` (keyboard users)
|
|
217
|
+
- Mouse clicks don't show focus ring (better UX)
|
|
218
|
+
|
|
219
|
+
### Disabled State
|
|
220
|
+
|
|
221
|
+
```css
|
|
222
|
+
:root {
|
|
223
|
+
/* Opacity for entire checkbox wrapper when disabled */
|
|
224
|
+
--checkbox-disabled-opacity: 0.6;
|
|
225
|
+
|
|
226
|
+
/* Label text color when disabled */
|
|
227
|
+
--checkbox-disabled-color: var(--color-disabled-text);
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Applied automatically via aria-disabled:**
|
|
232
|
+
|
|
233
|
+
```css
|
|
234
|
+
div:has(> input[aria-disabled="true"]) {
|
|
235
|
+
opacity: var(--checkbox-disabled-opacity, 0.6);
|
|
236
|
+
cursor: not-allowed;
|
|
237
|
+
|
|
238
|
+
.checkbox-label {
|
|
239
|
+
color: var(--checkbox-disabled-color, var(--color-disabled-text));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Example: Custom disabled styling**
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
<Checkbox
|
|
248
|
+
disabled
|
|
249
|
+
styles={{
|
|
250
|
+
'--checkbox-disabled-opacity': '0.4',
|
|
251
|
+
'--checkbox-disabled-color': '#999'
|
|
252
|
+
}}
|
|
253
|
+
...
|
|
254
|
+
/>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Error (Invalid) State
|
|
258
|
+
|
|
259
|
+
```css
|
|
260
|
+
:root {
|
|
261
|
+
/* Label color when validation fails */
|
|
262
|
+
--checkbox-error-label-color: var(--color-error-text);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Applied automatically via aria-invalid */
|
|
266
|
+
div:has(> input[aria-invalid="true"]) {
|
|
267
|
+
.checkbox-label {
|
|
268
|
+
color: var(--checkbox-error-label-color, var(--color-error-text));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Usage:**
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
<Checkbox
|
|
277
|
+
validationState="invalid"
|
|
278
|
+
errorMessage="This field is required"
|
|
279
|
+
styles={{
|
|
280
|
+
'--checkbox-error-label-color': '#dc2626'
|
|
281
|
+
}}
|
|
282
|
+
...
|
|
283
|
+
/>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Valid State
|
|
287
|
+
|
|
288
|
+
```css
|
|
289
|
+
:root {
|
|
290
|
+
/* Label color when validation passes */
|
|
291
|
+
--checkbox-valid-label-color: currentColor;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Applied when checked and explicitly valid */
|
|
295
|
+
div:has(> input[aria-invalid="false"]:checked) {
|
|
296
|
+
label[for] {
|
|
297
|
+
color: var(--checkbox-valid-label-color, currentColor);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Typography
|
|
305
|
+
|
|
306
|
+
### Label Font Size & Line Height
|
|
307
|
+
|
|
308
|
+
```css
|
|
309
|
+
:root {
|
|
310
|
+
/* Label font size */
|
|
311
|
+
--checkbox-label-fs: 1rem; /* 16px */
|
|
312
|
+
|
|
313
|
+
/* Label line height */
|
|
314
|
+
--checkbox-label-lh: 1.5;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.checkbox-label {
|
|
318
|
+
font-size: var(--checkbox-label-fs, 1rem);
|
|
319
|
+
line-height: var(--checkbox-label-lh, 1.5);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Example: Larger label text**
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
<Checkbox
|
|
327
|
+
styles={{
|
|
328
|
+
'--checkbox-label-fs': '1.125rem',
|
|
329
|
+
'--checkbox-label-lh': '1.6'
|
|
330
|
+
}}
|
|
331
|
+
...
|
|
332
|
+
/>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Required Indicator (Asterisk)
|
|
336
|
+
|
|
337
|
+
```css
|
|
338
|
+
:root {
|
|
339
|
+
/* Required asterisk color */
|
|
340
|
+
--color-required: #dc2626;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.checkbox-required {
|
|
344
|
+
color: var(--color-required);
|
|
345
|
+
font-weight: 600;
|
|
346
|
+
margin-inline-start: 0.125rem;
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Borders & Radius
|
|
353
|
+
|
|
354
|
+
### Border Radius
|
|
355
|
+
|
|
356
|
+
```css
|
|
357
|
+
:root {
|
|
358
|
+
/* Checkbox corner rounding */
|
|
359
|
+
--checkbox-radius: 0.25rem; /* 4px */
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Applied to input */
|
|
363
|
+
input[type="checkbox"] {
|
|
364
|
+
border-radius: var(--checkbox-radius, 0.25rem);
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Example: Fully rounded checkbox**
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
<Checkbox
|
|
372
|
+
styles={{
|
|
373
|
+
'--checkbox-radius': '50%' /* Circle */
|
|
374
|
+
}}
|
|
375
|
+
...
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Border Width & Style
|
|
380
|
+
|
|
381
|
+
```css
|
|
382
|
+
:root {
|
|
383
|
+
--checkbox-border: 0.125rem solid var(--checkbox-border-color);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Advanced Customization
|
|
390
|
+
|
|
391
|
+
### Transition & Animation
|
|
392
|
+
|
|
393
|
+
```css
|
|
394
|
+
:root {
|
|
395
|
+
--checkbox-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
input[type="checkbox"] {
|
|
399
|
+
transition: var(--checkbox-transition);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/* Respect user motion preferences (WCAG 2.3.3) */
|
|
403
|
+
@media (prefers-reduced-motion: reduce) {
|
|
404
|
+
.checkbox-label {
|
|
405
|
+
transition: none;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Cursor Styles
|
|
411
|
+
|
|
412
|
+
```css
|
|
413
|
+
:root {
|
|
414
|
+
--checkbox-cursor: pointer;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
input[type="checkbox"] {
|
|
418
|
+
cursor: var(--checkbox-cursor);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.checkbox-label {
|
|
422
|
+
cursor: pointer;
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Dark Mode Example
|
|
427
|
+
|
|
428
|
+
```css
|
|
429
|
+
/* Automatically applied based on color-scheme */
|
|
430
|
+
@media (prefers-color-scheme: dark) {
|
|
431
|
+
:root {
|
|
432
|
+
--checkbox-bg: #1a1a1a;
|
|
433
|
+
--checkbox-border-color: #4b5563;
|
|
434
|
+
--checkbox-checked-bg: #10b981;
|
|
435
|
+
--checkbox-label-fs: 1rem;
|
|
436
|
+
--color-disabled-text: #6b7280;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Via Component:**
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
<div className="dark-theme">
|
|
445
|
+
<Checkbox
|
|
446
|
+
styles={{
|
|
447
|
+
'--checkbox-bg': '#1a1a1a',
|
|
448
|
+
'--checkbox-border-color': '#4b5563',
|
|
449
|
+
'--checkbox-checked-bg': '#10b981'
|
|
450
|
+
}}
|
|
451
|
+
...
|
|
452
|
+
/>
|
|
453
|
+
</div>
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Custom Checkmark Icon
|
|
457
|
+
|
|
458
|
+
The checked state uses an SVG checkmark. Override via CSS:
|
|
459
|
+
|
|
460
|
+
```scss
|
|
461
|
+
input[type="checkbox"]:checked {
|
|
462
|
+
background: var(--checkbox-checked-bg) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'><path d='M6.173 11.414l-3.89-3.89 1.414-1.414 2.476 2.475 5.657-5.657 1.414 1.414z'/></svg>")
|
|
463
|
+
no-repeat center center;
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Custom icon example:**
|
|
468
|
+
|
|
469
|
+
```css
|
|
470
|
+
.custom-checkbox input[type="checkbox"]:checked {
|
|
471
|
+
background-image: url("data:image/svg+xml;utf8,<svg ...>YOUR_SVG_HERE</svg>");
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## CSS Variable Reference
|
|
478
|
+
|
|
479
|
+
### Complete List of Variables
|
|
480
|
+
|
|
481
|
+
#### Size & Spacing
|
|
482
|
+
|
|
483
|
+
| Variable | Default | Description |
|
|
484
|
+
| -------------------- | ------------------------- | ------------------------------------- |
|
|
485
|
+
| `--checkbox-size-xs` | `0.875rem` (14px) | Extra small size token |
|
|
486
|
+
| `--checkbox-size-sm` | `1rem` (16px) | Small size token |
|
|
487
|
+
| `--checkbox-size-md` | `1.25rem` (20px) | Medium size token (default) |
|
|
488
|
+
| `--checkbox-size-lg` | `1.5rem` (24px) | Large size token |
|
|
489
|
+
| `--checkbox-size` | `var(--checkbox-size-md)` | Active checkbox dimensions |
|
|
490
|
+
| `--checkbox-gap-xs` | `0.375rem` (6px) | Extra small gap |
|
|
491
|
+
| `--checkbox-gap-sm` | `0.5rem` (8px) | Small gap |
|
|
492
|
+
| `--checkbox-gap-md` | `0.5rem` (8px) | Medium gap (default) |
|
|
493
|
+
| `--checkbox-gap-lg` | `0.625rem` (10px) | Large gap |
|
|
494
|
+
| `--checkbox-gap` | `var(--checkbox-gap-md)` | Active gap between checkbox and label |
|
|
495
|
+
|
|
496
|
+
#### Colors & Backgrounds
|
|
497
|
+
|
|
498
|
+
| Variable | Default | Description |
|
|
499
|
+
| ---------------------------------- | -------------------------- | ---------------------------- |
|
|
500
|
+
| `--checkbox-bg` | `var(--color-surface)` | Background color (unchecked) |
|
|
501
|
+
| `--checkbox-border-color` | `var(--color-neutral-600)` | Border color |
|
|
502
|
+
| `--checkbox-checked-bg` | `var(--color-success)` | Background when checked |
|
|
503
|
+
| `--checkbox-checked-outline-color` | `var(--color-success)` | Outline color when checked |
|
|
504
|
+
|
|
505
|
+
#### States
|
|
506
|
+
|
|
507
|
+
| Variable | Default | Description |
|
|
508
|
+
| ------------------------------ | ---------------------------- | -------------------------- |
|
|
509
|
+
| `--checkbox-hover-label-color` | `currentColor` | Label color on hover |
|
|
510
|
+
| `--checkbox-focus-ring-color` | `var(--color-focus-ring)` | Focus ring color |
|
|
511
|
+
| `--checkbox-focus-ring-width` | `0.125rem` | Focus ring width |
|
|
512
|
+
| `--checkbox-focus-ring-offset` | `0.125rem` | Focus ring offset distance |
|
|
513
|
+
| `--checkbox-focus-radius` | `0.125rem` | Focus ring border radius |
|
|
514
|
+
| `--checkbox-disabled-opacity` | `0.6` | Opacity when disabled |
|
|
515
|
+
| `--checkbox-disabled-color` | `var(--color-disabled-text)` | Label color when disabled |
|
|
516
|
+
| `--checkbox-error-label-color` | `var(--color-error-text)` | Label color when invalid |
|
|
517
|
+
| `--checkbox-valid-label-color` | `currentColor` | Label color when valid |
|
|
518
|
+
|
|
519
|
+
#### Typography
|
|
520
|
+
|
|
521
|
+
| Variable | Default | Description |
|
|
522
|
+
| --------------------- | --------- | ----------------------- |
|
|
523
|
+
| `--checkbox-label-fs` | `1rem` | Label font size |
|
|
524
|
+
| `--checkbox-label-lh` | `1.5` | Label line height |
|
|
525
|
+
| `--color-required` | `#dc2626` | Required asterisk color |
|
|
526
|
+
|
|
527
|
+
#### Borders & Effects
|
|
528
|
+
|
|
529
|
+
| Variable | Default | Description |
|
|
530
|
+
| ----------------------- | --------------------------------------------- | ----------------- |
|
|
531
|
+
| `--checkbox-radius` | `0.25rem` | Border radius |
|
|
532
|
+
| `--checkbox-border` | `0.125rem solid var(--checkbox-border-color)` | Border style |
|
|
533
|
+
| `--checkbox-cursor` | `pointer` | Cursor style |
|
|
534
|
+
| `--checkbox-transition` | `all 0.2s cubic-bezier(0.4, 0, 0.2, 1)` | Transition timing |
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Data Attributes
|
|
539
|
+
|
|
540
|
+
### Size Variant Selector
|
|
541
|
+
|
|
542
|
+
The `size` prop applies a `data-checkbox-size` attribute for CSS targeting:
|
|
543
|
+
|
|
544
|
+
```css
|
|
545
|
+
/* Extra small */
|
|
546
|
+
div[data-checkbox-size~="xs"] {
|
|
547
|
+
--checkbox-size: var(--checkbox-size-xs);
|
|
548
|
+
--checkbox-gap: var(--checkbox-gap-xs);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/* Small */
|
|
552
|
+
div[data-checkbox-size~="sm"] {
|
|
553
|
+
--checkbox-size: var(--checkbox-size-sm);
|
|
554
|
+
--checkbox-gap: var(--checkbox-gap-sm);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* Medium */
|
|
558
|
+
div[data-checkbox-size~="md"] {
|
|
559
|
+
--checkbox-size: var(--checkbox-size-md);
|
|
560
|
+
--checkbox-gap: var(--checkbox-gap-md);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/* Large */
|
|
564
|
+
div[data-checkbox-size~="lg"] {
|
|
565
|
+
--checkbox-size: var(--checkbox-size-lg);
|
|
566
|
+
--checkbox-gap: var(--checkbox-gap-lg);
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
**Usage in custom CSS:**
|
|
571
|
+
|
|
572
|
+
```css
|
|
573
|
+
/* Target all large checkboxes */
|
|
574
|
+
[data-checkbox-size~="lg"] {
|
|
575
|
+
/* Custom styles for large checkboxes */
|
|
576
|
+
--checkbox-border: 0.1875rem solid var(--checkbox-border-color);
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## SCSS Structure
|
|
583
|
+
|
|
584
|
+
The checkbox styles use modern CSS with `:has()` selector for parent-based
|
|
585
|
+
styling:
|
|
586
|
+
|
|
587
|
+
```scss
|
|
588
|
+
// Checkbox wrapper detects child input state
|
|
589
|
+
div:has(> input[type="checkbox"]) {
|
|
590
|
+
display: flex;
|
|
591
|
+
align-items: center;
|
|
592
|
+
gap: var(--checkbox-gap, 0.5rem);
|
|
593
|
+
|
|
594
|
+
// Hover state (only when not disabled)
|
|
595
|
+
&:not(:has(> input[aria-disabled="true"])):hover {
|
|
596
|
+
.checkbox-label {
|
|
597
|
+
color: var(--checkbox-hover-label-color, currentColor);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Focus-visible for keyboard users
|
|
602
|
+
&:has(> input:focus-visible) {
|
|
603
|
+
.checkbox-label {
|
|
604
|
+
outline: var(--checkbox-focus-ring-width) solid var(
|
|
605
|
+
--checkbox-focus-ring-color
|
|
606
|
+
);
|
|
607
|
+
outline-offset: var(--checkbox-focus-ring-offset);
|
|
608
|
+
border-radius: var(--checkbox-focus-radius);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Disabled state via aria-disabled
|
|
613
|
+
&:has(> input[aria-disabled="true"]) {
|
|
614
|
+
opacity: var(--checkbox-disabled-opacity, 0.6);
|
|
615
|
+
cursor: not-allowed;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Invalid state via aria-invalid
|
|
619
|
+
&:has(> input[aria-invalid="true"]) {
|
|
620
|
+
.checkbox-label {
|
|
621
|
+
color: var(--checkbox-error-label-color);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Valid state (checked + explicitly valid)
|
|
626
|
+
&:has(> input[aria-invalid="false"]:checked) {
|
|
627
|
+
label[for] {
|
|
628
|
+
color: var(--checkbox-valid-label-color);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## Browser Compatibility
|
|
637
|
+
|
|
638
|
+
### `:has()` Selector Support
|
|
639
|
+
|
|
640
|
+
The checkbox styles use the modern `:has()` pseudo-class for parent-based
|
|
641
|
+
styling:
|
|
642
|
+
|
|
643
|
+
- ✅ Chrome 105+
|
|
644
|
+
- ✅ Firefox 121+
|
|
645
|
+
- ✅ Safari 15.4+
|
|
646
|
+
- ✅ Edge 105+
|
|
647
|
+
|
|
648
|
+
**Graceful Degradation:** Older browsers that don't support `:has()` will
|
|
649
|
+
display standard checkbox styling without advanced hover/focus/disabled states.
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## Naming Convention
|
|
654
|
+
|
|
655
|
+
All CSS variables follow the @fpkit/acss standardized naming pattern:
|
|
656
|
+
|
|
657
|
+
```
|
|
658
|
+
--{component}-{element}-{variant}-{property}-{modifier}
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Examples:**
|
|
662
|
+
|
|
663
|
+
| Variable | Breakdown |
|
|
664
|
+
| ----------------------------- | -------------------------------------------------------------------------- |
|
|
665
|
+
| `--checkbox-size` | component: `checkbox`, property: `size` |
|
|
666
|
+
| `--checkbox-label-fs` | component: `checkbox`, element: `label`, property: `fs` (font-size) |
|
|
667
|
+
| `--checkbox-focus-ring-color` | component: `checkbox`, state: `focus`, property: `ring`, modifier: `color` |
|
|
668
|
+
| `--checkbox-gap-sm` | component: `checkbox`, property: `gap`, variant: `sm` |
|
|
669
|
+
|
|
670
|
+
**Approved Abbreviations:**
|
|
671
|
+
|
|
672
|
+
- `bg` → background
|
|
673
|
+
- `fs` → font-size
|
|
674
|
+
- `fw` → font-weight
|
|
675
|
+
- `radius` → border-radius
|
|
676
|
+
- `gap` → gap (already short)
|
|
677
|
+
|
|
678
|
+
See `/docs/css-variables.md` for full naming guidelines.
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## Theming Examples
|
|
683
|
+
|
|
684
|
+
### Example 1: Brand Theme
|
|
685
|
+
|
|
686
|
+
```tsx
|
|
687
|
+
<Checkbox
|
|
688
|
+
id="brand"
|
|
689
|
+
label="Brand themed checkbox"
|
|
690
|
+
size="lg"
|
|
691
|
+
styles={{
|
|
692
|
+
"--checkbox-border-color": "#0066cc",
|
|
693
|
+
"--checkbox-checked-bg": "#0066cc",
|
|
694
|
+
"--checkbox-checked-outline-color": "#0066cc",
|
|
695
|
+
"--checkbox-focus-ring-color": "#0066cc",
|
|
696
|
+
"--checkbox-hover-label-color": "#0066cc",
|
|
697
|
+
}}
|
|
698
|
+
/>
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Example 2: High Contrast
|
|
702
|
+
|
|
703
|
+
```tsx
|
|
704
|
+
<Checkbox
|
|
705
|
+
id="high-contrast"
|
|
706
|
+
label="High contrast checkbox"
|
|
707
|
+
styles={{
|
|
708
|
+
"--checkbox-border": "0.1875rem solid #000",
|
|
709
|
+
"--checkbox-checked-bg": "#000",
|
|
710
|
+
"--checkbox-focus-ring-width": "0.25rem",
|
|
711
|
+
"--checkbox-focus-ring-color": "#000",
|
|
712
|
+
"--checkbox-label-fs": "1.125rem",
|
|
713
|
+
}}
|
|
714
|
+
/>
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### Example 3: Minimal Style
|
|
718
|
+
|
|
719
|
+
```tsx
|
|
720
|
+
<Checkbox
|
|
721
|
+
id="minimal"
|
|
722
|
+
label="Minimal checkbox"
|
|
723
|
+
styles={{
|
|
724
|
+
"--checkbox-border-color": "#e5e7eb",
|
|
725
|
+
"--checkbox-checked-bg": "#000",
|
|
726
|
+
"--checkbox-radius": "0.125rem",
|
|
727
|
+
"--checkbox-focus-ring-offset": "0.25rem",
|
|
728
|
+
}}
|
|
729
|
+
/>
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
## Migration from Old Variables
|
|
735
|
+
|
|
736
|
+
If you're upgrading from v4.x and used undocumented CSS variables:
|
|
737
|
+
|
|
738
|
+
| Old (v4.x) | New (v5.0) | Notes |
|
|
739
|
+
| ----------------- | ----------------------------- | --------------------- |
|
|
740
|
+
| `--checkbox-size` | `--checkbox-size` | ✅ Still works |
|
|
741
|
+
| `--checkbox-gap` | `--checkbox-gap` | ✅ Still works |
|
|
742
|
+
| N/A | `--checkbox-size-xs/sm/md/lg` | ✨ New size tokens |
|
|
743
|
+
| N/A | `--checkbox-gap-xs/sm/md/lg` | ✨ New gap tokens |
|
|
744
|
+
| N/A | `data-checkbox-size` | ✨ New data attribute |
|
|
745
|
+
|
|
746
|
+
**No breaking changes** - all v4.x CSS variables continue to work in v5.0!
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## Resources
|
|
751
|
+
|
|
752
|
+
- **Main Component Guide**: [CHECKBOX.mdx](./CHECKBOX.mdx)
|
|
753
|
+
- **CSS Variable Standard**: `/docs/css-variables.md`
|
|
754
|
+
- **Storybook Examples**: View live checkbox examples
|
|
755
|
+
- **Source Code**: `packages/fpkit/src/components/form/checkbox.scss`
|
|
756
|
+
|
|
757
|
+
---
|
|
758
|
+
|
|
759
|
+
## Support
|
|
760
|
+
|
|
761
|
+
Questions about CSS customization?
|
|
762
|
+
[Open an issue](https://github.com/your-org/fpkit/issues)
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
MIT © fpkit
|