Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/components/Switch/Switch.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
import Switch from './Switch';

export default {
title: 'Switch',
component: Switch,
};

export const DefaultSwitch = () => (
<div>
<Switch onClick={action('Default Switch Toggled')} />
<Switch
onClick={action('Default Switch Toggled')}
checked
label="Checked Switch"
/>
<Switch
onClick={action('Disabled Switch Clicked')}
disabled
label="Disabled Switch"
/>
</div>
);

export const DiffTypeSwitch = () => (
<div>
<Switch
onClick={action('Primary Switch Toggled')}
label="Primary Switch"
switchType="primary"
checked
/>
<Switch
onClick={action('Secondary Switch Toggled')}
label="Secondary Switch"
switchType="secondary"
checked
/>
<Switch
onClick={action('Secondary Switch Toggled')}
label="Customed Color Switch"
switchType="secondary"
color="#FFA500"
checked
/>
</div>
);

export const DiffSizeSwitch = () => (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Switch
onClick={action('Medium-sized Switch Toggled')}
// label="Medium"
switchType="primary"
checked
/>
<Switch
onClick={action('Small-sized Switch Toggled')}
// label="Small"
switchType="primary"
switchSize="small"
checked
/>
</div>
);
110 changes: 110 additions & 0 deletions src/components/Switch/Switch.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React from 'react';

import { render, fireEvent } from '@testing-library/react';
import Switch, { patSwitchProps } from './Switch';

describe('Switch', () => {
it('should match snapshot', () => {
const { asFragment } = render(<Switch />);
expect(asFragment()).toMatchSnapshot();
});

it('should render default switch', () => {
const switchProps = {
onClick: jest.fn(),
};
const wrapper = render(<Switch {...switchProps} label="Default Switch" />);

// for switch-wrapper
const switch_wrapper = wrapper.queryByTestId(
'switch-wrapper'
) as HTMLElement;
expect(switch_wrapper).toBeInTheDocument();
expect(switch_wrapper.tagName).toBe('DIV');
expect(switch_wrapper).toHaveClass(
'switch-wrapper switch-default switch-medium'
);

// for input checkbox
const input_checkbox = wrapper.queryByTestId(
'switch-input'
) as HTMLInputElement;
expect(input_checkbox).toBeInTheDocument();
expect(input_checkbox.tagName).toBe('INPUT');
expect(input_checkbox.type).toBe('checkbox');
expect(input_checkbox).toBeEnabled();
expect(input_checkbox.checked).toBe(false);

// for track
const track = wrapper.queryByTestId('switch-track') as HTMLElement;
expect(track).toBeInTheDocument();
expect(track.tagName).toBe('SPAN');
expect(track).toHaveClass('switch__slider');

// for label
const label = wrapper.queryByText('Default Switch') as HTMLElement;
expect(label).toBeInTheDocument();
expect(label.tagName).toBe('LABEL');
expect(label).toHaveClass('switch__text');

expect(switchProps.onClick).toHaveBeenCalledTimes(0);
fireEvent.click(label);
expect(switchProps.onClick).toHaveBeenCalledTimes(1);
expect(input_checkbox.checked).toBe(true);
fireEvent.click(wrapper.queryByTestId('switch') as HTMLElement);
expect(switchProps.onClick).toHaveBeenCalledTimes(2);
expect(input_checkbox.checked).toBe(false);
});

it('should render diff size & type switch', () => {
const switchProps: patSwitchProps = {
switchSize: 'small',
switchType: 'primary',
onClick: jest.fn(),
checked: true,
color: "#FFA500",
};
const wrapper = render(<Switch {...switchProps} label="Default Switch" />);

// for switch-wrapper
const switch_wrapper = wrapper.queryByTestId(
'switch-wrapper'
) as HTMLElement;
expect(switch_wrapper).toBeInTheDocument();
expect(switch_wrapper.tagName).toBe('DIV');
expect(switch_wrapper).toHaveClass(
'switch-wrapper switch-primary switch-small'
);

// for input checkbox
const input_checkbox = wrapper.queryByTestId(
'switch-input'
) as HTMLInputElement;
expect(input_checkbox).toBeInTheDocument();
expect(input_checkbox.tagName).toBe('INPUT');
expect(input_checkbox.type).toBe('checkbox');
expect(input_checkbox).toBeEnabled();
expect(input_checkbox.checked).toBe(true);

// for track
const track = wrapper.queryByTestId('switch-track') as HTMLElement;
expect(track).toBeInTheDocument();
expect(track.tagName).toBe('SPAN');
expect(track).toHaveClass('switch__slider');
expect(track).toHaveStyle('background-color: #FFA500');

// for label
const label = wrapper.queryByText('Default Switch') as HTMLElement;
expect(label).toBeInTheDocument();
expect(label.tagName).toBe('LABEL');
expect(label).toHaveClass('switch__text');

expect(switchProps.onClick).toHaveBeenCalledTimes(0);
fireEvent.click(label);
expect(switchProps.onClick).toHaveBeenCalledTimes(1);
expect(input_checkbox.checked).toBe(false);
fireEvent.click(wrapper.queryByTestId('switch') as HTMLElement);
expect(switchProps.onClick).toHaveBeenCalledTimes(2);
expect(input_checkbox.checked).toBe(true);
});
});
92 changes: 92 additions & 0 deletions src/components/Switch/Switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, {
ButtonHTMLAttributes,
AnchorHTMLAttributes,
FC,
MouseEvent,
} from 'react';
import { classNames } from '../../utils/classNames';

export interface ISwitchProps {
/** Indicate if the button is disabled*/
disabled?: boolean;

/** Inital State of the Switch */
checked?: boolean;

/** Text to put besides Switch */
label?: string;

/** Type of Switch */
switchType?: 'default' | 'primary' | 'secondary';

/** Size of Switch */
switchSize?: 'medium' | 'small';

/** set action on switch toggled */
onClick?: (arg0: object) => void;

/** Pass Customed Color*/
color?: string;
}

export type patSwitchProps = ISwitchProps;

/**
* A Switch provides a toggle checkbox.
*
* ```js
* import {Switch} from 'pat-ui'
* ```
*/
export const Switch: FC<patSwitchProps> = (props) => {
const [checked, setChecked] = React.useState(props.checked || false);

const switch_classes = classNames('switch-wrapper', {
[`switch-${props.switchType || 'default'}`]: true,
[`switch-${props.switchSize || 'medium'}`]: true,
[`switch-color-custum`]: props.color ? true : false,
disabled: props.disabled || false,
});

return (
<div
className={switch_classes}
onClick={(event) => {
if (props.onClick) {
props.onClick(event);
}

if (!props.disabled) {
setChecked((e) => !e);
}
}}
data-testid="switch-wrapper"
>
<div className="switch" data-testid="switch">
<input
type="checkbox"
checked={checked}
onChange={() => null}
data-testid="switch-input"
/>
<span
className="switch__slider"
data-testid="switch-track"
style={props.color ? { 'backgroundColor': props.color } : {}}
></span>
</div>
<label className="switch__text" data-testid="switch-label">
{props.label}
</label>
</div>
);
};

Switch.defaultProps = {
checked: false,
disabled: false,
switchType: 'default',
switchSize: 'medium',
};

export default Switch;
Loading