Skip to content

Commit

Permalink
fixup! fixup! fixup! Allow check fields and selectable fields to rend…
Browse files Browse the repository at this point in the history
…er as required #487
  • Loading branch information
adamkudrna committed Jan 22, 2025
1 parent 1fbe84d commit 2758996
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 89 deletions.
32 changes: 15 additions & 17 deletions src/components/CheckboxField/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,18 +205,23 @@ React.createElement(() => {
});
```

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

For this case, there is the `renderAsRequired` prop:
All form fields in React UI can be
[styled](/docs/customize/theming/forms/#required-state)
to indicate the required state.

However, you may find yourself in a misleading situation where a form field
is valid in both checked and unchecked states, for example to turn on or off a
feature. If your project uses the label color as the primary means to indicate
the required state of input fields and the usual asterisk `*` is omitted,
you may want to keep the label color consistent for both states.

For this edge case, there is the `renderAsRequired` prop:

```docoff-react-preview
React.createElement(() => {
const [optional, setOptional] = React.useState(false);
const [required, setRequired] = React.useState(false);
const [renderAsRequired, setRenderAsRequired] = React.useState(false);
return (
<React.Fragment>
Expand All @@ -236,16 +241,9 @@ React.createElement(() => {
onChange={() => setOptional(!optional)}
/>
<br />
<CheckboxField
checked={required}
label="This field is required and must be checked"
onChange={() => setRequired(!required)}
required
/>
<br />
<CheckboxField
checked={renderAsRequired}
label="Checked or unchecked, both states are valid"
label="This field is optional but looks like required"
onChange={() => setRenderAsRequired(!renderAsRequired)}
renderAsRequired
/>
Expand All @@ -255,8 +253,8 @@ React.createElement(() => {
});
```

It renders the field as required, but doesn't add the `required` attribute to
the actual input.
It renders the field as if it was required, but doesn't add the `required`
attribute to the actual input.

### Disabled State

Expand Down
95 changes: 69 additions & 26 deletions src/components/Radio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,41 +269,84 @@ React.createElement(() => {
})
```

However, you may find yourself in a situation where the input is not required
(i.e. making the input checked), but you also don't want to render the field as
optional because not choosing an option can be perfectly valid. For this case,
there is the `renderAsRequired` prop:
#### Styling the Required State

All form fields in React UI can be
[styled](/docs/customize/theming/forms/#required-state)
to indicate the required state.

However, you may find yourself in a misleading situation where a form field
is valid in both selected and unselected states, for example to turn on or off a
feature. If your project uses the label color as the primary means to indicate
the required state of input fields and the usual asterisk `*` is omitted,
you may want to keep the label color consistent for both states.

For this edge case, there is the `renderAsRequired` prop:

```docoff-react-preview
React.createElement(() => {
const [fruit, setFruit] = React.useState('apple');
return (
<Radio
label="Your favourite fruit"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
renderAsRequired
/>
<React.Fragment>
<style>
{`
.example--themed-form-fields {
--rui-FormField__label__color: var(--rui-color-text-secondary);
--rui-FormField--required__label__color: var(--rui-color-text-primary);
--rui-FormField--required__sign: '';
}
`}
</style>
<div class="example--themed-form-fields">
<Radio
label="This field is optional"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
/>
<br />
<br />
<Radio
label="This field is optional but looks like required"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
renderAsRequired
/>
</div>
</React.Fragment>
);
})
```

It renders the field as required, but doesn't add the `required` attribute to
the actual input.
It renders the field as if it was required, but doesn't add the `required`
attribute to the actual input.

### Disabled State

Expand Down
4 changes: 4 additions & 0 deletions src/components/Radio/Radio.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
@include foundation.label-required();
}

.isRootRequired .optionLabel {
@include foundation.label-required($show-require-sign: false);
}

// States
.isRootStateInvalid {
@include variants.validation(invalid);
Expand Down
95 changes: 69 additions & 26 deletions src/components/SelectField/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -624,41 +624,84 @@ React.createElement(() => {
});
```

However, you may find yourself in a situation where the input is not required
(i.e. selecting an option), but you also don't want to render the field as
optional because the unselected state can be perfectly valid. For this case,
there is the `renderAsRequired` prop:
#### Styling the Required State

All form fields in React UI can be
[styled](/docs/customize/theming/forms/#required-state)
to indicate the required state.

However, you may find yourself in a misleading situation where a form field
is valid in both selected and unselected states, for example to turn on or off a
feature. If your project uses the label color as the primary means to indicate
the required state of input fields and the usual asterisk `*` is omitted,
you may want to keep the label color consistent for both states.

For this edge case, there is the `renderAsRequired` prop:

```docoff-react-preview
React.createElement(() => {
const [fruit, setFruit] = React.useState('apple');
return (
<SelectField
label="Your favourite fruit"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
renderAsRequired
/>
<React.Fragment>
<style>
{`
.example--themed-form-fields {
--rui-FormField__label__color: var(--rui-color-text-secondary);
--rui-FormField--required__label__color: var(--rui-color-text-primary);
--rui-FormField--required__sign: '';
}
`}
</style>
<div class="example--themed-form-fields">
<SelectField
label="This field is optional"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
/>
<br />
<br />
<SelectField
label="This field is optional but looks like required"
onChange={(e) => setFruit(e.target.value)}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Grapefruit',
value: 'grapefruit',
},
]}
value={fruit}
renderAsRequired
/>
</div>
</React.Fragment>
);
});
```

It renders the field as required, but doesn't add the `required` attribute to
the actual input.
It renders the field as if it was required, but doesn't add the `required`
attribute to the actual input.

### Disabled State

Expand Down
55 changes: 42 additions & 13 deletions src/components/Toggle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,27 +181,56 @@ React.createElement(() => {
});
```

However, you may find yourself in a situation where the input is not required
(i.e. turning the toggle on), but you also don't want to render the field as
optional because the unchecked state can be perfectly valid. For this case,
there is the `renderAsRequired` prop:
#### Styling the Required State

All form fields in React UI can be
[styled](/docs/customize/theming/forms/#required-state)
to indicate the required state.

However, you may find yourself in a misleading situation where a form field
is valid in both checked and unchecked states, for example to turn on or off a
feature. If your project uses the label color as the primary means to indicate
the required state of input fields and the usual asterisk `*` is omitted,
you may want to keep the label color consistent for both states.

For this edge case, there is the `renderAsRequired` prop:

```docoff-react-preview
React.createElement(() => {
const [studioQuality, setStudioQuality] = React.useState(true);
const [optional, setOptional] = React.useState(false);
const [renderAsRequired, setRenderAsRequired] = React.useState(false);
return (
<Toggle
checked={studioQuality}
label="Listen in studio quality"
onChange={() => setStudioQuality(!studioQuality)}
renderAsRequired
/>
<React.Fragment>
<style>
{`
.example--themed-form-fields {
--rui-FormField__label__color: var(--rui-color-text-secondary);
--rui-FormField--required__label__color: var(--rui-color-text-primary);
--rui-FormField--required__sign: '';
}
`}
</style>
<div class="example--themed-form-fields">
<Toggle
checked={optional}
label="This field is optional"
onChange={() => setOptional(!optional)}
/>
<br />
<Toggle
checked={renderAsRequired}
label="This field is optional but looks like required"
onChange={() => setRenderAsRequired(!renderAsRequired)}
renderAsRequired
/>
</div>
</React.Fragment>
);
});
```

It renders the field as required, but doesn't add the `required` attribute to
the actual input.
It renders the field as if it was required, but doesn't add the `required`
attribute to the actual input.

### Disabled State

Expand Down
23 changes: 20 additions & 3 deletions src/docs/customize/theming/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ The following theme options define basic appearance of all form fields.
| `--rui-FormField__help-text__font-size` | Help text font size |
| `--rui-FormField__help-text__font-style` | Help text font style, e.g. italic |
| `--rui-FormField__help-text__color` | Help text color |
| `--rui-FormField--required__label__color` | Color of required input labels |
| `--rui-FormField--required__sign` | Text appended to required input labels |
| `--rui-FormField--required__sign__color` | Color of text appended to required input labels |

## Horizontal Layout

Expand Down Expand Up @@ -599,6 +596,26 @@ React.createElement(() => {
});
```

## Required State

Theming options for required fields are shared by all form components.

| Custom Property | Description |
|------------------------------------------------------|--------------------------------------------------------------|
| `--rui-FormField--required__label__color` | Color of required input labels |
| `--rui-FormField--required__sign` | Text appended to required input labels |
| `--rui-FormField--required__sign__color` | Color of text appended to required input labels |

👉 Please note that selected components can be rendered as required by setting
the `renderAsRequired` prop to `true`. This is useful when
`--rui-FormField--required__label__color` is used to indicate the required state
of input fields, but you want to bypass it for inputs like feature toggles.
This applies to
[CheckboxField](/components/CheckboxField/#styling-the-required-state),
[Radio](/components/Radio/#styling-the-required-state),
[SelectField](/components/SelectField/#styling-the-required-state),
and [Toggle](/components/Toggle/#styling-the-required-state).

## Disabled State

By default, all disabled form fields are semi-transparent and change mouse
Expand Down
Loading

0 comments on commit 2758996

Please sign in to comment.