forked from primer/react
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Checkbox.tsx
91 lines (82 loc) · 2.69 KB
/
Checkbox.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import styled from 'styled-components'
import {useProvidedRefOrCreate} from './hooks'
import React, {ChangeEventHandler, InputHTMLAttributes, ReactElement, useContext, useLayoutEffect} from 'react'
import sx, {SxProp} from './sx'
import {FormValidationStatus} from './utils/types/FormValidationStatus'
import {CheckboxGroupContext} from './CheckboxGroup'
import getGlobalFocusStyles from './_getGlobalFocusStyles'
export type CheckboxProps = {
/**
* Apply indeterminate visual appearance to the checkbox
*/
indeterminate?: boolean
/**
* Apply inactive visual appearance to the checkbox
*/
disabled?: boolean
/**
* Forward a ref to the underlying input element
*/
ref?: React.RefObject<HTMLInputElement>
/**
* Indicates whether the checkbox must be checked
*/
required?: boolean
/**
* Indicates whether the checkbox validation state
*/
validationStatus?: FormValidationStatus
/**
* A unique value that is never shown to the user.
* Used during form submission and to identify which checkbox inputs are selected
*/
value?: string
} & Exclude<InputHTMLAttributes<HTMLInputElement>, 'value'> &
SxProp
const StyledCheckbox = styled.input`
cursor: pointer;
${props => props.disabled && `cursor: not-allowed;`}
${getGlobalFocusStyles(0)};
${sx}
`
/**
* An accessible, native checkbox component
*/
const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
(
{checked, indeterminate, disabled, onChange, sx: sxProp, required, validationStatus, value, ...rest}: CheckboxProps,
ref
): ReactElement => {
const checkboxRef = useProvidedRefOrCreate(ref as React.RefObject<HTMLInputElement>)
const checkboxGroupContext = useContext(CheckboxGroupContext)
const handleOnChange: ChangeEventHandler<HTMLInputElement> = e => {
checkboxGroupContext.onChange && checkboxGroupContext.onChange(e)
onChange && onChange(e)
}
useLayoutEffect(() => {
if (checkboxRef.current) {
checkboxRef.current.indeterminate = indeterminate || false
}
}, [indeterminate, checked, checkboxRef])
return (
<StyledCheckbox
type="checkbox"
disabled={disabled}
aria-disabled={disabled ? 'true' : 'false'}
ref={ref || checkboxRef}
checked={indeterminate ? false : checked}
aria-checked={indeterminate ? 'mixed' : checked ? 'true' : 'false'}
sx={sxProp}
required={required}
aria-required={required ? 'true' : 'false'}
aria-invalid={validationStatus === 'error' ? 'true' : 'false'}
onChange={handleOnChange}
value={value}
name={value}
{...rest}
/>
)
}
)
Checkbox.displayName = 'Checkbox'
export default Checkbox