From 76e58de80f0ef5d2e7ebeaf7b7b178bc327deda6 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Wed, 14 Aug 2019 11:17:55 +0300 Subject: [PATCH] Aligning switch semantics with aria role (#2193) * Removes FF's focus ring to match other browsers * Aligning switch semantics with aria role --- CHANGELOG.md | 3 +- src-docs/src/views/form_controls/switch.js | 4 +- src/components/form/_variables.scss | 3 +- .../switch/__snapshots__/switch.test.js.snap | 114 ++++++++-------- src/components/form/switch/_switch.scss | 122 ++++++++---------- src/components/form/switch/index.d.ts | 12 +- src/components/form/switch/switch.js | 49 +++---- src/global_styling/reset/_reset.scss | 7 +- 8 files changed, 160 insertions(+), 154 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b352718ccdb..d1ca4c54673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `13.3.0`. +- Fixed `EuiSwitch` semantics to align with aria roles ([#2193](https://github.com/elastic/eui/pull/2193)) +- Removed Firefox's focus ring to match other browsers ([#2193](https://github.com/elastic/eui/pull/2193)) ## [`13.3.0`](https://github.com/elastic/eui/tree/v13.3.0) diff --git a/src-docs/src/views/form_controls/switch.js b/src-docs/src/views/form_controls/switch.js index 2d8f061679c..f465980af56 100644 --- a/src-docs/src/views/form_controls/switch.js +++ b/src-docs/src/views/form_controls/switch.js @@ -11,9 +11,9 @@ export default class extends Component { }; } - onChange = e => { + onChange = () => { this.setState({ - checked: e.target.checked, + checked: !this.state.checked, }); }; diff --git a/src/components/form/_variables.scss b/src/components/form/_variables.scss index eae29dabd11..e8bc6ece33a 100644 --- a/src/components/form/_variables.scss +++ b/src/components/form/_variables.scss @@ -21,4 +21,5 @@ $euiFormBorderDisabledColor: transparentize($euiColorFullShade, .92) !default; $euiFormCustomControlDisabledIconColor: shadeOrTint($euiColorMediumShade, 38%, 48.5%) !default; // exact 508c foreground for $euiColorLightShade $euiFormControlDisabledColor: $euiColorMediumShade !default; $euiFormControlBoxShadow: 0 1px 1px -1px transparentize($euiShadowColor, .8), 0 3px 2px -2px transparentize($euiShadowColor, .8); -$euiFormInputGroupLabelBackground: shadeOrTint($euiFormBackgroundDisabledColor, 0, 3%); \ No newline at end of file +$euiFormInputGroupLabelBackground: shadeOrTint($euiFormBackgroundDisabledColor, 0, 3%); +$euiSwitchOffColor: lightOrDarkTheme(transparentize($euiColorMediumShade, .8), transparentize($euiColorMediumShade, .3)); diff --git a/src/components/form/switch/__snapshots__/switch.test.js.snap b/src/components/form/switch/__snapshots__/switch.test.js.snap index 7d5d582e468..642f2dce792 100644 --- a/src/components/form/switch/__snapshots__/switch.test.js.snap +++ b/src/components/form/switch/__snapshots__/switch.test.js.snap @@ -4,38 +4,43 @@ exports[`EuiSwitch assigns automatically generated ID to label 1`] = `
- - - - - + + + + - + +
`; @@ -43,39 +48,44 @@ exports[`EuiSwitch is rendered 1`] = `
- - - - - + + + + - + +
`; diff --git a/src/components/form/switch/_switch.scss b/src/components/form/switch/_switch.scss index cea8270aa94..a143b66ffee 100644 --- a/src/components/form/switch/_switch.scss +++ b/src/components/form/switch/_switch.scss @@ -4,30 +4,63 @@ min-height: $euiSwitchHeight; .euiSwitch__label { + cursor: pointer; padding-left: $euiSizeS; line-height: $euiSwitchHeight; font-size: $euiFontSizeS; vertical-align: middle; } - /** - * 1. The input is "hidden" but still focusable. - * 2. Make sure it's still hidden when [disabled]. - */ - .euiSwitch__input, - .euiSwitch__input[disabled] /* 2 */ { - position: absolute; - opacity: 0; /* 1 */ - width: 100%; - height: 100%; - cursor: pointer; - } - - .euiSwitch__input:focus + .euiSwitch__body { + .euiSwitch__button { + line-height: 0; // ensures button takes height of switch inside - .euiSwitch__thumb { + &:focus .euiSwitch__thumb { @include euiCustomControlFocused; } + + &:disabled { + &:hover, + ~ .euiSwitch__label:hover { + cursor: not-allowed; + } + + .euiSwitch__body { + background-color: $euiSwitchOffColor; + } + + .euiSwitch__thumb { + @include euiCustomControlDisabled; + background-color: $euiSwitchOffColor; + } + + .euiSwitch__icon { + fill: $euiFormCustomControlDisabledIconColor; + } + + + .euiSwitch__label { + color: $euiFormControlDisabledColor; + } + } + + &[aria-checked='false'] { + .euiSwitch__body { + background-color: $euiSwitchOffColor; + } + + // When input is not checked, we shift around the positioning of the thumb and the icon + .euiSwitch__thumb { // move the thumb left + left: 0; + } + + .euiSwitch__icon { // move the icon right + right: -$euiSizeS; + + &.euiSwitch__icon--checked { + right: auto; + left: -($euiSwitchWidth - ($euiSwitchThumbSize / 2)); + } + } + } } .euiSwitch__body { @@ -77,64 +110,13 @@ fill: $euiColorEmptyShade; } - /** - * The thumb is slightly scaled when in use, unless it's disabled. - */ - &:hover { - .euiSwitch__input:not(:disabled) ~ .euiSwitch__body { - .euiSwitch__thumb { - transform: scale(1.05); - } + &:hover .euiSwitch__button { + &:not(:disabled) .euiSwitch__thumb { + transform: scale(1.05); } - } - &:active { - .euiSwitch__thumb { + &:active .euiSwitch__thumb { transform: scale(.95); } } - - .euiSwitch__input:disabled:hover { - cursor: not-allowed; - } - - .euiSwitch__input:disabled ~ .euiSwitch__body, - .euiSwitch__input:checked:disabled ~ .euiSwitch__body { - background-color: lightOrDarkTheme(transparentize($euiColorMediumShade, .8), transparentize($euiColorMediumShade, .3)); - - .euiSwitch__thumb { - @include euiCustomControlDisabled; - background-color: lightOrDarkTheme(transparentize($euiColorMediumShade, .8), transparentize($euiColorMediumShade, .3)); - } - - .euiSwitch__icon { - fill: $euiFormCustomControlDisabledIconColor; - } - - + label { - color: $euiFormControlDisabledColor; - } - } - - .euiSwitch__input:not(:checked):not(:disabled) ~ .euiSwitch__body { - background-color: lightOrDarkTheme(transparentize($euiColorMediumShade, .8), transparentize($euiColorMediumShade, .3)); - } - - /** - * When input is not checked, we shift around the positioning of sibling/child selectors. - */ - .euiSwitch__input:not(:checked) ~ .euiSwitch__body { - .euiSwitch__thumb { - left: 0; - } - - .euiSwitch__icon { - right: -$euiSizeS; - - &.euiSwitch__icon--checked { - right: auto; - left: -($euiSwitchWidth - ($euiSwitchThumbSize / 2)); - } - } - } } diff --git a/src/components/form/switch/index.d.ts b/src/components/form/switch/index.d.ts index caaea6c1bdc..8bd9f11e8c4 100644 --- a/src/components/form/switch/index.d.ts +++ b/src/components/form/switch/index.d.ts @@ -1,14 +1,20 @@ import { CommonProps } from '../../common'; -import { FunctionComponent, InputHTMLAttributes, ReactNode } from 'react'; +import { FunctionComponent, ButtonHTMLAttributes, ReactNode } from 'react'; declare module '@elastic/eui' { /** * @see './switch.js' */ export type EuiSwitchProps = CommonProps & - InputHTMLAttributes & { - label?: ReactNode; + ButtonHTMLAttributes & { + label: ReactNode; + checked: boolean; + onChange: ( + event: React.FormEvent + ) => void; + disabled?: boolean; + compressed?: boolean; }; export const EuiSwitch: FunctionComponent; diff --git a/src/components/form/switch/switch.js b/src/components/form/switch/switch.js index ab16f30bcaa..3395b8a97be 100644 --- a/src/components/form/switch/switch.js +++ b/src/components/form/switch/switch.js @@ -15,6 +15,11 @@ export class EuiSwitch extends Component { }; } + onClick = e => { + e.target.checked = !this.props.checked; + this.props.onChange(e); + }; + render() { const { label, @@ -40,35 +45,31 @@ export class EuiSwitch extends Component { return (
- - - - - - + onClick={this.onClick} + {...rest}> + + + + - + + - + - {label && ( - - )} +
); } diff --git a/src/global_styling/reset/_reset.scss b/src/global_styling/reset/_reset.scss index 0824f6a834e..26d7b809ea5 100644 --- a/src/global_styling/reset/_reset.scss +++ b/src/global_styling/reset/_reset.scss @@ -71,6 +71,11 @@ body { *:focus { outline: none; + + // sass-lint:disable no-vendor-prefixes + &::-moz-focus-inner { + border: none; + } } a { @@ -136,4 +141,4 @@ hr { fieldset { min-inline-size: auto; -} \ No newline at end of file +}