Skip to content

Commit 2758996

Browse files
committed
fixup! fixup! fixup! Allow check fields and selectable fields to render as required #487
1 parent 1fbe84d commit 2758996

File tree

7 files changed

+225
-89
lines changed

7 files changed

+225
-89
lines changed

src/components/CheckboxField/README.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -205,18 +205,23 @@ React.createElement(() => {
205205
});
206206
```
207207

208-
However, your project may use the label color as the primary means to indicate
209-
the required state of input fields (see
210-
[Forms Theming](/docs/customize/theming/forms) for more). Because not checking
211-
an input is also a valid action, it may be confusing to users to see the
212-
optional check inputs greyed out.
208+
#### Styling the Required State
213209

214-
For this case, there is the `renderAsRequired` prop:
210+
All form fields in React UI can be
211+
[styled](/docs/customize/theming/forms/#required-state)
212+
to indicate the required state.
213+
214+
However, you may find yourself in a misleading situation where a form field
215+
is valid in both checked and unchecked states, for example to turn on or off a
216+
feature. If your project uses the label color as the primary means to indicate
217+
the required state of input fields and the usual asterisk `*` is omitted,
218+
you may want to keep the label color consistent for both states.
219+
220+
For this edge case, there is the `renderAsRequired` prop:
215221

216222
```docoff-react-preview
217223
React.createElement(() => {
218224
const [optional, setOptional] = React.useState(false);
219-
const [required, setRequired] = React.useState(false);
220225
const [renderAsRequired, setRenderAsRequired] = React.useState(false);
221226
return (
222227
<React.Fragment>
@@ -236,16 +241,9 @@ React.createElement(() => {
236241
onChange={() => setOptional(!optional)}
237242
/>
238243
<br />
239-
<CheckboxField
240-
checked={required}
241-
label="This field is required and must be checked"
242-
onChange={() => setRequired(!required)}
243-
required
244-
/>
245-
<br />
246244
<CheckboxField
247245
checked={renderAsRequired}
248-
label="Checked or unchecked, both states are valid"
246+
label="This field is optional but looks like required"
249247
onChange={() => setRenderAsRequired(!renderAsRequired)}
250248
renderAsRequired
251249
/>
@@ -255,8 +253,8 @@ React.createElement(() => {
255253
});
256254
```
257255

258-
It renders the field as required, but doesn't add the `required` attribute to
259-
the actual input.
256+
It renders the field as if it was required, but doesn't add the `required`
257+
attribute to the actual input.
260258

261259
### Disabled State
262260

src/components/Radio/README.md

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -269,41 +269,84 @@ React.createElement(() => {
269269
})
270270
```
271271

272-
However, you may find yourself in a situation where the input is not required
273-
(i.e. making the input checked), but you also don't want to render the field as
274-
optional because not choosing an option can be perfectly valid. For this case,
275-
there is the `renderAsRequired` prop:
272+
#### Styling the Required State
273+
274+
All form fields in React UI can be
275+
[styled](/docs/customize/theming/forms/#required-state)
276+
to indicate the required state.
277+
278+
However, you may find yourself in a misleading situation where a form field
279+
is valid in both selected and unselected states, for example to turn on or off a
280+
feature. If your project uses the label color as the primary means to indicate
281+
the required state of input fields and the usual asterisk `*` is omitted,
282+
you may want to keep the label color consistent for both states.
283+
284+
For this edge case, there is the `renderAsRequired` prop:
276285

277286
```docoff-react-preview
278287
React.createElement(() => {
279288
const [fruit, setFruit] = React.useState('apple');
280289
return (
281-
<Radio
282-
label="Your favourite fruit"
283-
onChange={(e) => setFruit(e.target.value)}
284-
options={[
285-
{
286-
label: 'Apple',
287-
value: 'apple',
288-
},
289-
{
290-
label: 'Banana',
291-
value: 'banana',
292-
},
293-
{
294-
label: 'Grapefruit',
295-
value: 'grapefruit',
296-
},
297-
]}
298-
value={fruit}
299-
renderAsRequired
300-
/>
290+
<React.Fragment>
291+
<style>
292+
{`
293+
.example--themed-form-fields {
294+
--rui-FormField__label__color: var(--rui-color-text-secondary);
295+
--rui-FormField--required__label__color: var(--rui-color-text-primary);
296+
--rui-FormField--required__sign: '';
297+
}
298+
`}
299+
</style>
300+
<div class="example--themed-form-fields">
301+
<Radio
302+
label="This field is optional"
303+
onChange={(e) => setFruit(e.target.value)}
304+
options={[
305+
{
306+
label: 'Apple',
307+
value: 'apple',
308+
},
309+
{
310+
label: 'Banana',
311+
value: 'banana',
312+
},
313+
{
314+
label: 'Grapefruit',
315+
value: 'grapefruit',
316+
},
317+
]}
318+
value={fruit}
319+
/>
320+
<br />
321+
<br />
322+
<Radio
323+
label="This field is optional but looks like required"
324+
onChange={(e) => setFruit(e.target.value)}
325+
options={[
326+
{
327+
label: 'Apple',
328+
value: 'apple',
329+
},
330+
{
331+
label: 'Banana',
332+
value: 'banana',
333+
},
334+
{
335+
label: 'Grapefruit',
336+
value: 'grapefruit',
337+
},
338+
]}
339+
value={fruit}
340+
renderAsRequired
341+
/>
342+
</div>
343+
</React.Fragment>
301344
);
302345
})
303346
```
304347

305-
It renders the field as required, but doesn't add the `required` attribute to
306-
the actual input.
348+
It renders the field as if it was required, but doesn't add the `required`
349+
attribute to the actual input.
307350

308351
### Disabled State
309352

src/components/Radio/Radio.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
@include foundation.label-required();
5353
}
5454

55+
.isRootRequired .optionLabel {
56+
@include foundation.label-required($show-require-sign: false);
57+
}
58+
5559
// States
5660
.isRootStateInvalid {
5761
@include variants.validation(invalid);

src/components/SelectField/README.md

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -624,41 +624,84 @@ React.createElement(() => {
624624
});
625625
```
626626

627-
However, you may find yourself in a situation where the input is not required
628-
(i.e. selecting an option), but you also don't want to render the field as
629-
optional because the unselected state can be perfectly valid. For this case,
630-
there is the `renderAsRequired` prop:
627+
#### Styling the Required State
628+
629+
All form fields in React UI can be
630+
[styled](/docs/customize/theming/forms/#required-state)
631+
to indicate the required state.
632+
633+
However, you may find yourself in a misleading situation where a form field
634+
is valid in both selected and unselected states, for example to turn on or off a
635+
feature. If your project uses the label color as the primary means to indicate
636+
the required state of input fields and the usual asterisk `*` is omitted,
637+
you may want to keep the label color consistent for both states.
638+
639+
For this edge case, there is the `renderAsRequired` prop:
631640

632641
```docoff-react-preview
633642
React.createElement(() => {
634643
const [fruit, setFruit] = React.useState('apple');
635644
return (
636-
<SelectField
637-
label="Your favourite fruit"
638-
onChange={(e) => setFruit(e.target.value)}
639-
options={[
640-
{
641-
label: 'Apple',
642-
value: 'apple',
643-
},
644-
{
645-
label: 'Banana',
646-
value: 'banana',
647-
},
648-
{
649-
label: 'Grapefruit',
650-
value: 'grapefruit',
651-
},
652-
]}
653-
value={fruit}
654-
renderAsRequired
655-
/>
645+
<React.Fragment>
646+
<style>
647+
{`
648+
.example--themed-form-fields {
649+
--rui-FormField__label__color: var(--rui-color-text-secondary);
650+
--rui-FormField--required__label__color: var(--rui-color-text-primary);
651+
--rui-FormField--required__sign: '';
652+
}
653+
`}
654+
</style>
655+
<div class="example--themed-form-fields">
656+
<SelectField
657+
label="This field is optional"
658+
onChange={(e) => setFruit(e.target.value)}
659+
options={[
660+
{
661+
label: 'Apple',
662+
value: 'apple',
663+
},
664+
{
665+
label: 'Banana',
666+
value: 'banana',
667+
},
668+
{
669+
label: 'Grapefruit',
670+
value: 'grapefruit',
671+
},
672+
]}
673+
value={fruit}
674+
/>
675+
<br />
676+
<br />
677+
<SelectField
678+
label="This field is optional but looks like required"
679+
onChange={(e) => setFruit(e.target.value)}
680+
options={[
681+
{
682+
label: 'Apple',
683+
value: 'apple',
684+
},
685+
{
686+
label: 'Banana',
687+
value: 'banana',
688+
},
689+
{
690+
label: 'Grapefruit',
691+
value: 'grapefruit',
692+
},
693+
]}
694+
value={fruit}
695+
renderAsRequired
696+
/>
697+
</div>
698+
</React.Fragment>
656699
);
657700
});
658701
```
659702

660-
It renders the field as required, but doesn't add the `required` attribute to
661-
the actual input.
703+
It renders the field as if it was required, but doesn't add the `required`
704+
attribute to the actual input.
662705

663706
### Disabled State
664707

src/components/Toggle/README.md

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,56 @@ React.createElement(() => {
181181
});
182182
```
183183

184-
However, you may find yourself in a situation where the input is not required
185-
(i.e. turning the toggle on), but you also don't want to render the field as
186-
optional because the unchecked state can be perfectly valid. For this case,
187-
there is the `renderAsRequired` prop:
184+
#### Styling the Required State
185+
186+
All form fields in React UI can be
187+
[styled](/docs/customize/theming/forms/#required-state)
188+
to indicate the required state.
189+
190+
However, you may find yourself in a misleading situation where a form field
191+
is valid in both checked and unchecked states, for example to turn on or off a
192+
feature. If your project uses the label color as the primary means to indicate
193+
the required state of input fields and the usual asterisk `*` is omitted,
194+
you may want to keep the label color consistent for both states.
195+
196+
For this edge case, there is the `renderAsRequired` prop:
188197

189198
```docoff-react-preview
190199
React.createElement(() => {
191-
const [studioQuality, setStudioQuality] = React.useState(true);
200+
const [optional, setOptional] = React.useState(false);
201+
const [renderAsRequired, setRenderAsRequired] = React.useState(false);
192202
return (
193-
<Toggle
194-
checked={studioQuality}
195-
label="Listen in studio quality"
196-
onChange={() => setStudioQuality(!studioQuality)}
197-
renderAsRequired
198-
/>
203+
<React.Fragment>
204+
<style>
205+
{`
206+
.example--themed-form-fields {
207+
--rui-FormField__label__color: var(--rui-color-text-secondary);
208+
--rui-FormField--required__label__color: var(--rui-color-text-primary);
209+
--rui-FormField--required__sign: '';
210+
}
211+
`}
212+
</style>
213+
<div class="example--themed-form-fields">
214+
<Toggle
215+
checked={optional}
216+
label="This field is optional"
217+
onChange={() => setOptional(!optional)}
218+
/>
219+
<br />
220+
<Toggle
221+
checked={renderAsRequired}
222+
label="This field is optional but looks like required"
223+
onChange={() => setRenderAsRequired(!renderAsRequired)}
224+
renderAsRequired
225+
/>
226+
</div>
227+
</React.Fragment>
199228
);
200229
});
201230
```
202231

203-
It renders the field as required, but doesn't add the `required` attribute to
204-
the actual input.
232+
It renders the field as if it was required, but doesn't add the `required`
233+
attribute to the actual input.
205234

206235
### Disabled State
207236

src/docs/customize/theming/forms.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ The following theme options define basic appearance of all form fields.
2323
| `--rui-FormField__help-text__font-size` | Help text font size |
2424
| `--rui-FormField__help-text__font-style` | Help text font style, e.g. italic |
2525
| `--rui-FormField__help-text__color` | Help text color |
26-
| `--rui-FormField--required__label__color` | Color of required input labels |
27-
| `--rui-FormField--required__sign` | Text appended to required input labels |
28-
| `--rui-FormField--required__sign__color` | Color of text appended to required input labels |
2926

3027
## Horizontal Layout
3128

@@ -599,6 +596,26 @@ React.createElement(() => {
599596
});
600597
```
601598

599+
## Required State
600+
601+
Theming options for required fields are shared by all form components.
602+
603+
| Custom Property | Description |
604+
|------------------------------------------------------|--------------------------------------------------------------|
605+
| `--rui-FormField--required__label__color` | Color of required input labels |
606+
| `--rui-FormField--required__sign` | Text appended to required input labels |
607+
| `--rui-FormField--required__sign__color` | Color of text appended to required input labels |
608+
609+
👉 Please note that selected components can be rendered as required by setting
610+
the `renderAsRequired` prop to `true`. This is useful when
611+
`--rui-FormField--required__label__color` is used to indicate the required state
612+
of input fields, but you want to bypass it for inputs like feature toggles.
613+
This applies to
614+
[CheckboxField](/components/CheckboxField/#styling-the-required-state),
615+
[Radio](/components/Radio/#styling-the-required-state),
616+
[SelectField](/components/SelectField/#styling-the-required-state),
617+
and [Toggle](/components/Toggle/#styling-the-required-state).
618+
602619
## Disabled State
603620

604621
By default, all disabled form fields are semi-transparent and change mouse

0 commit comments

Comments
 (0)