Skip to content

Commit

Permalink
feat(toggle): add toggle component
Browse files Browse the repository at this point in the history
  • Loading branch information
w0wka91 committed Dec 1, 2019
1 parent 2d16e88 commit f3d3828
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/components/toggle/Toggle.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Toggle
---

import { Playground } from 'docz'
import { Toggle } from './Toggle'
import { useToggle } from '../../hooks/useToggle'

# Toggle

Basic usage of a toggle component

<Playground>
{() => {
const [toggleValue, toggle] = useToggle(false)
return (
<>
<Toggle label="Toggle" onChange={toggle} checked={toggleValue} />
</>
)
}}

</Playground>
19 changes: 19 additions & 0 deletions src/components/toggle/Toggle.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup, fireEvent } from '@testing-library/react'
import { Toggle } from './Toggle'

afterEach(cleanup)

it('should be checked after render', () => {
const { getByLabelText } = render(<Toggle label="Test" defaultChecked />)
expect(getByLabelText('Test')).toHaveAttribute('checked')
})

it('should execute the passed function', () => {
const func = jest.fn()
const { getByLabelText } = render(<Toggle onClick={func} label="Test" />)
fireEvent.focus(getByLabelText('Test'))
fireEvent.click(getByLabelText('Test'))
expect(func).toHaveBeenCalledTimes(1)
})
92 changes: 92 additions & 0 deletions src/components/toggle/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useState } from 'react'
import { css } from 'emotion'
import { colors } from '../../utils/colors'
import { useId } from '../../hooks/useId'

interface Props {
label?: string
}

function Toggle({
label,
value,
checked,
disabled,
onBlur,
onFocus,
...rest
}: Props & React.HTMLProps<HTMLInputElement>) {
const id = useId()
const [focus, setFocus] = useState(false)
return (
<div
className={css`
position: relative;
`}
>
<input
{...rest}
type="checkbox"
id={`toggle-${id}`}
checked={checked}
disabled={disabled}
className={css`
position: absolute;
opacity: 0;
&:disabled + label {
cursor: auto;
}
`}
onFocus={evt => {
setFocus(true)
if (onFocus) onFocus(evt)
}}
onBlur={evt => {
setFocus(false)
if (onBlur) onBlur(evt)
}}
/>
<label
htmlFor={`toggle-${id}`}
className={css`
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
color: inherit;
font-family: inherit;
`}
>
<div
className={css`
position: relative;
width: 4.8rem;
height: 2.4rem;
margin-right: ${label && '1.2rem'};
border-radius: 256px;
border: 1px solid ${checked ? colors.blue500 : colors.grey400};
box-shadow: ${focus && `0 0 0 2px ${colors.blue300}`};
background: ${disabled && colors.grey100};
`}
>
<div
className={css`
position: absolute;
top: 50%;
transform: translateY(-50%) ${checked && 'translateX(150%)'};
border-radius: 100%;
width: 1.6rem;
height: 1.6rem;
background: ${checked ? colors.blue500 : colors.grey300};
margin: 0 3px;
transition: all 0.2s linear;
`}
/>
</div>
{label}
</label>
</div>
)
}

export { Toggle }

0 comments on commit f3d3828

Please sign in to comment.