forked from primer/react
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Radio.tsx
95 lines (86 loc) · 2.73 KB
/
Radio.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
92
93
94
95
import styled from 'styled-components'
import React, {ChangeEventHandler, InputHTMLAttributes, ReactElement, useContext} from 'react'
import sx, {SxProp} from './sx'
import {FormValidationStatus} from './utils/types/FormValidationStatus'
import {RadioGroupContext} from './RadioGroup'
import getGlobalFocusStyles from './_getGlobalFocusStyles'
export type RadioProps = {
/**
* A unique value that is never shown to the user.
* Used during form submission and to identify which radio button in a group is selected
*/
value: string
/**
* Name attribute of the input element. Required for grouping radio inputs
*/
name?: string
/**
* Apply inactive visual appearance to the radio button
*/
disabled?: boolean
/**
* Indicates whether the radio button is selected
*/
checked?: boolean
/**
* Forward a ref to the underlying input element
*/
ref?: React.RefObject<HTMLInputElement>
/**
* Indicates whether the radio button must be checked before the form can be submitted
*/
required?: boolean
/**
* Indicates whether the radio button validation state is non-standard
*/
validationStatus?: FormValidationStatus
} & InputHTMLAttributes<HTMLInputElement> &
SxProp
const StyledRadio = styled.input`
cursor: pointer;
${props => props.disabled && `cursor: not-allowed;`}
${getGlobalFocusStyles(0)};
${sx}
`
/**
* An accessible, native radio component for selecting one option from a list.
*/
const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
(
{checked, disabled, name: nameProp, onChange, sx: sxProp, required, validationStatus, value, ...rest}: RadioProps,
ref
): ReactElement => {
const radioGroupContext = useContext(RadioGroupContext)
const handleOnChange: ChangeEventHandler<HTMLInputElement> = e => {
radioGroupContext?.onChange && radioGroupContext.onChange(e)
onChange && onChange(e)
}
const name = nameProp || radioGroupContext?.name
if (!name) {
// eslint-disable-next-line no-console
console.warn(
'A radio input must have a `name` attribute. Pass `name` as a prop directly to each Radio, or nest them in a `RadioGroup` component with a `name` prop'
)
}
return (
<StyledRadio
type="radio"
value={value}
name={name}
ref={ref}
disabled={disabled}
aria-disabled={disabled ? 'true' : 'false'}
checked={checked}
aria-checked={checked ? 'true' : 'false'}
required={required}
aria-required={required ? 'true' : 'false'}
aria-invalid={validationStatus === 'error' ? 'true' : 'false'}
sx={sxProp}
onChange={handleOnChange}
{...rest}
/>
)
}
)
Radio.displayName = 'Radio'
export default Radio