Skip to content

Commit

Permalink
feat(checkboxgroup): New CheckBoxGroup, update CheckBox & asInput styles
Browse files Browse the repository at this point in the history
feat(checkboxgroup): New CheckBoxGroup, update CheckBox & asInput styles
  • Loading branch information
Farhanah Sheets authored Jan 8, 2018
2 parents cfe8858 + e3a156e commit d9bfb4c
Show file tree
Hide file tree
Showing 9 changed files with 442 additions and 23 deletions.
327 changes: 311 additions & 16 deletions .storybook/__snapshots__/Storyshots.test.js.snap

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Demo implementations of each component are viewable at the Paragon doc site at h
- [asInput](src/asInput)
- [Button](src/Button)
- [CheckBox](src/CheckBox)
- [CheckBoxGroup](src/CheckBoxGroup)
- [Dropdown](src/Dropdown)
- [Hyperlink](src/Hyperlink)
- [Icon](src/Icon)
Expand Down
3 changes: 2 additions & 1 deletion src/CheckBox/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Check extends React.Component {
return (
<input
id={props.id}
className={props.className}
type="checkbox"
name={props.name}
defaultChecked={this.state.checked}
Expand All @@ -49,6 +50,6 @@ Check.defaultProps = {
onChange: () => {},
};

const CheckBox = asInput(Check, false);
const CheckBox = asInput(Check, 'checkbox', false);

export default CheckBox;
2 changes: 2 additions & 0 deletions src/CheckBoxGroup/CheckBoxGroup.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "~bootstrap/scss/_forms";
@import "~bootstrap/scss/mixins/_forms";
28 changes: 28 additions & 0 deletions src/CheckBoxGroup/CheckBoxGroup.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-console */
import React from 'react';
import { storiesOf } from '@storybook/react';

import CheckBoxGroup from './index';
import CheckBox from '../CheckBox';

storiesOf('CheckBoxGroup', module)
.add('basic usage', () => (
<CheckBoxGroup>
<CheckBox
id="checkbox1"
name="basicCheckBox"
label="CheckBox 1"
/>
<CheckBox
id="checkbox2"
name="basicCheckBox"
label="CheckBox 2"
/>
<CheckBox
id="checkbox3"
name="basicCheckBox"
label="CheckBox 3"
/>
</CheckBoxGroup>
));
34 changes: 34 additions & 0 deletions src/CheckBoxGroup/CheckBoxGroup.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* eslint-disable import/no-extraneous-dependencies */
import React from 'react';
import { mount } from 'enzyme';
import CheckBoxGroup from './index';
import CheckBox from '../CheckBox';

describe('<CheckBoxGroup />', () => {
it('correct number of children displayed in group', () => {
const checkBoxGroup = (
<CheckBoxGroup>
<CheckBox
id="checkbox1"
name="basicCheckBox"
label="CheckBox 1"
/>
<CheckBox
id="checkbox2"
name="basicCheckBox"
label="CheckBox 2"
/>
<CheckBox
id="checkbox3"
name="basicCheckBox"
label="CheckBox 3"
/>
</CheckBoxGroup>
);
const wrapper = mount(checkBoxGroup);

expect(wrapper.find('[id="checkbox1"]').exists()).toEqual(true);
expect(wrapper.find('[id="checkbox2"]').exists()).toEqual(true);
expect(wrapper.find('[id="checkbox3"]').exists()).toEqual(true);
});
});
8 changes: 8 additions & 0 deletions src/CheckBoxGroup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CheckBoxGroup

CheckboxGroup is a group of the CheckBox components. It takes CheckBox components as children and wraps them in the bootstrap `form-group` styling. See `CheckBox` description for more details

## API

### `children` (array of `CheckBox`; required)
`children` represents the CheckBox components defined within the CheckBoxGroup component and is not a specific named prop that needs to be passed in. At least one CheckBox must be defined within the group. Example: `<CheckBoxGroup><CheckBox .../></CheckBoxGroup>`
20 changes: 20 additions & 0 deletions src/CheckBoxGroup/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
import ElementPropTypes from 'react-element-proptypes';

import CheckBox from '../CheckBox';
import styles from './CheckBoxGroup.scss';

function CheckBoxGroup(props) {
return (
<div className={styles['form-group']}>
{props.children}
</div>
);
}

CheckBoxGroup.propTypes = {
children: PropTypes.arrayOf(ElementPropTypes.elementOfType(CheckBox)).isRequired,
};

export default CheckBoxGroup;
42 changes: 36 additions & 6 deletions src/asInput/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const defaultProps = {
themes: [],
};

const asInput = (WrappedComponent, labelFirst = true) => {
const asInput = (WrappedComponent, inputType = undefined, labelFirst = true) => {
class NewComponent extends React.Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -125,10 +125,33 @@ const asInput = (WrappedComponent, labelFirst = true) => {
return desc;
}

getLabel() {
return (
<label
id={`label-${this.state.id}`}
htmlFor={this.state.id}
className={[classNames({
[styles['form-check-label']]: this.isGroupedInput(),
})]}
>
{this.props.label}
</label>
);
}

hasDangerTheme() {
return this.props.themes.includes('danger');
}

isGroupedInput() {
switch (inputType) {
case 'checkbox':
return true;
default:
return false;
}
}

handleBlur(event) {
const val = event.target.value;

Expand All @@ -149,21 +172,28 @@ const asInput = (WrappedComponent, labelFirst = true) => {
render() {
const { description, error, describedBy } = this.getDescriptions();
return (
<div className={styles['form-group']}>
{labelFirst && <label id={`label-${this.state.id}`} htmlFor={this.state.id}>{this.props.label}</label>}
<div className={[classNames({
[styles['form-group']]: !this.isGroupedInput(),
[styles['form-check']]: this.isGroupedInput(),
})]}
>
{labelFirst && this.getLabel()}
<WrappedComponent
{...this.props}
{...this.state}
className={[classNames(
styles['form-control'],
{ [styles['is-invalid']]: !this.state.isValid && this.hasDangerTheme() },
{
[styles['form-control']]: !this.isGroupedInput(),
[styles['form-check-input']]: this.isGroupedInput(),
[styles['is-invalid']]: !this.state.isValid && this.hasDangerTheme(),
},
{ ...this.props.className },
)]}
describedBy={describedBy}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
{!labelFirst && <label htmlFor={this.state.id}>{this.props.label}</label>}
{!labelFirst && this.getLabel()}
{error}
{description}
</div>
Expand Down

0 comments on commit d9bfb4c

Please sign in to comment.