diff --git a/src/atoms/switch/index.js b/src/atoms/switch/index.js new file mode 100644 index 0000000..be21a9d --- /dev/null +++ b/src/atoms/switch/index.js @@ -0,0 +1 @@ +export { default as Switch } from './switch'; diff --git a/src/atoms/switch/switch.js b/src/atoms/switch/switch.js new file mode 100644 index 0000000..f94870e --- /dev/null +++ b/src/atoms/switch/switch.js @@ -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 ( + + + + + } + > + {children} + + ); +}; + +export default Switch; diff --git a/src/atoms/switch/switch.scss b/src/atoms/switch/switch.scss new file mode 100644 index 0000000..394a715 --- /dev/null +++ b/src/atoms/switch/switch.scss @@ -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); + } + } + } +} diff --git a/src/atoms/switch/switch.stories.js b/src/atoms/switch/switch.stories.js new file mode 100644 index 0000000..383e5f9 --- /dev/null +++ b/src/atoms/switch/switch.stories.js @@ -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 ( +
+

+ This is me, a cool Switch family ready to be played around. Try me :) +

+
+ {generator.name()} + {generator.name()} + {generator.name()} +
+
+ ); +}; + +export const Playground = Template.bind({}); diff --git a/src/atoms/switch/switch.test.js b/src/atoms/switch/switch.test.js new file mode 100644 index 0000000..1b29c56 --- /dev/null +++ b/src/atoms/switch/switch.test.js @@ -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(); + + 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); + }); +});