Skip to content

Commit

Permalink
[WNMGDS-529] Error styling on radio button and checkbox options (#810)
Browse files Browse the repository at this point in the history
* Add styles for border color of check and radio

* Add error class to fieldset when errorMessage used

* Remove commented out line

* update disabled border - remove right to left

* Update choice test remove right to left

* update class for choice error

* add class to choice div when errored

* PR feedback - update className

* update html markup to match React

* update error border to not show on checked items

* update example

* comment out styling of choice error

* add error class to choice input to be consistent

* more organizing of choice styles

* remove divs from plain html examples

* Update packages/design-system-docs/src/pages/components/ChoiceList/checkbox-radio.example.html

Co-authored-by: Bernard <[email protected]>

* Update examples to not have error state and checked choices

* Reorder CSS classes, add some commments and remove some unnecessary code

* Disable error style

* PR feedback

* Fix last error message inconsistency

* Add back checkChild styling

Co-authored-by: Bernard <[email protected]>
Co-authored-by: bernardwang <[email protected]>
  • Loading branch information
3 people authored Sep 25, 2020
1 parent c500d77 commit 6db8583
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ReactDOM.render(
/>
<ChoiceList
choices={[
{ label: 'Choice 1', value: 'A', hint: 'Choice hint text', defaultChecked: true },
{ label: 'Choice 1', value: 'A', hint: 'Choice hint text' },
{
label: 'Choice 2',
value: 'B',
Expand Down Expand Up @@ -46,7 +46,6 @@ ReactDOM.render(
label: 'Choice 1',
requirementLabel: 'Choice hint text',
value: 'A',
defaultChecked: true,
},
{ label: 'Choice 2', value: 'B' },
{ label: 'Disabled choice 3', value: 'c', disabled: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,23 @@
Example error message
</span>
<input
class="ds-c-choice"
class="ds-c-choice ds-c-choice--error"
id="radio-1"
type="radio"
name="radio-choices"
value="radio-1"
checked
/>
<label for="radio-1">
<span>Choice 1</span>
<span class="ds-c-field__hint">Choice hint text</span>
</label>
<input class="ds-c-choice" id="radio-2" type="radio" name="radio-choices" value="radio-2" />
<input
class="ds-c-choice ds-c-choice--error"
id="radio-2"
type="radio"
name="radio-choices"
value="radio-2"
/>
<label for="radio-2"><span>Choice 2</span></label>
</fieldset>
<fieldset class="ds-c-fieldset">
Expand Down Expand Up @@ -85,19 +90,18 @@
<span class="ds-c-field__hint ds-c-field__hint--inverse">Helpful hint text</span>
<span class="ds-c-field__hint ds-u-color--error-light">Example error message</span>
<input
class="ds-c-choice ds-c-choice--inverse"
class="ds-c-choice ds-c-choice--inverse ds-c-choice--error"
id="inverse-1"
type="checkbox"
name="inverse-choices"
value="inverse-1"
checked
/>
<label for="inverse-1">
<span>Choice 1</span>
<span class="ds-c-field__hint ds-c-field__hint--inverse">Choice hint text</span>
</label>
<input
class="ds-c-choice ds-c-choice--inverse"
class="ds-c-choice ds-c-choice--inverse ds-c-choice--error"
id="inverse-2"
type="checkbox"
name="inverse-choices"
Expand All @@ -107,7 +111,7 @@
<span>Choice 2</span>
</label>
<input
class="ds-c-choice ds-c-choice--inverse"
class="ds-c-choice ds-c-choice--inverse ds-c-choice--error"
id="inverse-3"
type="checkbox"
name="inverse-choices"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<span>Error field</span>
<span class="ds-c-field__hint">Helpful hint text</span>
<span class="ds-c-field__hint ds-u-color--error" role="alert">
Error message example
Example error message
</span>
</label>
<input class="ds-c-field ds-c-field--error" id="input-error" name="error" type="text" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ describe('Choice', () => {
const input = wrapper.find('input');

expect(input.hasClass('ds-c-choice')).toBe(true);
expect(input.hasClass('ds-c-choice--right')).toBe(false);
});

it('applies small className to input', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export class ChoiceList extends React.PureComponent {
choiceProps.onChange = this.props.onChange;
choiceProps.size = this.props.size;
choiceProps.type = this.props.type;
choiceProps.inputClassName = classNames(choiceProps.inputClassName, {
'ds-c-choice--error': this.props.errorMessage,
});
choiceProps.disabled = choiceProps.disabled || this.props.disabled; // Individual choices can be disabled as well as the entire field
choiceProps.inputRef = (ref) => {
this.choiceRefs.push(ref);
Expand Down
233 changes: 118 additions & 115 deletions packages/design-system/src/styles/components/_Choice.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,111 +2,63 @@

$ds-c-inset-border-width: $spacer-half;

// Hide the default browser checkbox/radio button since we'll
// create our own custom version
// Order of the choice styles is important to ensure styles have the correct precedent
// normal < errored < checked < disabled < focused

.ds-c-choice {
// Hide the default browser checkbox/radio button
// We create our own custom version using '+ label::before'
left: -999em;
opacity: 0;
position: absolute;

// Checked children container
&__checkedChild {
border-left: $ds-c-inset-border-width solid $color-primary;
margin-bottom: $spacer-2;
margin-left: ($choice-size / 2) - ($ds-c-inset-border-width / 2);
padding: $spacer-2;

// Checked children container on dark background
&--inverse {
border-left-color: $color-white;
}

// Small input variant
&--small {
margin-left: $spacer-1;
}
// Choice label
+ label {
align-items: center;
cursor: pointer;
display: flex;
flex-wrap: wrap;
font-weight: $font-normal;
margin: $spacer-1 0;
max-width: $measure-base;
min-height: $choice-size;
padding-left: $choice-size + $spacer-1;
position: relative;
}
}

.ds-c-choice + label {
align-items: center;
cursor: pointer;
display: flex;
flex-wrap: wrap;
font-weight: $font-normal;
margin: $spacer-1 0;
max-width: $measure-base;
min-height: $choice-size;
padding-left: $choice-size + $spacer-1;
position: relative;
}

// Create a custom checkbox/radio button
.ds-c-choice + label::before {
background-color: $color-background;
border: $choice-border-width solid $choice-border-color;
box-sizing: border-box;
content: '\a0';
height: $choice-size;
left: 0;
line-height: $choice-size;
position: absolute;
text-indent: 0.15em;
top: 0;
width: $choice-size;
}

.ds-c-choice--inverse + label::before {
background-color: transparent;
border-color: $choice-border-color-inverse;
}

// Display an outline
.ds-c-choice:focus + label::before {
@if $ds-include-focus-styles {
border-color: $color-base;
border-width: 3px;
box-shadow: 0 0 0 3px $focus-color;
// Transparent outline for Windows High Contrast Mode
outline: 3px solid transparent;
outline-offset: 3px;
} @else {
box-shadow: 0 0 0 2px $color-background, 0 0 2px 4px $color-focus;
// Choice checkbox/radio button
+ label::before {
background-color: $color-background;
border: $choice-border-width solid $choice-border-color;
box-sizing: border-box;
content: '\a0';
height: $choice-size;
left: 0;
line-height: $choice-size;
position: absolute;
text-indent: 0.15em;
top: 0;
width: $choice-size;
}
}

@if $ds-include-focus-styles {
.ds-c-choice--small:focus + label::before {
border-width: 2px;
}
.ds-c-choice:checked:focus + label::before {
border-color: $color-primary-darker;
}
}
// Errored checkbox/radio button
// Currently only enabled in HC.gov DS
// &.ds-c-choice--error + label::before {
// border-color: $color-error;
// }

.ds-c-choice--inverse:focus + label::before {
@if $ds-include-focus-styles {
border-color: $choice-border-color-inverse;
box-shadow: 0 0 0 3px $focus-color-inverse;
} @else {
box-shadow: 0 0 0 2px $color-background-inverse, 0 0 2px 4px $color-focus-inverse;
// Checked checkbox/radio button
&:checked + label::before {
background-color: $choice-checked-background-color;
background-image: url('#{$image-path}/checkmark-white.svg');
background-position: 50%;
background-repeat: no-repeat;
background-size: $choice-size - $spacer-1;
border-color: $choice-checked-background-color;
}
}

// Display a checkmark
.ds-c-choice:checked + label::before {
background-color: $choice-checked-background-color;
background-image: url('#{$image-path}/checkmark-white.svg');
background-position: 50%;
background-repeat: no-repeat;
background-size: $choice-size - $spacer-1;
border-color: $choice-checked-background-color;
}

// Fade the checkbox and label
.ds-c-choice:disabled {
+ label {
// Disabled checkbox/radio button and label
&:disabled + label {
color: $color-muted;

&::before {
Expand All @@ -115,14 +67,57 @@ $ds-c-inset-border-width: $spacer-half;
cursor: not-allowed;
}
}

// Focused checkbox/radio button
&:focus + label::before {
@if $ds-include-focus-styles {
border-color: $color-base;
border-width: 3px;
box-shadow: 0 0 0 3px $focus-color;
// Transparent outline for Windows High Contrast Mode
outline: 3px solid transparent;
outline-offset: 3px;
} @else {
box-shadow: 0 0 0 2px $color-background, 0 0 2px 4px $color-focus;
}
}
}

.ds-c-choice--inverse:disabled {
+ label {
.ds-c-choice--inverse {
// Choice checkbox/radio button
+ label::before {
background-color: transparent;
border-color: $choice-border-color-inverse;
}

// Errored checkbox/radio button
// Currently only enabled in HC.gov DS
// &.ds-c-choice--error + label::before {
// border-color: $color-error-light;
// }

// Checked checkbox/radio button
&:checked + label::before {
border-color: $choice-checked-background-color;
}

// Disabled checkbox/radio button and label
&:disabled + label {
color: $color-muted-inverse;

&::before {
background-color: rgba($color-muted-inverse, 0.15);
border-color: $color-gray-light;
}
}

// Focused checkbox/radio button
&:focus + label::before {
@if $ds-include-focus-styles {
border-color: $choice-border-color-inverse;
box-shadow: 0 0 0 3px $focus-color-inverse;
} @else {
box-shadow: 0 0 0 2px $color-background-inverse, 0 0 2px 4px $color-focus-inverse;
}
}
}
Expand All @@ -132,24 +127,7 @@ $ds-c-inset-border-width: $spacer-half;
border-radius: 100%;
}

/*
Right-to-Left
*/

.ds-c-choice--right + label {
padding-left: 0;
padding-right: $choice-size + $spacer-1;

&::before {
left: auto;
right: 0;
}
}

/*
Size variants
*/

// Size variants
.ds-c-choice--small {
+ label {
min-height: $choice-size-small;
Expand All @@ -166,9 +144,34 @@ Size variants
&:checked + label::before {
background-size: $choice-size-small;
}
}

@if $ds-include-focus-styles {
.ds-c-choice--small:focus + label::before {
border-width: 2px;
}
.ds-c-choice:checked:focus + label::before {
border-color: $color-primary-darker;
}
}

// TODO: rename to .ds-c-choice__checked-child
/* stylelint-disable selector-class-pattern */

// Checked children container
.ds-c-choice__checkedChild {
border-left: $ds-c-inset-border-width solid $color-primary;
margin-bottom: $spacer-2;
margin-left: ($choice-size / 2) - ($ds-c-inset-border-width / 2);
padding: $spacer-2;

&--inverse {
border-left-color: $color-white;
}

&.ds-c-choice--right + label {
padding-left: 0;
padding-right: $choice-size-small + $spacer-1;
&--small {
margin-left: $spacer-1;
}
}

/* stylelint-enable selector-class-pattern */

0 comments on commit 6db8583

Please sign in to comment.