Created the <RadioButton /> and <FormField /> components. (#7112)

* Created the <RadioButton /> and <FormField /> components.
This commit is contained in:
Nick Taylor 2020-04-08 15:04:54 -04:00 committed by GitHub
parent 60d2febc54
commit 29951e05e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 257 additions and 0 deletions

View file

@ -0,0 +1,28 @@
import { h } from 'preact';
import PropTypes from 'prop-types';
import { defaultChildrenPropTypes } from '../../../src/components/common-prop-types';
// Only radio and checkboxes require an additional CSS class (variant class). Other form elements do not.
export const FormField = ({ children, variant }) => {
return (
<div
className={`crayons-field${
variant && variant.length > 0 ? ` crayons-field--${variant}` : ''
}`}
>
{children}
</div>
);
};
FormField.displayName = 'FormField';
FormField.defaultProps = {
variant: undefined,
};
FormField.propTypes = {
children: defaultChildrenPropTypes.isRequired,
variant: PropTypes.oneOf(['radio', 'checkbox']),
};

View file

@ -0,0 +1 @@
export * from './FormField';

View file

@ -0,0 +1,43 @@
import { h } from 'preact';
import PropTypes from 'prop-types';
export const RadioButton = ({
id,
value,
name,
className,
checked,
onClick,
}) => {
return (
<input
id={id}
value={value}
name={name}
className={`crayons-radio${
className && className.length > 0 ? ` ${className}` : ''
}`}
checked={checked}
onClick={onClick}
type="radio"
/>
);
};
RadioButton.displayName = 'RadioButton';
RadioButton.defaultProps = {
id: undefined,
className: undefined,
checked: false,
name: undefined,
};
RadioButton.propTypes = {
id: PropTypes.string,
value: PropTypes.string.isRequired,
className: PropTypes.string,
checked: PropTypes.bool,
name: PropTypes.string,
onClick: PropTypes.func.isRequired,
};

View file

@ -0,0 +1 @@
export * from './RadioButton';

View file

@ -0,0 +1,24 @@
import { h } from 'preact';
import { action } from '@storybook/addon-actions';
import { FormField, RadioButton } from '@crayons';
export default {
title: 'Components/Form Components/Form Field',
};
export const RadioVariant = () => (
<FormField variant="radio">
<RadioButton
id="some-id"
name="some-radio-button"
onClick={action('clicked')}
/>
<label htmlFor="some-id" className="crayons-field__label">
Some Radio Button Text
</label>
</FormField>
);
RadioVariant.story = {
name: 'radio',
};

View file

@ -0,0 +1,34 @@
import { h } from 'preact';
import { withKnobs, text, boolean } from '@storybook/addon-knobs/react';
import { action } from '@storybook/addon-actions';
import { RadioButton } from '@crayons';
export default {
title: 'Components/Form Components/Radio Button',
decorators: [withKnobs],
};
export const Default = () => (
<RadioButton
name="some-radio-button"
checked={boolean('checked', false)}
onClick={action('clicked')}
/>
);
Default.story = {
name: 'default',
};
export const AdditionalCssClassName = () => (
<RadioButton
name="some-radio-button"
checked={boolean('checked', false)}
className={text('className', 'mr-10')}
onClick={action('clicked')}
/>
);
AdditionalCssClassName.story = {
name: 'additional CSS class',
};

View file

@ -0,0 +1,20 @@
import { h } from 'preact';
import render from 'preact-render-to-json';
import { FormField, RadioButton } from '@crayons';
describe('<FormField /> component', () => {
it('should render', () => {
const tree = render(<FormField />);
expect(tree).toMatchSnapshot();
});
it('should render with contents', () => {
const tree = render(
<FormField>
<RadioButton id="some-id" value="some-value" name="some-name" />
<label htmlFor="some-id">Some Label</label>
</FormField>,
);
expect(tree).toMatchSnapshot();
});
});

View file

@ -0,0 +1,47 @@
import { h } from 'preact';
import render from 'preact-render-to-json';
import { shallow } from 'preact-render-spy';
import { RadioButton } from '@crayons';
describe('<RadioButton /> component', () => {
it('should render a radio button unchecked by default', () => {
const tree = render(<RadioButton />);
expect(tree).toMatchSnapshot();
});
it('should render a radio button checked', () => {
const tree = render(<RadioButton checked />);
expect(tree).toMatchSnapshot();
});
it('should render a radio button with given props', () => {
const tree = render(
<RadioButton
id="some-id"
value="some-value"
name="some-name"
className="additional-css-class-name"
onClick={jest.fn()}
/>,
);
expect(tree).toMatchSnapshot();
});
it('should support onClick', () => {
const onClick = jest.fn();
const wrapper = shallow(
<RadioButton
id="some-id"
value="some-value"
name="some-name"
className="additional-css-class-name"
onClick={onClick}
/>,
);
wrapper.simulate('click');
expect(onClick).toHaveBeenCalled();
});
});

View file

@ -0,0 +1,27 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<FormField /> component should render 1`] = `
<div
class="crayons-field"
/>
`;
exports[`<FormField /> component should render with contents 1`] = `
<div
class="crayons-field"
>
<input
checked={false}
class="crayons-radio"
id="some-id"
name="some-name"
type="radio"
value="some-value"
/>
<label
htmlFor="some-id"
>
Some Label
</label>
</div>
`;

View file

@ -0,0 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<RadioButton /> component should render a radio button checked 1`] = `
<input
checked={true}
class="crayons-radio"
type="radio"
/>
`;
exports[`<RadioButton /> component should render a radio button unchecked by default 1`] = `
<input
checked={false}
class="crayons-radio"
type="radio"
/>
`;
exports[`<RadioButton /> component should render a radio button with given props 1`] = `
<input
checked={false}
class="crayons-radio additional-css-class-name"
id="some-id"
name="some-name"
onClick={[MockFunction]}
type="radio"
value="some-value"
/>
`;

View file

@ -0,0 +1,2 @@
export * from './FormField';
export * from './RadioButton';

View file

@ -1,3 +1,4 @@
export * from '@crayons/Button';
export * from '@crayons/ButtonGroup';
export * from '@crayons/Dropdown';
export * from '@crayons/formElements';