Skip to content

Commit

Permalink
feat: add switch component
Browse files Browse the repository at this point in the history
  • Loading branch information
welingtonms committed Mar 26, 2021
1 parent d3435f6 commit afaa224
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/atoms/switch/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Switch } from './switch';
46 changes: 46 additions & 0 deletions src/atoms/switch/switch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import clsx from 'clsx';

import { Box } from '../box';
import { Icon } from '../icon';

import './switch.scss';

const Switch = ({
borderless = true,
children,
className,
disabled,
paddingless = 'horizontal',
block = false,
trailing,
...others
}) => {
return (
<Box
as="label"
borderless={borderless}
paddingless={paddingless}
block={block}
trailing={trailing}
className={clsx('cb-switch', { 'is-disabled': disabled }, className)}
data-testid="cb-switch"
leading={
<React.Fragment>
<input
{...others}
disabled={disabled}
type="checkbox"
className="selector"
data-testid="selector"
/>
<Icon name="circle" className="check" size={14} />
</React.Fragment>
}
>
{children}
</Box>
);
};

export default Switch;
61 changes: 61 additions & 0 deletions src/atoms/switch/switch.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@import '../../styles/tools/_tools.mixins';

.cb-switch {
@include font;
@include disableable;
@include interactable;

align-items: center;
justify-content: flex-start;

.check {
@include transition(left);

@include var(color, color-white);

fill: currentColor;
position: absolute;
left: 2px;
}

.selector:first-of-type {
@include focusable;
@include bordered;
@include rounded(0.5rem);

@include transition(background color border-color);

cursor: pointer !important;
appearance: none;
outline: none;

@include var(border-color, color-gray-300);
@include var(background-color, color-gray-300);

flex-shrink: 0;

@include var(height, spacing-4);
@include var(width, spacing-8);

&:checked {
@include var(border-color, color-primary-500);
@include var(background-color, color-primary-500);
}

&:checked + .check {
left: calc(32px - 16px);
}
}

@include hoverable {
.selector {
@include var(border-color, color-gray-400);
@include var(background-color, color-gray-400);

&:checked {
@include var(border-color, color-primary-700);
@include var(background-color, color-primary-700);
}
}
}
}
31 changes: 31 additions & 0 deletions src/atoms/switch/switch.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';

import Switch from './switch';
import generator from '../../../test/data-generator';

export default {
title: 'Atoms/Switch',
component: Switch,
docs: {
description: {
story: 'some story *a*markdown**',
},
},
};

const Template = args => {
return (
<div className="block">
<p className="mb-2">
This is me, a cool Switch family ready to be played around. Try me :)
</p>
<div className="flex flex-col space-y-2">
<Switch {...args}>{generator.name()}</Switch>
<Switch {...args}>{generator.name()}</Switch>
<Switch {...args}>{generator.name()}</Switch>
</div>
</div>
);
};

export const Playground = Template.bind({});
28 changes: 28 additions & 0 deletions src/atoms/switch/switch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import { render, fireEvent } from '../../../test/helpers';
import { Switch } from './index';
import generator from '../../../test/data-generator';

describe('Switch', () => {
const props = {
children: generator.word(),
onChange: jest.fn(),
};

const { getByTestId } = render(<Switch {...props} />);

const component = getByTestId('cb-switch');
const selector = getByTestId('selector');

it('renders correctly', () => {
expect(component).toHaveTextContent(props.children);
expect(selector).toHaveAttribute('type', 'checkbox');
});

it('triggers onChange when clicked', () => {
expect(selector.checked).toBe(false);
fireEvent.click(selector);
expect(selector.checked).toBe(true);
});
});

0 comments on commit afaa224

Please sign in to comment.