Skip to content

Commit

Permalink
fixup! Feat(web-react): Introduce UNSTABLE_Toggle component #DS-1346
Browse files Browse the repository at this point in the history
  • Loading branch information
curdaj committed Jul 16, 2024
1 parent 7cd70e1 commit d486030
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 18 deletions.
19 changes: 14 additions & 5 deletions packages/web-react/src/components/UNSTABLE_Toggle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ import { UNSTABLE_Toggle } from '@lmc-eu/spirit-web-react/components';
<UNSTABLE_Toggle id="toggle-default" label="Toggle Label" />;
```

## 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
<UNSTABLE_Toggle id="toggle-indicators" label="Toggle Label" hasIndicators />
```

## Required

Add the `isRequired` prop to mark it as required.
Expand Down Expand Up @@ -76,16 +84,17 @@ On top of adding the `isDisabled` props to disable Toggle.
| Name | Type | Default | Required | Description |
| ----------------- | ---------------------------------------------- | ------- | -------- | ------------------------------ |
| `id` | string | - || Input and label identification |
| `isDisabled` | boolean | - || Whether is toggle disabled |
| `isChecked` | boolean | - || Whether is toggle checked |
| `isLabelHidden` | boolean | - || Whether is label hidden |
| `isFluid` | boolean | - || Whether is toggle fluid |
| `isDisabled` | boolean | `false` || Whether is toggle disabled |
| `isChecked` | boolean | `false` || Whether is toggle checked |
| `isLabelHidden` | boolean | `false` || Whether is label hidden |
| `isFluid` | boolean | `false` || Whether is toggle fluid |
| `hasIndicators` | boolean | `false` || Whether has visual indicators |
| `label` | string | - || Label text |
| `helperText` | string | - || Helper text |
| `ref` | `ForwardedRef<HTMLInputElement>` | - || Input element reference |
| `onChange` | (event: ChangeEvent<HTMLInputElement>) => void | - || Change event handler |
| `validationState` | [Validation dictionary][dictionary-validation] | - || Type of validation state |
| `validationText` | string[] | - || Validation text |
| `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]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import classNames from 'classnames';
import React, { ForwardedRef, forwardRef } from 'react';
import { useStyleProps } from '../../hooks';
import { SpiritToggleProps } from '../../types/toggle';
import { SpiritToggleProps } from '../../types';
import { HelperText, useAriaIds, ValidationText } from '../Field';
import { useToggleStyleProps } from './useToggleStyleProps';

Expand Down Expand Up @@ -39,10 +39,22 @@ const _UNSTABLE_Toggle = (props: SpiritToggleProps, ref: ForwardedRef<HTMLInputE
registerAria={register}
helperText={helperText}
/>
{validationState && (
{validationState && Array.isArray(validationText) && (
<ul className={classProps.validationText} id={`${id}-validation-text`}>
{validationText.map((text, index) => (
<ValidationText
key={`${index + 1}-${id}__validationText`}
validationText={text}
registerAria={register}
elementType="li"
/>
))}
</ul>
)}
{validationState && !Array.isArray(validationText) && (
<ValidationText
className={classProps.validationText}
id={`${id}__helperText`}
id={`${id}__validationText`}
validationText={validationText}
registerAria={register}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,30 @@ describe('UNSTABLE_Toggle', () => {
it('should have correct className', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" />);

expect(screen.getByLabelText('Toggle Label').parentElement).toHaveClass('UNSTABLE_Toggle');
expect(screen.getByRole('checkbox').parentElement).toHaveClass('UNSTABLE_Toggle');
});

it('should have label classname', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" />);

expect(screen.getByText('Toggle Label')).toHaveClass('UNSTABLE_Toggle__label');
expect(screen.getByText('Toggle Label')).toContainHTML('label');
});

it('should have label with required classname', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" isRequired />);

expect(screen.getByText('Toggle Label')).toHaveClass('UNSTABLE_Toggle__label');
expect(screen.getByText('Toggle Label')).toHaveClass('UNSTABLE_Toggle__label--required');
});

it('should have hidden classname', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" isLabelHidden />);

const label = screen.getByLabelText('Toggle Label').parentElement;
const label = screen.getByText('Toggle Label');

expect(label).toHaveClass('UNSTABLE_Toggle');
expect(label).toHaveClass('UNSTABLE_Toggle--hiddenLabel');
expect(label).toHaveClass('UNSTABLE_Toggle__label');
expect(label).toHaveClass('UNSTABLE_Toggle__label--hidden');
});

it('should have input classname', () => {
Expand Down Expand Up @@ -70,6 +78,15 @@ describe('UNSTABLE_Toggle', () => {
it('should have correct classname if fluid', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" isFluid />);

expect(screen.getByLabelText('Toggle Label').parentElement).toHaveClass('UNSTABLE_Toggle UNSTABLE_Toggle--fluid');
expect(screen.getByRole('checkbox').parentElement).toHaveClass('UNSTABLE_Toggle UNSTABLE_Toggle--fluid');
});

it('should have indicators classname', () => {
render(<UNSTABLE_Toggle id="test-toggle" label="Toggle Label" hasIndicators />);

const checkbox = screen.getByRole('checkbox');

expect(checkbox).toHaveClass('UNSTABLE_Toggle__input');
expect(checkbox).toHaveClass('UNSTABLE_Toggle__input--indicators');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('useToggleStyleProps', () => {
const props = { id: 'toggle', label: 'text', isLabelHidden: true } as SpiritToggleProps;
const { result } = renderHook(() => useToggleStyleProps(props));

expect(result.current.classProps.root).toBe('UNSTABLE_Toggle UNSTABLE_Toggle--hiddenLabel');
expect(result.current.classProps.label).toBe('UNSTABLE_Toggle__label UNSTABLE_Toggle__label--hidden');
});

it('should return disabled', () => {
Expand All @@ -38,4 +38,25 @@ describe('useToggleStyleProps', () => {

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');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { UNSTABLE_Toggle } from '../index';

const ToggleDefault = () => (
<>
<UNSTABLE_Toggle id="toggle-indicators" label="Toggle Label" hasIndicators />
<UNSTABLE_Toggle id="toggle-indicators-checked" label="Toggle Label" isChecked hasIndicators />
</>
);

export default ToggleDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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';

Expand All @@ -14,6 +15,9 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<DocsSection title="Default" stackAlignment="stretch">
<ToggleDefault />
</DocsSection>
<DocsSection title="Indicators" stackAlignment="stretch">
<ToggleIndicators />
</DocsSection>
<DocsSection title="Required" stackAlignment="stretch">
<ToggleRequired />
</DocsSection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ export function useToggleStyleProps(props: SpiritToggleProps): ToggleStyles<Spir
const {
isRequired = false,
isFluid = false,
isDisabled,
isDisabled = false,
isLabelHidden = false,
validationState,
hasIndicators,
...restProps
} = props;

Expand All @@ -33,16 +34,20 @@ export function useToggleStyleProps(props: SpiritToggleProps): ToggleStyles<Spir
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, {
[toggleHiddenLabelClass]: isLabelHidden,
[toggleFluidClass]: isFluid,
[toggleDisabledClass]: isDisabled,
[toggleValidationClass]: validationState,
});
const labelClass = classNames(toggleLabelClass, {
[toggleRequiredClass]: isRequired,
[toggleHiddenLabelClass]: isLabelHidden,
});
const inputClass = classNames(toggleInputClass, {
[toggleInputIndicatorsClass]: hasIndicators,
});

return {
Expand All @@ -51,9 +56,9 @@ export function useToggleStyleProps(props: SpiritToggleProps): ToggleStyles<Spir
label: labelClass,
text: toggleTextClass,
helperText: toggleHelperTextClass,
input: toggleInputClass,
input: inputClass,
validationText: toggleValidationTextClass,
},
props: restProps,
props: { ...restProps, validationState, isDisabled, isRequired },
};
}
1 change: 1 addition & 0 deletions packages/web-react/src/types/toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface ToggleProps
label: string;
validationText?: ValidationTextType;
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
hasIndicators?: boolean;
}

export interface SpiritToggleProps extends ToggleProps {}

0 comments on commit d486030

Please sign in to comment.