diff --git a/CHANGELOG.md b/CHANGELOG.md
index 38336ba4ba5..f83a0f8adea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@
- Fixed `EuiSuperDatePicker` to update `asyncInterval.isStopped` on a `isPaused` prop change. ([#2250](https://github.com/elastic/eui/pull/2250))
- Converted table, popover, buttons, pagination, outside click detector, focus trap, context menu, and panel to TypeScript ([#2212](https://github.com/elastic/eui/pull/2212))
+**Reverts**
+
+- Revert conversion of `EuiSwitch` to `button[role=switch]` and TypeScript ([#2255](https://github.com/elastic/eui/pull/2255))
+
## [`13.5.0`](https://github.com/elastic/eui/tree/v13.5.0)
- Fixed `logoCloudEnterprise`, `logoLogging`, and `logoSecurity` SVGs in `EuiIcon` to be center aligned ([#2246](https://github.com/elastic/eui/pull/2246))
diff --git a/src-docs/src/views/form_controls/switch.js b/src-docs/src/views/form_controls/switch.js
index f465980af56..2d8f061679c 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 = () => {
+ onChange = e => {
this.setState({
- checked: !this.state.checked,
+ checked: e.target.checked,
});
};
diff --git a/src/components/form/_variables.scss b/src/components/form/_variables.scss
index e8bc6ece33a..eae29dabd11 100644
--- a/src/components/form/_variables.scss
+++ b/src/components/form/_variables.scss
@@ -21,5 +21,4 @@ $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%);
-$euiSwitchOffColor: lightOrDarkTheme(transparentize($euiColorMediumShade, .8), transparentize($euiColorMediumShade, .3));
+$euiFormInputGroupLabelBackground: shadeOrTint($euiFormBackgroundDisabledColor, 0, 3%);
\ No newline at end of file
diff --git a/src/components/form/index.d.ts b/src/components/form/index.d.ts
index a31e554069b..366419d36f9 100644
--- a/src/components/form/index.d.ts
+++ b/src/components/form/index.d.ts
@@ -9,6 +9,7 @@ import { CommonProps } from '../common';
///
///
///
+///
///
import { FunctionComponent, FormHTMLAttributes, ReactNode } from 'react';
diff --git a/src/components/form/switch/__snapshots__/switch.test.js.snap b/src/components/form/switch/__snapshots__/switch.test.js.snap
new file mode 100644
index 00000000000..7d5d582e468
--- /dev/null
+++ b/src/components/form/switch/__snapshots__/switch.test.js.snap
@@ -0,0 +1,81 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EuiSwitch assigns automatically generated ID to label 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`EuiSwitch is rendered 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/components/form/switch/__snapshots__/switch.test.tsx.snap b/src/components/form/switch/__snapshots__/switch.test.tsx.snap
deleted file mode 100644
index b05767ccc4d..00000000000
--- a/src/components/form/switch/__snapshots__/switch.test.tsx.snap
+++ /dev/null
@@ -1,97 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`EuiSwitch assigns automatically generated ID to label 1`] = `
-
-
-
-
-`;
-
-exports[`EuiSwitch is rendered 1`] = `
-
-
-
-
-`;
diff --git a/src/components/form/switch/_switch.scss b/src/components/form/switch/_switch.scss
index a143b66ffee..cea8270aa94 100644
--- a/src/components/form/switch/_switch.scss
+++ b/src/components/form/switch/_switch.scss
@@ -4,62 +4,29 @@
min-height: $euiSwitchHeight;
.euiSwitch__label {
- cursor: pointer;
padding-left: $euiSizeS;
line-height: $euiSwitchHeight;
font-size: $euiFontSizeS;
vertical-align: middle;
}
- .euiSwitch__button {
- line-height: 0; // ensures button takes height of switch inside
-
- &: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;
- }
+ /**
+ * 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__icon { // move the icon right
- right: -$euiSizeS;
+ .euiSwitch__input:focus + .euiSwitch__body {
- &.euiSwitch__icon--checked {
- right: auto;
- left: -($euiSwitchWidth - ($euiSwitchThumbSize / 2));
- }
- }
+ .euiSwitch__thumb {
+ @include euiCustomControlFocused;
}
}
@@ -110,13 +77,64 @@
fill: $euiColorEmptyShade;
}
- &:hover .euiSwitch__button {
- &:not(:disabled) .euiSwitch__thumb {
- transform: scale(1.05);
+ /**
+ * 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);
+ }
}
+ }
- &: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
new file mode 100644
index 00000000000..caaea6c1bdc
--- /dev/null
+++ b/src/components/form/switch/index.d.ts
@@ -0,0 +1,15 @@
+import { CommonProps } from '../../common';
+
+import { FunctionComponent, InputHTMLAttributes, ReactNode } from 'react';
+
+declare module '@elastic/eui' {
+ /**
+ * @see './switch.js'
+ */
+ export type EuiSwitchProps = CommonProps &
+ InputHTMLAttributes & {
+ label?: ReactNode;
+ };
+
+ export const EuiSwitch: FunctionComponent;
+}
diff --git a/src/components/form/switch/index.js b/src/components/form/switch/index.js
new file mode 100644
index 00000000000..893cd7f7f6c
--- /dev/null
+++ b/src/components/form/switch/index.js
@@ -0,0 +1 @@
+export { EuiSwitch } from './switch';
diff --git a/src/components/form/switch/index.ts b/src/components/form/switch/index.ts
deleted file mode 100644
index 6c4ce9a8635..00000000000
--- a/src/components/form/switch/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { EuiSwitch, EuiSwitchEvent, EuiSwitchProps } from './switch';
diff --git a/src/components/form/switch/switch.js b/src/components/form/switch/switch.js
new file mode 100644
index 00000000000..ab16f30bcaa
--- /dev/null
+++ b/src/components/form/switch/switch.js
@@ -0,0 +1,85 @@
+import React, { Component } from 'react';
+
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+
+import makeId from '../../form/form_row/make_id';
+import { EuiIcon } from '../../icon';
+
+export class EuiSwitch extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ switchId: props.id || makeId(),
+ };
+ }
+
+ render() {
+ const {
+ label,
+ id,
+ name,
+ checked,
+ disabled,
+ compressed,
+ onChange,
+ className,
+ ...rest
+ } = this.props;
+
+ const { switchId } = this.state;
+
+ const classes = classNames(
+ 'euiSwitch',
+ {
+ 'euiSwitch--compressed': compressed,
+ },
+ className
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {label && (
+
+ )}
+
+ );
+ }
+}
+
+EuiSwitch.propTypes = {
+ name: PropTypes.string,
+ id: PropTypes.string,
+ label: PropTypes.node,
+ checked: PropTypes.bool,
+ onChange: PropTypes.func,
+ disabled: PropTypes.bool,
+ compressed: PropTypes.bool,
+};
diff --git a/src/components/form/switch/switch.test.tsx b/src/components/form/switch/switch.test.js
similarity index 65%
rename from src/components/form/switch/switch.test.tsx
rename to src/components/form/switch/switch.test.js
index a564df98ca1..50927c7fa6e 100644
--- a/src/components/form/switch/switch.test.tsx
+++ b/src/components/form/switch/switch.test.js
@@ -4,25 +4,17 @@ import { requiredProps } from '../../../test/required_props';
import { EuiSwitch } from './switch';
-const props = {
- checked: false,
- label: 'Label',
- onChange: () => {},
-};
-
jest.mock('../form_row/make_id', () => () => 'generated-id');
describe('EuiSwitch', () => {
test('is rendered', () => {
- const component = render(
-
- );
+ const component = render();
expect(component).toMatchSnapshot();
});
test('assigns automatically generated ID to label', () => {
- const component = render();
+ const component = render();
expect(component).toMatchSnapshot();
});
diff --git a/src/components/form/switch/switch.tsx b/src/components/form/switch/switch.tsx
deleted file mode 100644
index 334b7394bb6..00000000000
--- a/src/components/form/switch/switch.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import React, {
- ButtonHTMLAttributes,
- FunctionComponent,
- ReactNode,
- useState,
-} from 'react';
-import classNames from 'classnames';
-
-import { CommonProps, Omit } from '../../common';
-import makeId from '../../form/form_row/make_id';
-import { EuiIcon } from '../../icon';
-
-export type EuiSwitchEvent = React.BaseSyntheticEvent<
- React.MouseEvent,
- HTMLButtonElement,
- EventTarget & {
- checked: boolean;
- }
->;
-
-export type EuiSwitchProps = CommonProps &
- Omit, 'onChange'> & {
- label: ReactNode;
- checked: boolean;
- onChange: (event: EuiSwitchEvent) => void;
- disabled?: boolean;
- compressed?: boolean;
- };
-
-export const EuiSwitch: FunctionComponent = ({
- label,
- id,
- name,
- checked,
- disabled,
- compressed,
- onChange,
- className,
- ...rest
-}) => {
- const [switchId] = useState(id || makeId());
-
- const onClick = (e: React.MouseEvent) => {
- const event = (e as unknown) as EuiSwitchEvent;
- event.target.checked = !checked;
- onChange(event);
- };
-
- const classes = classNames(
- 'euiSwitch',
- {
- 'euiSwitch--compressed': compressed,
- },
- className
- );
-
- return (
-
-
-
-
-
- );
-};
diff --git a/src/global_styling/reset/_reset.scss b/src/global_styling/reset/_reset.scss
index 26d7b809ea5..0824f6a834e 100644
--- a/src/global_styling/reset/_reset.scss
+++ b/src/global_styling/reset/_reset.scss
@@ -71,11 +71,6 @@ body {
*:focus {
outline: none;
-
- // sass-lint:disable no-vendor-prefixes
- &::-moz-focus-inner {
- border: none;
- }
}
a {
@@ -141,4 +136,4 @@ hr {
fieldset {
min-inline-size: auto;
-}
+}
\ No newline at end of file