1 | ---
|
2 | title: Radio
|
3 | storybookPath: forms-radio--default
|
4 | isExperimentalPackage: true
|
5 | ---
|
6 |
|
7 | Radios are used select a single value from several options — ususally in a form.
|
8 | If multiple choices are valid, consider using a `Checkbox` instead.
|
9 |
|
10 | ## Examples
|
11 |
|
12 | In order to toggle between options, all Radio components should have a matching
|
13 | `name` prop (unless you are using them inside of a `RadioGroup`).
|
14 |
|
15 | ```jsx live
|
16 | <Fieldset legend="Shrek Characters" gap="large">
|
17 | <Radio name="character_radio" value="Shrek" defaultChecked>
|
18 | Shrek
|
19 | </Radio>
|
20 | <Radio name="character_radio" value="Fiona">
|
21 | Fiona
|
22 | </Radio>
|
23 | <Radio name="character_radio" value="Donkey">
|
24 | Donkey
|
25 | </Radio>
|
26 | </Fieldset>
|
27 | ```
|
28 |
|
29 | ### Size
|
30 |
|
31 | Radio buttons are available in two sizes: `small` and `medium`.
|
32 |
|
33 | ```jsx live
|
34 | <Stack gap="large" dividers>
|
35 | <Fieldset legend="Radio variations (small)" gap="large">
|
36 | <Radio size="small" checked={false}>
|
37 | Unchecked
|
38 | </Radio>
|
39 | <Radio size="small" checked>
|
40 | Checked
|
41 | </Radio>
|
42 | <Radio size="small" disabled>
|
43 | Disabled
|
44 | </Radio>
|
45 | <Radio size="small" checked disabled>
|
46 | Checked + disabled
|
47 | </Radio>
|
48 | </Fieldset>
|
49 | <Fieldset legend="Radio variations (small)" gap="large">
|
50 | <Radio size="medium" checked={false}>
|
51 | Unchecked
|
52 | </Radio>
|
53 | <Radio size="medium" checked>
|
54 | Checked
|
55 | </Radio>
|
56 | <Radio size="medium" disabled>
|
57 | Disabled
|
58 | </Radio>
|
59 | <Radio size="medium" checked disabled>
|
60 | Checked + disabled
|
61 | </Radio>
|
62 | </Fieldset>
|
63 | </Stack>
|
64 | ```
|
65 |
|
66 | ## RadioGroup
|
67 |
|
68 | The `RadioGroup` can be used to control a group of `Radio` components. The
|
69 | `RadioGroup` handles the `value`, `tone`, `message`, and `disabled` state of
|
70 | it's children.
|
71 |
|
72 | ### Controlled
|
73 |
|
74 | To control a group of `Radio` components, wrap them with a `RadioGroup` and
|
75 | provide it with a `value` and `onChange` function.
|
76 |
|
77 | All `Radio` children _must_ be provided with a `value`.
|
78 |
|
79 | ```jsx live
|
80 | const [selected, setSelected] = React.useState('Shrek');
|
81 |
|
82 | return (
|
83 | <Fieldset legend="Shrek Characters" gap="large">
|
84 | <RadioGroup value={selected} onChange={setSelected} gap="large">
|
85 | <Radio value="Shrek">Shrek</Radio>
|
86 | <Radio value="Fiona">Fiona</Radio>
|
87 | <Radio value="Donkey">Donkey</Radio>
|
88 | </RadioGroup>
|
89 | {selected && (
|
90 | <Text>
|
91 | The selected character is <Strong>{selected}</Strong>
|
92 | </Text>
|
93 | )}
|
94 | </Fieldset>
|
95 | );
|
96 | ```
|
97 |
|
98 | ### Message and tone
|
99 |
|
100 | The `message` is used to communicate the status of a field, such as an error
|
101 | message. This will be announced on focus and can be combined with a `tone` to
|
102 | illustrate intent. The supported tones are: `critical`, `positive` and
|
103 | `neutral`.
|
104 |
|
105 | ```jsx live
|
106 | const [selected, setSelected] = React.useState('critical');
|
107 | const statuses = {
|
108 | critical: {
|
109 | message: 'Critical message',
|
110 | tone: 'critical',
|
111 | },
|
112 | positive: {
|
113 | message: 'Positive message',
|
114 | tone: 'positive',
|
115 | },
|
116 | neutral: {
|
117 | message: 'Neutral message',
|
118 | tone: 'neutral',
|
119 | },
|
120 | };
|
121 |
|
122 | return (
|
123 | <Fieldset legend="Message and Tone" gap="large">
|
124 | <RadioGroup
|
125 | message={statuses[selected]?.message}
|
126 | tone={statuses[selected]?.tone}
|
127 | value={selected}
|
128 | onChange={setSelected}
|
129 | >
|
130 | <Radio value="critical">Critical</Radio>
|
131 | <Radio value="positive">Positive</Radio>
|
132 | <Radio value="neutral">Neutral</Radio>
|
133 | </RadioGroup>
|
134 | </Fieldset>
|
135 | );
|
136 | ```
|
137 |
|
138 | ## RadioCard
|
139 |
|
140 | A RadioCard is an alternative to Radio. Use RadioCard where a user needs to make
|
141 | one selection out of several choices, and where each option requires some
|
142 | detailed information.
|
143 |
|
144 | ### Controlled
|
145 |
|
146 | ```jsx live
|
147 | const terms = [
|
148 | { label: '6 months', description: '$426.08/fortnight' },
|
149 | { label: '12 months', description: '$214.54/fortnight' },
|
150 | { label: '24 months', description: '$108.77/fortnight' },
|
151 | { label: '36 months', description: '73.52/fortnight' },
|
152 | { label: '48 months', description: '55.89/fortnight' },
|
153 | ];
|
154 |
|
155 | const [selected, setSelected] = React.useState(terms[0].label);
|
156 |
|
157 | return (
|
158 | <Stack gap="large">
|
159 | <Fieldset legend="Select a repayment term" gap="large">
|
160 | <RadioGroup value={selected} onChange={setSelected}>
|
161 | {terms.map(({ label, description }) => (
|
162 | <RadioCard key={label} value={label} description={description}>
|
163 | {label}
|
164 | </RadioCard>
|
165 | ))}
|
166 | </RadioGroup>
|
167 | </Fieldset>
|
168 | {selected && (
|
169 | <Text>
|
170 | You have selected <Strong>{selected}</Strong>
|
171 | </Text>
|
172 | )}
|
173 | </Stack>
|
174 | );
|
175 | ```
|
176 |
|
177 | ### Uncontrolled
|
178 |
|
179 | ```jsx live
|
180 | <Fieldset legend="Select a repayment term" gap="large">
|
181 | <RadioCard
|
182 | description="$426.08/fortnight"
|
183 | name="repayment_terms"
|
184 | defaultChecked
|
185 | >
|
186 | 6 months
|
187 | </RadioCard>
|
188 | <RadioCard description="$214.54/fortnight" name="repayment_terms">
|
189 | 12 months
|
190 | </RadioCard>
|
191 | <RadioCard description="$108.77/fortnight" name="repayment_terms">
|
192 | 24 months
|
193 | </RadioCard>
|
194 | <RadioCard description="73.52/fortnight" name="repayment_terms">
|
195 | 36 months
|
196 | </RadioCard>
|
197 | <RadioCard description="55.89/fortnight" name="repayment_terms">
|
198 | 48 months
|
199 | </RadioCard>
|
200 | </Fieldset>
|
201 | ```
|
202 |
|
203 | ### Without description
|
204 |
|
205 | RadioCards without a description have a lower prominence label.
|
206 |
|
207 | ```jsx live
|
208 | const [selected, setSelected] = React.useState('Shrek');
|
209 |
|
210 | return (
|
211 | <Fieldset legend="Shrek Characters" gap="large">
|
212 | <RadioGroup value={selected} onChange={setSelected} gap="large">
|
213 | <RadioCard value="Shrek">Shrek</RadioCard>
|
214 | <RadioCard value="Fiona">Fiona</RadioCard>
|
215 | <RadioCard value="Donkey">Donkey</RadioCard>
|
216 | </RadioGroup>
|
217 | {selected && (
|
218 | <Text>
|
219 | The selected character is <Strong>{selected}</Strong>
|
220 | </Text>
|
221 | )}
|
222 | </Fieldset>
|
223 | );
|
224 | ```
|
225 |
|
226 | ## Props
|
227 |
|
228 | ### Radio
|
229 |
|
230 | <PropsTable displayName="Radio" />
|
231 |
|
232 | The `Radio` component also extends `InputHTMLAttributes` props and are not
|
233 | listed here.
|
234 |
|
235 | ### RadioPrimitive
|
236 |
|
237 | <PropsTable displayName="RadioPrimitive" />
|
238 |
|
239 | [data-attribute-map]:
|
240 | https://github.com/brighte-labs/spark-web/blob/e7f6f4285b4cfd876312cc89fbdd094039aa239a/packages/utils/src/internal/buildDataAttributes.ts#L1
|
241 |
|
242 | The `CheckboxPrimitive` component also extends `InputHTMLAttributes` props and
|
243 | are not listed here.
|
244 |
|
245 | ### RadioGroup
|
246 |
|
247 | <PropsTable displayName="RadioGroup" />
|
248 |
|
249 | ### RadioCard
|
250 |
|
251 | <PropsTable displayName="RadioCard" />
|
252 |
|
253 | The `RadioCard` component also extends `InputHTMLAttributes` props and are not
|
254 | listed here.
|