Skip to content

Commit

Permalink
feat: support form switch
Browse files Browse the repository at this point in the history
- make Input api similar to CustomInput (e.g. allow writing <Input type="switch" />
- make FormGroup api for switch similar to api for checkbox (e.g. allow
  writing <FormGroup switch />)

https://getbootstrap.com/docs/5.0/forms/checks-radios/#switches
  • Loading branch information
darreneng authored and phwebi committed Oct 27, 2021
1 parent 06868e2 commit f403595
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
4 changes: 4 additions & 0 deletions docs/lib/examples/InputType.js
Expand Up @@ -140,6 +140,10 @@ const Example = (props) => {
<Input id="InputType-checkbox" type="checkbox" />
<Label for="InputType-checkbox" check>Check me out</Label>
</FormGroup>
<FormGroup switch>
<Input id="InputType-switch" type="switch" />
<Label for="InputType-switch" check>Check me out</Label>
</FormGroup>
</Form>
);
}
Expand Down
12 changes: 8 additions & 4 deletions src/FormGroup.js
Expand Up @@ -7,6 +7,7 @@ const propTypes = {
children: PropTypes.node,
row: PropTypes.bool,
check: PropTypes.bool,
switch: PropTypes.bool,
inline: PropTypes.bool,
disabled: PropTypes.bool,
tag: tagPropType,
Expand All @@ -30,14 +31,17 @@ const FormGroup = (props) => {
...attributes
} = props;

const formCheck = check || props.switch;

const classes = mapToCssModules(classNames(
className,
row ? 'row' : false,
check ? 'form-check' : 'mb-3',
check && inline ? 'form-check-inline' : false,
check && disabled ? 'disabled' : false
formCheck ? 'form-check' : 'mb-3',
props.switch ? 'form-switch' : false,
formCheck && inline ? 'form-check-inline' : false,
formCheck && disabled ? 'disabled' : false
), cssModule);

if (Tag === 'fieldset') {
attributes.disabled = disabled;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Input.js
Expand Up @@ -63,7 +63,7 @@ class Input extends React.Component {
...attributes
} = this.props;

const checkInput = ['radio', 'checkbox'].indexOf(type) > -1;
const checkInput = ['switch', 'radio', 'checkbox'].indexOf(type) > -1;
const isNotaNumber = new RegExp('\\D', 'g');

const textareaInput = type === 'textarea';
Expand Down Expand Up @@ -112,7 +112,7 @@ class Input extends React.Component {
);

if (Tag === 'input' || (tag && typeof tag === 'function')) {
attributes.type = type;
attributes.type = type === 'switch' ? 'checkbox' : type;
}

if (
Expand Down
38 changes: 36 additions & 2 deletions src/__tests__/FormGroup.spec.js
Expand Up @@ -34,20 +34,41 @@ describe('FormGroup', () => {
expect(wrapper.hasClass('form-check')).toBe(true);
});

it('should render with "form-check" and "form-switch" class when switch prop is truthy', () => {
const wrapper = shallow(<FormGroup switch>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check')).toBe(true);
expect(wrapper.hasClass('form-switch')).toBe(true);
});

it('should not render with "form-check-inline" class when check prop is truthy and inline prop is falsy', () => {
const wrapper = shallow(<FormGroup check>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check-inline')).toBe(false);
});

it('should not render with "form-check-inline" class when switch prop is truthy and inline prop is falsy', () => {
const wrapper = shallow(<FormGroup switch>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check-inline')).toBe(false);
});

it('should render with "form-check" and "form-check-inline" classes when check prop and inline prop are both truthy', () => {
const wrapper = shallow(<FormGroup check inline>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check')).toBe(true);
expect(wrapper.hasClass('form-check-inline')).toBe(true);
});

it('should not render with "form-check-inline" class when check prop is falsy and inline prop is truthy', () => {
it('should render with "form-check" and "form-switch" and "form-check-inline" classes when check prop and inline prop are both truthy', () => {
const wrapper = shallow(<FormGroup switch inline>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check')).toBe(true);
expect(wrapper.hasClass('form-switch')).toBe(true);
expect(wrapper.hasClass('form-check-inline')).toBe(true);
});

it('should not render with "form-check-inline" class when check and switch prop are falsy and inline prop is truthy', () => {
const wrapper = shallow(<FormGroup inline>Yo!</FormGroup>);

expect(wrapper.hasClass('form-check-inline')).toBe(false);
Expand All @@ -59,7 +80,13 @@ describe('FormGroup', () => {
expect(wrapper.hasClass('mb-3')).toBe(false);
});

it('should not render with "disabled" class when disabled prop is truthy but check is not', () => {
it('should not render with "mb-3" class when switch prop is truthy', () => {
const wrapper = shallow(<FormGroup switch>Yo!</FormGroup>);

expect(wrapper.hasClass('mb-3')).toBe(false);
});

it('should not render with "disabled" class when disabled prop is truthy but check and switch are not', () => {
const wrapper = shallow(<FormGroup disabled>Yo!</FormGroup>);

expect(wrapper.hasClass('disabled')).toBe(false);
Expand All @@ -72,6 +99,13 @@ describe('FormGroup', () => {
expect(wrapper.hasClass('form-check')).toBe(true);
});

it('should render with "disabled" class when both switch and disabled props are truthy', () => {
const wrapper = shallow(<FormGroup switch disabled>Yo!</FormGroup>);

expect(wrapper.hasClass('disabled')).toBe(true);
expect(wrapper.hasClass('form-check')).toBe(true);
});

it('should render with "row" class when row prop is truthy', () => {
const wrapper = shallow(<FormGroup row>Yo!</FormGroup>);

Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/Input.spec.js
Expand Up @@ -211,6 +211,12 @@ describe('Input', () => {
expect(wrapper.hasClass('form-check-input')).toBe(true);
});

it('should render with "form-check-input" class when type is switch', () => {
const wrapper = shallow(<Input type="switch" />);

expect(wrapper.hasClass('form-check-input')).toBe(true);
});

it('should not render with "form-check-input" nor "form-control" class when type is checkbox and addon is truthy', () => {
const wrapper = shallow(<Input addon type="checkbox" />);

Expand Down Expand Up @@ -243,6 +249,12 @@ describe('Input', () => {
expect(wrapper.hasClass('other')).toBe(true);
});

it('should render checkbox type when type is switch', () => {
const input = shallow(<Input type="switch" />);

expect(input.find('[type="checkbox"]').exists()).toBe(true);
});

it('should render "select" and "textarea" without type property', () => {
const input = shallow(<Input type="select">Yo!</Input>);
const textarea = shallow(<Input type="textarea" />);
Expand Down

0 comments on commit f403595

Please sign in to comment.