Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

feat(checkboxes): adds Checkbox component #67

Merged
merged 9 commits into from
Oct 16, 2019
48 changes: 48 additions & 0 deletions src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { Component } from 'react'
import FormCheck from 'react-bootstrap/FormCheck'

interface Props {
/** The id for the checkbox */
id?: string
/** The label to render next to the checkbox */
label: string
/* Determines the side of the checkbox to render the label on. By default right */
labelSide?: 'right' | 'left'
/** Gives the checkbox a name */
name?: string
/** Determines if the checkbox should be disabled or not. By default false */
disabled?: boolean
/** Determines if the checkbox should render inline or not. By default false. */
inline?: boolean
/** The onChange listener */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
}

/**
* Checkbox is used to mark if something is true or not. Often times is used in a group where
* multiple things can be true at one time.
*/
class Checkbox extends Component<Props, {}> {
render() {
const labelSide = this.props.labelSide ? this.props.labelSide : 'right'

return (
<FormCheck name={this.props.name} inline={this.props.inline}>
{labelSide === 'left' && (
<FormCheck.Label htmlFor={this.props.id}>{this.props.label}</FormCheck.Label>
)}
<FormCheck.Input
id={this.props.id}
type="checkbox"
disabled={this.props.disabled}
onChange={this.props.onChange}
/>
{labelSide === 'right' && (
<FormCheck.Label htmlFor={this.props.id}>{this.props.label}</FormCheck.Label>
)}
</FormCheck>
)
}
}

export { Checkbox }
1 change: 1 addition & 0 deletions src/components/Checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Checkbox'
4 changes: 0 additions & 4 deletions src/components/Radio/Radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ interface Props {
}

class Radio extends Component<Props, {}> {
constructor(props: Props) {
super(props)
}

render() {
return (
<FormCheck
Expand Down
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export * from './components/Button'
export * from './components/Icon'
export * from './components/Badge'
export * from './components/Pill'
export * from './components/Checkbox'
export * from './components/Navbar'
export * from './components/TextField'
export * from './components/Radio'
Expand Down
24 changes: 24 additions & 0 deletions stories/checkbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import { Checkbox } from '../src'

storiesOf('Checkbox', module)
.addParameters({
info: {
inline: true,
},
})
.addDecorator(storyFn => <div style={{ textAlign: 'center' }}>{storyFn()}</div>)
.add('Checkbox', () => (
<div>
<h1>Vertical</h1>
<Checkbox label="Checkbox 1" id="checkbox1" />
<Checkbox label="Checkbox 2" id="checkbox2" />
<Checkbox label="Checkbox 3" id="checkbox3" disabled />
<br />
<h1>Horizontal</h1>
<Checkbox label="Checkbox 1" id="checkbox11" inline />
<Checkbox label="Checkbox 2" id="checkbox22" inline />
<Checkbox label="Checkbox 3" id="checkbox33" inline />
</div>
))
59 changes: 59 additions & 0 deletions test/checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react'
import { mount, shallow } from 'enzyme'
import FormCheck from 'react-bootstrap/FormCheck'
import * as sinon from 'sinon'
import { Checkbox } from '../dist'

describe('Checkbox', () => {
it('Checkbox renders itself without crashing', () => {
const checkboxWrapper = shallow(<Checkbox label="Checkbox" />)
expect(checkboxWrapper.text()).toEqual('Checkbox')
expect(checkboxWrapper.props().disabled).toBeFalsy()
expect(checkboxWrapper.props().inline).toBeFalsy()
expect(checkboxWrapper.props().name).toBeUndefined()
expect(checkboxWrapper.props().onChange).toBeUndefined()
expect(checkboxWrapper.find(FormCheck)).toHaveLength(1)
})

it('Checkbox renders the label on the right hand side by default', () => {
const checkboxWrapperRight = shallow(<Checkbox label="Checkbox" labelSide="right" />)
expect(checkboxWrapperRight.text()).toEqual('Checkbox')
expect(checkboxWrapperRight.childAt(1).type()).toBe(FormCheck.Label)
})

it('Checkbox should allow for the use of a name', () => {
const checkboxWrapper = shallow(<Checkbox label="Checkbox" name="test" />)
const bootstrapCheckBox = checkboxWrapper.find(FormCheck)
expect(bootstrapCheckBox.props().name).toEqual('test')
})

it('Checkbox should render inline if the inline prop is used', () => {
const checkboxWrapper = shallow(<Checkbox label="Checkbox" inline />)
const bootstrapCheckBox = checkboxWrapper.find(FormCheck)
expect(bootstrapCheckBox.props().inline).toBeTruthy()
})

it('Checkbox renders the label on the correct side', () => {
const checkboxWrapperLeft = shallow(<Checkbox label="Checkbox" labelSide="left" />)
expect(checkboxWrapperLeft.text()).toEqual('Checkbox')
expect(checkboxWrapperLeft.childAt(0).type()).toBe(FormCheck.Label)

const checkboxWrapperRight = shallow(<Checkbox label="Checkbox" labelSide="right" />)
expect(checkboxWrapperRight.text()).toEqual('Checkbox')
expect(checkboxWrapperRight.childAt(1).type()).toBe(FormCheck.Label)
})

it('Checkbox should render be rendered disabled when disabled prop is used', () => {
const wrapper = mount(<Checkbox label="Checkbox" disabled />)
const input = wrapper.find(HTMLInputElement)
expect(input.prop('disabled')).toBe(true)
})

it('Checkbox handle the change event', () => {
const onChange = sinon.spy()
const wrapper = mount(<Checkbox label="Checkbox" onChange={onChange} />)
const input = wrapper.find(HTMLInputElement)
input.simulate('change')
expect(onChange).toHaveProperty('callCount', 1)
})
})