diff --git a/packages/web-react/scripts/entryPoints.js b/packages/web-react/scripts/entryPoints.js
index 49767f4e54..4cf53f2d76 100644
--- a/packages/web-react/scripts/entryPoints.js
+++ b/packages/web-react/scripts/entryPoints.js
@@ -52,6 +52,8 @@ const entryPoints = [
{ dirs: ['components', 'UNSTABLE_PartnerLogo'] },
{ dirs: ['components', 'UNSTABLE_ProductLogo'] },
{ dirs: ['components', 'UNSTABLE_Slider'] },
+ { dirs: ['components', 'UNSTABLE_Toggle'] },
+ { dirs: ['components', 'UNSTABLE_Truncate'] },
{ dirs: ['components', 'VisuallyHidden'] },
];
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/README.md b/packages/web-react/src/components/UNSTABLE_Toggle/README.md
new file mode 100644
index 0000000000..a7a2aa549c
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/README.md
@@ -0,0 +1,110 @@
+# UNSTABLE Toggle
+
+> ⚠️ This component is UNSTABLE. It may significantly change at any point in the future.
+> Please use it with caution.
+
+Toggle is a form control that allows users to switch between two states.
+
+## Basic Usage
+
+The Toggle component implements the HTML [checkbox input][mdn-checkbox] element. It uses
+the native input element and styles it to look like a toggle switch.
+
+```jsx
+import { UNSTABLE_Toggle } from '@lmc-eu/spirit-web-react/components';
+
+;
+```
+
+## Indicators
+
+If you need to indicate the state of the toggle, you can add the `hasIndicators` prop. This will add a visual indicators to the toggle switch.
+
+```jsx
+
+```
+
+## Required
+
+Add the `isRequired` prop to mark it as required.
+
+```jsx
+
+```
+
+## Hidden Label
+
+```jsx
+
+```
+
+## Fluid
+
+```jsx
+
+```
+
+## Helper Text
+
+```jsx
+
+```
+
+## Validation States
+
+Validation states can be presented by prop `validationState`. See Validation state [dictionary][dictionary-validation].
+
+```jsx
+
+
+
+```
+
+## Disabled State
+
+You can add `isDisabled` prop to disable Toggle.
+
+```jsx
+
+```
+
+## API
+
+| Name | Type | Default | Required | Description |
+| ----------------- | ---------------------------------------------- | ------- | -------- | ---------------------------------------------------- |
+| `autoComplete` | `string` | - | ✕ | [Automated assistance in filling][autocomplete-attr] |
+| `hasIndicators` | boolean | `false` | ✕ | Whether has visual indicators |
+| `helperText` | string | - | ✕ | Helper text |
+| `id` | string | - | ✓ | Input and label identification |
+| `isChecked` | boolean | `false` | ✕ | Whether is toggle checked |
+| `isDisabled` | boolean | `false` | ✕ | Whether is toggle disabled |
+| `isFluid` | boolean | `false` | ✕ | Whether is toggle fluid |
+| `isLabelHidden` | boolean | `false` | ✕ | Whether is label hidden |
+| `label` | string | - | ✓ | Label text |
+| `name` | string | - | ✕ | Input name |
+| `onChange` | (event: ChangeEvent) => void | - | ✕ | Change event handler |
+| `ref` | `ForwardedRef` | - | ✕ | Input element reference |
+| `validationState` | [Validation dictionary][dictionary-validation] | - | ✕ | Type of validation state |
+| `validationText` | `string` \| `string[]` | - | ✕ | Validation text |
+
+The components accept [additional attributes][readme-additional-attributes].
+If you need more control over the styling of a component, you can use [style props][readme-style-props]
+and [escape hatches][readme-escape-hatches].
+
+[autocomplete-attr]: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
+[dictionary-validation]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#validation
+[mdn-checkbox]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox
+[readme-additional-attributes]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#additional-attributes
+[readme-escape-hatches]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#escape-hatches
+[readme-style-props]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#style-props
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/UNSTABLE_Toggle.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/UNSTABLE_Toggle.tsx
new file mode 100644
index 0000000000..f465f803b7
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/UNSTABLE_Toggle.tsx
@@ -0,0 +1,75 @@
+import classNames from 'classnames';
+import React, { ForwardedRef, forwardRef, useState } from 'react';
+import { useStyleProps } from '../../hooks';
+import { SpiritToggleProps } from '../../types';
+import { HelperText, useAriaIds, ValidationText } from '../Field';
+import { useToggleStyleProps } from './useToggleStyleProps';
+
+/* We need an exception for components exported with forwardRef */
+/* eslint no-underscore-dangle: ['error', { allow: ['_UNSTABLE_Toggle'] }] */
+/* eslint-disable-next-line camelcase */
+const _UNSTABLE_Toggle = (props: SpiritToggleProps, ref: ForwardedRef) => {
+ const { classProps, props: modifiedProps } = useToggleStyleProps(props);
+ const {
+ 'aria-describedby': ariaDescribedBy = '',
+ id,
+ isDisabled,
+ isChecked = false,
+ isRequired,
+ label,
+ helperText,
+ onChange = () => {},
+ validationState,
+ validationText,
+ ...restProps
+ } = modifiedProps;
+
+ const { styleProps, props: otherProps } = useStyleProps(restProps);
+
+ const [ids, register] = useAriaIds(ariaDescribedBy);
+ const [checked, setChecked] = useState(isChecked);
+
+ const handleOnChange = (event: React.ChangeEvent) => {
+ setChecked(event.target.checked);
+ onChange(event);
+ };
+
+ return (
+
+ );
+};
+
+export const UNSTABLE_Toggle = forwardRef(_UNSTABLE_Toggle);
+
+export default UNSTABLE_Toggle;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/UNSTABLE_Toggle.test.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/UNSTABLE_Toggle.test.tsx
new file mode 100644
index 0000000000..6d1e057e66
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/UNSTABLE_Toggle.test.tsx
@@ -0,0 +1,111 @@
+import '@testing-library/jest-dom';
+import { fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { classNamePrefixProviderTest } from '../../../../tests/providerTests/classNamePrefixProviderTest';
+import { validationStatePropsTest } from '../../../../tests/providerTests/dictionaryPropsTest';
+import { requiredPropsTest } from '../../../../tests/providerTests/requiredPropsTest';
+import { restPropsTest } from '../../../../tests/providerTests/restPropsTest';
+import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+describe('UNSTABLE_Toggle', () => {
+ classNamePrefixProviderTest(UNSTABLE_Toggle, 'UNSTABLE_Toggle');
+
+ stylePropsTest(UNSTABLE_Toggle);
+
+ restPropsTest(UNSTABLE_Toggle, 'input');
+
+ validationStatePropsTest(UNSTABLE_Toggle, 'UNSTABLE_Toggle--');
+
+ requiredPropsTest(UNSTABLE_Toggle, 'checkbox', 'id', 'example-id');
+
+ it('should have correct className', () => {
+ render();
+
+ expect(screen.getByRole('checkbox').parentElement).toHaveClass('UNSTABLE_Toggle');
+ });
+
+ it('should have label classname', () => {
+ render();
+
+ const label = screen.getByText('Toggle Label');
+
+ expect(label).toHaveClass('UNSTABLE_Toggle__label');
+ expect(label).toContainHTML('label');
+ });
+
+ it('should have label with required classname', () => {
+ render();
+
+ const label = screen.getByText('Toggle Label');
+
+ expect(label).toHaveClass('UNSTABLE_Toggle__label');
+ expect(label).toHaveClass('UNSTABLE_Toggle__label--required');
+ });
+
+ it('should have hidden classname', () => {
+ render();
+
+ const label = screen.getByText('Toggle Label');
+
+ expect(label).toHaveClass('UNSTABLE_Toggle__label');
+ expect(label).toHaveClass('UNSTABLE_Toggle__label--hidden');
+ });
+
+ it('should have input classname', () => {
+ render();
+
+ expect(screen.getByRole('checkbox')).toHaveClass('UNSTABLE_Toggle__input');
+ });
+
+ it('should have helper text with correct classname', () => {
+ render();
+
+ const helperText = screen.getByText('Helper Text');
+
+ expect(helperText).toBeInTheDocument();
+ expect(helperText).toHaveClass('UNSTABLE_Toggle__helperText');
+ });
+
+ it('should have correct attribute when checked', () => {
+ render();
+
+ expect(screen.getByRole('checkbox')).toBeChecked();
+ });
+
+ it('should have correct attribute when disabled', () => {
+ render();
+
+ expect(screen.getByRole('checkbox')).toBeDisabled();
+ });
+
+ it('should have correct classname if fluid', () => {
+ render();
+
+ const checkbox = screen.getByRole('checkbox');
+
+ expect(checkbox.parentElement).toHaveClass('UNSTABLE_Toggle');
+ expect(checkbox.parentElement).toHaveClass('UNSTABLE_Toggle--fluid');
+ });
+
+ it('should have indicators classname', () => {
+ render();
+
+ const checkbox = screen.getByRole('checkbox');
+
+ expect(checkbox).toHaveClass('UNSTABLE_Toggle__input');
+ expect(checkbox).toHaveClass('UNSTABLE_Toggle__input--indicators');
+ });
+
+ it('should change the state of the checkbox when clicked', () => {
+ render();
+
+ const checkbox = screen.getByRole('checkbox');
+
+ expect(checkbox).not.toBeChecked();
+
+ fireEvent.click(checkbox);
+
+ expect(checkbox).toBeChecked();
+ });
+});
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/useToggleStyleProps.test.ts b/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/useToggleStyleProps.test.ts
new file mode 100644
index 0000000000..c2534ebb4b
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/__tests__/useToggleStyleProps.test.ts
@@ -0,0 +1,62 @@
+import { renderHook } from '@testing-library/react';
+import { ValidationStates } from '../../../constants';
+import { SpiritToggleProps } from '../../../types';
+import { useToggleStyleProps } from '../useToggleStyleProps';
+
+describe('useToggleStyleProps', () => {
+ it('should return defaults', () => {
+ const props = { id: 'toggle', label: 'text' };
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps).toEqual({
+ root: 'UNSTABLE_Toggle',
+ text: 'UNSTABLE_Toggle__text',
+ input: 'UNSTABLE_Toggle__input',
+ label: 'UNSTABLE_Toggle__label',
+ helperText: 'UNSTABLE_Toggle__helperText',
+ validationText: 'UNSTABLE_Toggle__validationText',
+ });
+ });
+
+ it('should return hidden label', () => {
+ const props = { id: 'toggle', label: 'text', isLabelHidden: true } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.label).toBe('UNSTABLE_Toggle__label UNSTABLE_Toggle__label--hidden');
+ });
+
+ it('should return disabled', () => {
+ const props = { id: 'toggle', label: 'text', isDisabled: true } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.root).toBe('UNSTABLE_Toggle UNSTABLE_Toggle--disabled');
+ });
+
+ it.each([Object.values(ValidationStates)])('should return field with %s', (state) => {
+ const props = { validationState: state } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.root).toBe(`UNSTABLE_Toggle UNSTABLE_Toggle--${state}`);
+ });
+
+ it('should return fluid', () => {
+ const props = { id: 'toggle', label: 'text', isFluid: true } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.root).toBe('UNSTABLE_Toggle UNSTABLE_Toggle--fluid');
+ });
+
+ it('should return required', () => {
+ const props = { id: 'toggle', label: 'text', isRequired: true } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.label).toBe('UNSTABLE_Toggle__label UNSTABLE_Toggle__label--required');
+ });
+
+ it('should return input with indicators', () => {
+ const props = { id: 'toggle', label: 'text', hasIndicators: true } as SpiritToggleProps;
+ const { result } = renderHook(() => useToggleStyleProps(props));
+
+ expect(result.current.classProps.input).toBe('UNSTABLE_Toggle__input UNSTABLE_Toggle__input--indicators');
+ });
+});
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDefault.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDefault.tsx
new file mode 100644
index 0000000000..e4ee11f330
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDefault.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import { UNSTABLE_Toggle } from '..';
+
+const ToggleDefault = () => (
+ <>
+
+
+ >
+);
+
+export default ToggleDefault;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDisabled.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDisabled.tsx
new file mode 100644
index 0000000000..b1183a0143
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleDisabled.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleDisabled = () => (
+ <>
+
+
+
+ >
+);
+
+export default ToggleDisabled;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleFluid.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleFluid.tsx
new file mode 100644
index 0000000000..238d23e277
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleFluid.tsx
@@ -0,0 +1,6 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleFluid = () => ;
+
+export default ToggleFluid;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHelperText.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHelperText.tsx
new file mode 100644
index 0000000000..99c01cb62d
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHelperText.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleHelperText = () => (
+ <>
+
+
+ >
+);
+
+export default ToggleHelperText;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHiddenLabel.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHiddenLabel.tsx
new file mode 100644
index 0000000000..920eda882c
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleHiddenLabel.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleHiddenLabel = () => (
+
+);
+
+export default ToggleHiddenLabel;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleIndicators.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleIndicators.tsx
new file mode 100644
index 0000000000..5a3be49d6c
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleIndicators.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleIndicators = () => (
+ <>
+
+
+ >
+);
+
+export default ToggleIndicators;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleRequired.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleRequired.tsx
new file mode 100644
index 0000000000..704a94902b
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleRequired.tsx
@@ -0,0 +1,6 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleRequired = () => ;
+
+export default ToggleRequired;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleValidation.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleValidation.tsx
new file mode 100644
index 0000000000..f40637813a
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/ToggleValidation.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const ToggleValidation = () => (
+ <>
+
+
+
+
+ >
+);
+
+export default ToggleValidation;
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/demo/index.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/demo/index.tsx
new file mode 100644
index 0000000000..171510741f
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/demo/index.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import DocsSection from '../../../../docs/DocsSections';
+import ToggleDefault from './ToggleDefault';
+import ToggleDisabled from './ToggleDisabled';
+import ToggleFluid from './ToggleFluid';
+import ToggleHelperText from './ToggleHelperText';
+import ToggleHiddenLabel from './ToggleHiddenLabel';
+import ToggleIndicators from './ToggleIndicators';
+import ToggleRequired from './ToggleRequired';
+import ToggleValidation from './ToggleValidation';
+
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+);
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/index.html b/packages/web-react/src/components/UNSTABLE_Toggle/index.html
new file mode 100644
index 0000000000..8ddd1b2783
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/index.html
@@ -0,0 +1 @@
+{{> web-react/demo }}
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/index.ts b/packages/web-react/src/components/UNSTABLE_Toggle/index.ts
new file mode 100644
index 0000000000..9da6010143
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/index.ts
@@ -0,0 +1,3 @@
+export * from './UNSTABLE_Toggle';
+export * from './useToggleStyleProps';
+export { default as UNSTABLE_Toggle } from './UNSTABLE_Toggle';
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/stories/UNSTABLE_Toggle.stories.tsx b/packages/web-react/src/components/UNSTABLE_Toggle/stories/UNSTABLE_Toggle.stories.tsx
new file mode 100644
index 0000000000..d3a6d44d52
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/stories/UNSTABLE_Toggle.stories.tsx
@@ -0,0 +1,44 @@
+import { Markdown } from '@storybook/blocks';
+import type { Meta, StoryObj } from '@storybook/react';
+import React from 'react';
+import { ValidationStates } from '../../../constants';
+import ReadMe from '../README.md';
+import UNSTABLE_Toggle from '../UNSTABLE_Toggle';
+
+const meta: Meta = {
+ title: 'Experimental/UNSTABLE_Toggle',
+ component: UNSTABLE_Toggle,
+ parameters: {
+ docs: {
+ page: () => {ReadMe},
+ },
+ },
+ argTypes: {
+ validationState: {
+ control: 'select',
+ options: [...Object.values(ValidationStates), undefined],
+ table: {
+ defaultValue: { summary: undefined },
+ },
+ },
+ },
+ args: {
+ hasIndicators: false,
+ helperText: '',
+ id: 'toggle',
+ isRequired: false,
+ isDisabled: false,
+ isFluid: false,
+ isChecked: false,
+ label: 'Toggle Label',
+ validationState: undefined,
+ validationText: '',
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {
+ name: 'UNSTABLE_Toggle',
+};
diff --git a/packages/web-react/src/components/UNSTABLE_Toggle/useToggleStyleProps.ts b/packages/web-react/src/components/UNSTABLE_Toggle/useToggleStyleProps.ts
new file mode 100644
index 0000000000..aa174a6c15
--- /dev/null
+++ b/packages/web-react/src/components/UNSTABLE_Toggle/useToggleStyleProps.ts
@@ -0,0 +1,64 @@
+import classNames from 'classnames';
+import { useClassNamePrefix } from '../../hooks';
+import { SpiritToggleProps } from '../../types';
+
+export interface ToggleStyles {
+ classProps: {
+ root: string;
+ label: string;
+ text: string;
+ helperText: string;
+ input: string;
+ validationText: string;
+ };
+ props: T;
+}
+
+export function useToggleStyleProps(props: SpiritToggleProps): ToggleStyles {
+ const {
+ isRequired = false,
+ isFluid = false,
+ isDisabled = false,
+ isLabelHidden = false,
+ validationState,
+ hasIndicators = false,
+ ...restProps
+ } = props;
+
+ const toggleClass = useClassNamePrefix('UNSTABLE_Toggle');
+ const toggleFluidClass = `${toggleClass}--fluid`;
+ const toggleDisabledClass = `${toggleClass}--disabled`;
+ const toggleTextClass = `${toggleClass}__text`;
+ const toggleLabelClass = `${toggleClass}__label`;
+ const toggleHiddenLabelClass = `${toggleLabelClass}--hidden`;
+ const toggleValidationClass = `${toggleClass}--${validationState}`;
+ const toggleRequiredClass = `${toggleLabelClass}--required`;
+ const toggleInputClass = `${toggleClass}__input`;
+ const toggleInputIndicatorsClass = `${toggleInputClass}--indicators`;
+ const toggleHelperTextClass = `${toggleClass}__helperText`;
+ const toggleValidationTextClass = `${toggleClass}__validationText`;
+ const rootClass = classNames(toggleClass, {
+ [toggleFluidClass]: isFluid,
+ [toggleDisabledClass]: isDisabled,
+ [toggleValidationClass]: validationState,
+ });
+ const labelClass = classNames(toggleLabelClass, {
+ [toggleRequiredClass]: isRequired,
+ [toggleHiddenLabelClass]: isLabelHidden,
+ });
+ const inputClass = classNames(toggleInputClass, {
+ [toggleInputIndicatorsClass]: hasIndicators,
+ });
+
+ return {
+ classProps: {
+ root: rootClass,
+ label: labelClass,
+ text: toggleTextClass,
+ helperText: toggleHelperTextClass,
+ input: inputClass,
+ validationText: toggleValidationTextClass,
+ },
+ props: { ...restProps, validationState, isDisabled, isRequired },
+ };
+}
diff --git a/packages/web-react/src/components/index.ts b/packages/web-react/src/components/index.ts
index bf43e42351..f83c1a8bf1 100644
--- a/packages/web-react/src/components/index.ts
+++ b/packages/web-react/src/components/index.ts
@@ -37,4 +37,5 @@ export * from './UNSTABLE_Avatar';
export * from './UNSTABLE_Divider';
export * from './UNSTABLE_PartnerLogo';
export * from './UNSTABLE_ProductLogo';
+export * from './UNSTABLE_Toggle';
export * from './VisuallyHidden';
diff --git a/packages/web-react/src/types/index.ts b/packages/web-react/src/types/index.ts
index ba69f0b3d2..0ec027fd76 100644
--- a/packages/web-react/src/types/index.ts
+++ b/packages/web-react/src/types/index.ts
@@ -33,5 +33,6 @@ export * from './textArea';
export * from './textField';
export * from './textFieldBase';
export * from './toast';
+export * from './toggle';
export * from './tooltip';
export * from './visuallyHidden';
diff --git a/packages/web-react/src/types/toggle.ts b/packages/web-react/src/types/toggle.ts
new file mode 100644
index 0000000000..1fdaf9e7a6
--- /dev/null
+++ b/packages/web-react/src/types/toggle.ts
@@ -0,0 +1,35 @@
+import { ChangeEvent } from 'react';
+import { LabelProps } from './label';
+import {
+ ChildrenProps,
+ HelperTextProps,
+ InputBaseProps,
+ RequiredProps,
+ SpiritInputElementPropsWithRef,
+ StyleProps,
+ Validation,
+ ValidationTextType,
+} from './shared';
+
+export type ToggleElementBaseProps = SpiritInputElementPropsWithRef;
+
+export interface ToggleProps
+ extends ToggleElementBaseProps,
+ ChildrenProps,
+ LabelProps,
+ RequiredProps,
+ InputBaseProps,
+ HelperTextProps,
+ StyleProps,
+ Validation {
+ hasIndicators?: boolean;
+ isChecked?: boolean;
+ isDisabled?: boolean;
+ isFluid?: boolean;
+ isLabelHidden?: boolean;
+ label: string;
+ onChange?: (event: ChangeEvent) => void;
+ validationText?: ValidationTextType;
+}
+
+export interface SpiritToggleProps extends ToggleProps {}
diff --git a/tests/e2e/demo-homepages.spec.ts-snapshots/web-react-chromium-linux.png b/tests/e2e/demo-homepages.spec.ts-snapshots/web-react-chromium-linux.png
index 8b405c1c33..bc6c0eaa70 100644
Binary files a/tests/e2e/demo-homepages.spec.ts-snapshots/web-react-chromium-linux.png and b/tests/e2e/demo-homepages.spec.ts-snapshots/web-react-chromium-linux.png differ