Repository: react-materialize/react-materialize
Pull request #723 (2018-12-16 14:43:24)

Implement RadioGroup
Feature RadioGroup


Patch:
diff --git a/src/RadioGroup.js b/src/RadioGroup.js
new file mode 100644
index 0000000..92084f9
--- /dev/null
+++ b/src/RadioGroup.js
@@ -0,0 +1,72 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import cx from 'classnames';
+
+const RadioGroup = ({
+  onChange,
+  withGap,
+  disabled,
+  name,
+  radioClassNames,
+  value,
+  options
+}) => {
+  return (
+    <React.Fragment>
+      {options.map((radioItem, idx) => (
+        <label
+          className={radioClassNames}
+          htmlFor={`radio${idx}`}
+          key={`radio${idx}`}
+        >
+          <input
+            id={`radio${idx}`}
+            value={radioItem.value}
+            type="radio"
+            defaultChecked={radioItem.value === value}
+            name={name}
+            onChange={onChange}
+            disabled={disabled}
+            className={cx({ 'with-gap': withGap })}
+          />
+          <span>{radioItem.label}</span>
+        </label>
+      ))}
+    </React.Fragment>
+  );
+};
+
+RadioGroup.propTypes = {
+  options: PropTypes.arrayOf(
+    PropTypes.shape({
+      label: PropTypes.string.isRequired,
+      value: PropTypes.string.isRequired
+    })
+  ).isRequired,
+  /*
+   * predefined checked value
+   */
+  value: PropTypes.string,
+  /*
+   * radio group name
+   */
+  name: PropTypes.string,
+  /*
+   * with-gap styled checkbox
+   */
+  withGap: PropTypes.bool,
+  /*
+   * onChange callback
+   */
+  onChange: PropTypes.func,
+  /*
+   * disabled input
+   */
+  disabled: PropTypes.bool,
+  /*
+   * classnames passed to label wrapper
+   */
+  radioClassNames: PropTypes.string
+};
+
+export default RadioGroup;
diff --git a/src/Select.js b/src/Select.js
deleted file mode 100644
index c5c0122..0000000
--- a/src/Select.js
+++ /dev/null
@@ -1,196 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import cx from 'classnames';
-import idgen from './idgen';
-import constants from './constants';
-
-class Select extends Component {
-  constructor(props) {
-    super(props);
-
-    this.id = props.id || idgen();
-    this.handleChange = this.handleChange.bind(this);
-    this.state = { value: props.value };
-  }
-
-  handleChange(event) {
-    const { onChange } = this.props;
-    let value = event.target.value;
-
-    if (this.props.multiple) {
-      value = this.instance.getSelectedValues();
-    }
-
-    if (onChange) onChange(event);
-
-    this.setState({ value });
-  }
-
-  componentDidMount() {
-    if (typeof M !== 'undefined') {
-      this.instance = M.FormSelect.init(this._selectRef);
-    }
-  }
-
-  render() {
-    const {
-      s,
-      m,
-      l,
-      disabled,
-      noLayout,
-      browserDefault,
-      icon,
-      label,
-      selectClassName,
-      success,
-      error,
-      validate,
-      children,
-      multiple,
-      value,
-      type
-    } = this.props;
-
-    const sizes = { s, m, l };
-
-    let responsiveClasses;
-    if (!noLayout) {
-      responsiveClasses = { col: true };
-      constants.SIZES.forEach(size => {
-        responsiveClasses[size + sizes[size]] = sizes[size];
-      });
-    }
-
-    const wrapperClasses = cx('input-field', responsiveClasses);
-
-    const selectProps = {
-      type: 'select',
-      id: this.id,
-      value: this.state.value,
-      disabled,
-      multiple
-    };
-
-    const renderLabel = () =>
-      label && (
-        <label
-          data-success={success}
-          data-error={error}
-          htmlFor={selectProps.id}
-        >
-          {label}
-        </label>
-      );
-
-    const renderIcon = () =>
-      icon && <i className="material-icons prefix">{icon}</i>;
-
-    const renderOption = child =>
-      React.cloneElement(child, { key: child.props.value });
-
-    const renderOptions = () => React.Children.map(children, renderOption);
-
-    return (
-      <div className={wrapperClasses}>
-        {renderIcon()}
-        <select
-          value={this.state.value}
-          ref={el => {
-            this._selectRef = el;
-          }}
-          onChange={this.handleChange}
-          className={cx(
-            {
-              validate,
-              multiple,
-              ['browser-default']: browserDefault
-            },
-            selectClassName
-          )}
-          {...selectProps}
-        >
-          {renderOptions()}
-        </select>
-        {renderLabel()}
-      </div>
-    );
-  }
-}
-
-Select.propTypes = {
-  /*
-   * Use browser default styles
-   */
-  browserDefault: PropTypes.bool,
-  /*
-   * Strip away all layout classes such as col and sX
-   */
-  noLayout: PropTypes.bool,
-  /*
-   * Responsive size for Small
-   */
-  s: PropTypes.number,
-  /*
-   * Responsive size for Medium
-   */
-  m: PropTypes.number,
-  /*
-   * Responsive size for Large
-   */
-  l: PropTypes.number,
-  /*
-   * disabled input
-   */
-  disabled: PropTypes.bool,
-  /*
-   * override id
-   * @default idgen()
-   */
-  id: PropTypes.string,
-  /*
-   * prefix icon
-   */
-  icon: PropTypes.string,
-  /*
-   * label text
-   */
-  label: PropTypes.string,
-  /*
-   * Input initial value
-   */
-  value: PropTypes.string,
-  /*
-   * Add validate class to input
-   */
-  validate: PropTypes.bool,
-  /*
-   * Custom success message
-   */
-  success: PropTypes.string,
-  /*
-   * Custom error message
-   */
-  error: PropTypes.string,
-  /*
-   * Additional classes for input
-   */
-  selectClassName: PropTypes.string,
-  /*
-   * override type="text"
-   */
-  type: PropTypes.string,
-  /*
-   * onChange callback
-   */
-  onChange: PropTypes.func,
-  /*
-   * Render a multiple dropdown,
-   * use instance.getSelectedValues()
-   * to get array of selected values
-   */
-  multiple: PropTypes.bool,
-  children: PropTypes.any
-};
-
-export default Select;
diff --git a/src/TextInput.js b/src/TextInput.js
index 8c64784..c92e46a 100644
--- a/src/TextInput.js
+++ b/src/TextInput.js
@@ -7,16 +7,20 @@ import constants from './constants';
 class TextInput extends Component {
   constructor(props) {
     super(props);
+    this.state = {
+      value: ''
+    };
 
     this.id = props.id || idgen();
+    this.handleChange = this.handleChange.bind(this);
+  }
 
-    if (props.password) {
-      this.id = 'password';
-    }
+  handleChange(event) {
+    const { target: { value } } = event;
+    const { onChange } = this.props;
+    if (onChange) onChange(event);
 
-    if (props.email) {
-      this.id = 'email';
-    }
+    this.setState({ value });
   }
 
   componentDidUpdate(prevProps) {
@@ -41,8 +45,6 @@ class TextInput extends Component {
       inputClassName,
       success,
       error,
-      password,
-      email,
       validate,
       value,
       type
@@ -60,29 +62,17 @@ class TextInput extends Component {
 
     const wrapperClasses = cx('input-field', responsiveClasses);
 
-    let computedType;
-    if (type) {
-      computedType = type;
-    } else if (password) {
-      computedType = 'password';
-    } else if (email) {
-      computedType = 'email';
-    } else {
-      computedType = 'text';
-    }
-
     const inputProps = {
       placeholder,
-      type: computedType,
+      type: type || 'text',
       id: this.id,
-      defaultValue: value,
+      value: value || this.state.value,
       disabled
     };
 
     const renderLabel = () =>
       label && (
         <label
-          className={cx({ active: value || placeholder })}
           data-success={success}
           data-error={error}
           htmlFor={inputProps.id}
@@ -91,15 +81,6 @@ class TextInput extends Component {
         </label>
       );
 
-    const renderHelper = () =>
-      [error || success] && (
-        <span
-          className="helper-text"
-          data-error={error}
-          data-success={success}
-        />
-      );
-
     const renderIcon = () =>
       icon && <i className="material-icons prefix">{icon}</i>;
 
@@ -115,7 +96,6 @@ class TextInput extends Component {
           {...inputProps}
         />
         {renderLabel()}
-        {renderHelper()}
       </div>
     );
   }
@@ -190,15 +170,7 @@ TextInput.propTypes = {
   /*
    * onChange callback
    */
-  onChange: PropTypes.func,
-  /*
-   * password type
-   */
-  password: PropTypes.bool,
-  /*
-   * email type
-   */
-  email: PropTypes.bool
+  onChange: PropTypes.func
 };
 
 export default TextInput;
diff --git a/src/index.js b/src/index.js
index 721685e..722ec0a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -29,11 +29,11 @@ import Parallax from './Parallax';
 import Preloader from './Preloader';
 import ProgressBar from './ProgressBar';
 import Row from './Row';
+import RadioGroup from './RadioGroup';
 import SearchForm from './SearchForm';
 import Section from './Section';
 import SideNav from './SideNav';
 import SideNavItem from './SideNavItem';
-import Select from './Select';
 import Slide from './Slide';
 import Slider from './Slider';
 import Tab from './Tab';
@@ -75,11 +75,11 @@ export {
   Preloader,
   ProgressBar,
   Row,
+  RadioGroup,
   SearchForm,
   Section,
   SideNav,
   SideNavItem,
-  Select,
   Slide,
   Slider,
   Tab,
diff --git a/stories/Checkbox.stories.js b/stories/Checkbox.stories.js
index 5b489bd..f162bb7 100644
--- a/stories/Checkbox.stories.js
+++ b/stories/Checkbox.stories.js
@@ -2,7 +2,7 @@ import React from 'react';
 import { storiesOf } from '@storybook/react';
 import Checkbox from '../src/Checkbox';
 
-const stories = storiesOf('components/Checkbox', module);
+const stories = storiesOf('javascript/Checkbox', module);
 
 stories.addParameters({
   info: {
diff --git a/stories/RadioGroup.stories.js b/stories/RadioGroup.stories.js
new file mode 100644
index 0000000..63cf91c
--- /dev/null
+++ b/stories/RadioGroup.stories.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import RadioGroup from '../src/RadioGroup';
+
+const stories = storiesOf('components/RadioGroup', module);
+
+stories.addParameters({
+  info: {
+    text: `Radio Buttons are used when the user must make
+     only one selection out of a group of items.
+     Radios are added to a group by default.`
+  }
+});
+
+stories.add('Default', () => (
+  <RadioGroup
+    name="size"
+    label="T-Shirt Size"
+    onChange={(evt) => console.log(evt.target.value)}
+    options={[
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]}
+  />
+));
+
+stories.add('Predefined value', () => (
+  <RadioGroup
+    name="size"
+    label="T-Shirt Size"
+    value="xl"
+    options={[
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]}
+  />
+));
+
+stories.add('with gap', () => (
+  <RadioGroup
+    name="size"
+    withGap
+    label="T-Shirt Size"
+    value="xl"
+    options={[
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]}
+  />
+));
+
+stories.add('disabled', () => (
+  <RadioGroup
+    name="size"
+    disabled
+    label="T-Shirt Size"
+    value="xl"
+    options={[
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]}
+  />
+));
+
+stories.add('with classnames', () => (
+  <RadioGroup
+    name="size"
+    label="T-Shirt Size"
+    radioClassNames="teal-text"
+    options={[
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]}
+  />
+));
diff --git a/stories/Select.stories.js b/stories/Select.stories.js
deleted file mode 100644
index 79eddec..0000000
--- a/stories/Select.stories.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from 'react';
-import { storiesOf } from '@storybook/react';
-import Select from '../src/Select';
-
-const stories = storiesOf('components/Select', module);
-
-stories.addParameters({
-  info: {
-    text: `Select allows user input through specified options.`
-  }
-});
-
-stories.add('Default', () => (
-  <Select>
-    <option value="" disabled selected>Choose your option</option>
-    <option value="1">Option 1</option>
-    <option value="2">Option 2</option>
-    <option value="3">Option 3</option>
-  </Select>
-));
-
-stories.add('Multiple', () => (
-  <Select multiple>
-    <option value="" disabled selected>Choose your option</option>
-    <option value="1">Option 1</option>
-    <option value="2">Option 2</option>
-    <option value="3">Option 3</option>
-  </Select>
-));
-
-stories.add('Label', () => (
-  <Select label="Choose your option">
-    <option value="1">Option 1</option>
-    <option value="2" selected>Option 2</option>
-    <option value="3">Option 3</option>
-  </Select>
-));
-
-stories.add('Disabled', () => (
-  <Select disabled>
-    <option value="1">Option 1</option>
-    <option value="2" selected>Option 2</option>
-    <option value="3">Option 3</option>
-  </Select>
-));
-
-stories.add('Browser default', () => (
-  <Select browserDefault>
-    <option value="1">Option 1</option>
-    <option value="2" selected>Option 2</option>
-    <option value="3">Option 3</option>
-  </Select>
-));
diff --git a/stories/TextInput.stories.js b/stories/TextInput.stories.js
deleted file mode 100644
index d48974c..0000000
--- a/stories/TextInput.stories.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from 'react';
-import { storiesOf } from '@storybook/react';
-import TextInput from '../src/TextInput';
-
-const stories = storiesOf('components/TextInput', module);
-
-stories.addParameters({
-  info: {
-    text: `Text fields allow user input. The border should light
-     up simply and clearly indicating which field the user is 
-     currently editing.
-     The validate prop leverages HTML5 validation and will add
-      a valid and invalid class accordingly. If you don't want 
-      the Green and Red validation states, just remove the validate prop.`
-  }
-});
-
-stories.add('Default', () => (
-  <TextInput />
-));
-
-stories.add('Label', () => (
-  <TextInput label="First Name" />
-));
-
-stories.add('Placeholder', () => (
-  <TextInput placeholder="First Name" />
-));
-
-stories.add('Predefined value', () => (
-  <TextInput value="John" />
-));
-
-stories.add('Disabled', () => (
-  <TextInput disabled value="John" />
-));
-
-stories.add('Password', () => (
-  <TextInput password label="Password" />
-));
-
-stories.add('Email validate', () => (
-  <TextInput email validate label="Email" />
-));
-
-stories.add('with custom error/success', () => (
-  <TextInput email validate label="Email" error="Wrong Email sir" success="Great" />
-));
-
-stories.add('with Icon', () => (
-  <TextInput icon="email" label="Email" />
-));


Test patch:
diff --git a/test/RadioGroup.spec.js b/test/RadioGroup.spec.js
new file mode 100644
index 0000000..611ede5
--- /dev/null
+++ b/test/RadioGroup.spec.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import RadioGroup from '../src/RadioGroup';
+
+describe('<RadioGroup />', () => {
+  let wrapper;
+  const mockOnChange = jest.fn();
+
+  const defaultProps = {
+    name: 'size',
+    label: 'T-Shirt Size',
+    onChange: mockOnChange,
+    options: [
+      { label: 'XL', value: 'xl' },
+      { label: 'L', value: 'l' },
+      { label: 'M', value: 'm' }
+    ]
+  };
+
+  test('renders', () => {
+    wrapper = shallow(<RadioGroup {...defaultProps} />);
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('with predefined value', () => {
+    wrapper = shallow(<RadioGroup value="l" {...defaultProps} />);
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('with gap', () => {
+    wrapper = shallow(<RadioGroup withGap {...defaultProps} />);
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('disabled', () => {
+    wrapper = shallow(<RadioGroup disabled {...defaultProps} />);
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('with classnames', () => {
+    wrapper = shallow(<RadioGroup radioClassNames="red" {...defaultProps} />);
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('onChange callback', () => {
+    wrapper = shallow(<RadioGroup {...defaultProps} />);
+    wrapper
+      .find('input')
+      .first()
+      .simulate('change');
+    expect(mockOnChange).toHaveBeenCalled();
+  });
+});
diff --git a/test/Select.spec.js b/test/Select.spec.js
deleted file mode 100644
index a169c26..0000000
--- a/test/Select.spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import React from 'react';
-import { shallow, mount } from 'enzyme';
-import Select from '../src/Select';
-import mocker from './helper/new-mocker';
-
-describe('<Select />', () => {
-  let wrapper;
-
-  test('handles layout classes', () => {
-    wrapper = shallow(<Select s={4} m={6} />);
-
-    expect(wrapper.hasClass('input-field')).toBeTruthy();
-    expect(wrapper.hasClass('col')).toBeTruthy();
-    expect(wrapper.hasClass('s4')).toBeTruthy();
-    expect(wrapper.hasClass('m6')).toBeTruthy();
-  });
-
-  test('handles removing layout classes', () => {
-    wrapper = shallow(<Select s={4} m={6} noLayout />);
-
-    expect(wrapper.hasClass('input-field')).toBeTruthy();
-    expect(wrapper.hasClass('col')).toBeFalsy();
-    expect(wrapper.hasClass('s4')).toBeFalsy();
-    expect(wrapper.hasClass('m6')).toBeFalsy();
-  });
-
-  test('renders browserDefault', () => {
-    wrapper = shallow(<Select browserDefault />);
-    expect(wrapper.find('select').hasClass('browser-default')).toBeTruthy();
-  });
-
-  test('renders label', () => {
-    wrapper = shallow(<Select label="Name" />);
-    expect(wrapper.find('label').text()).toEqual('Name');
-  });
-
-  test('handles validate', () => {
-    wrapper = shallow(<Select validate />);
-    expect(wrapper.find('select.validate')).toHaveLength(1);
-  });
-
-  test('handles selectClassName', () => {
-    wrapper = shallow(<Select validate selectClassName={'hello red'} />);
-    expect(wrapper.find('select.hello.red.validate')).toHaveLength(1);
-  });
-
-  test('calls onChange if provided', () => {
-    wrapper = shallow(<Select />);
-    wrapper.setState({ value: 'hello' });
-    expect(wrapper.find('select').prop('value')).toEqual('hello');
-  });
-
-  test('with icon', () => {
-    wrapper = shallow(<Select icon="cloud" />);
-    expect(wrapper.find('i.material-icons.prefix')).toHaveLength(1);
-  });
-
-  test('renders options', () => {
-    wrapper = shallow(
-      <Select>
-        <option value={1}>1</option>
-        <option value={2}>2</option>
-      </Select>
-    );
-
-    expect(wrapper.find('option')).toHaveLength(2);
-  });
-
-  test('renders multiple', () => {
-    wrapper = shallow(<Select multiple />);
-    expect(wrapper.find('select.multiple')).toHaveLength(1);
-  });
-
-  describe('initialises', () => {
-    const selectInitMock = jest.fn();
-    const selectInstanceDestroyMock = jest.fn();
-    const selectMock = {
-      init: (el, options) => {
-        selectInitMock(options);
-        return {
-          destroy: selectInstanceDestroyMock
-        };
-      }
-    };
-    const restore = mocker('FormSelect', selectMock);
-
-    beforeEach(() => {
-      selectInitMock.mockClear();
-      selectInstanceDestroyMock.mockClear();
-    });
-
-    test('calls FormSelect', () => {
-      mount(<Select />);
-
-      expect(selectInitMock).toHaveBeenCalledTimes(1);
-    });
-  });
-});
diff --git a/test/TextInput.spec.js b/test/TextInput.spec.js
index 8d4eea9..4a082d8 100644
--- a/test/TextInput.spec.js
+++ b/test/TextInput.spec.js
@@ -44,10 +44,16 @@ describe('<TextInput />', () => {
   });
 
   test('handles other types', () => {
-    wrapper = shallow(<TextInput password />);
+    wrapper = shallow(<TextInput type="password" />);
     expect(wrapper.find('input').prop('type')).toEqual('password');
   });
 
+  test('calls onChange if provided', () => {
+    wrapper = shallow(<TextInput />);
+    wrapper.setState({ value: 'hello' });
+    expect(wrapper.find('input').prop('value')).toEqual('hello');
+  });
+
   test('with icon', () => {
     wrapper = shallow(<TextInput icon="cloud" />);
     expect(wrapper.find('i.material-icons.prefix')).toHaveLength(1);
diff --git a/test/__snapshots__/RadioGroup.spec.js.snap b/test/__snapshots__/RadioGroup.spec.js.snap
new file mode 100644
index 0000000..01da649
--- /dev/null
+++ b/test/__snapshots__/RadioGroup.spec.js.snap
@@ -0,0 +1,287 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`<RadioGroup /> disabled 1`] = `
+<Fragment>
+  <label
+    htmlFor="radio0"
+    key="radio0"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      disabled={true}
+      id="radio0"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="xl"
+    />
+    <span>
+      XL
+    </span>
+  </label>
+  <label
+    htmlFor="radio1"
+    key="radio1"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      disabled={true}
+      id="radio1"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="l"
+    />
+    <span>
+      L
+    </span>
+  </label>
+  <label
+    htmlFor="radio2"
+    key="radio2"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      disabled={true}
+      id="radio2"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="m"
+    />
+    <span>
+      M
+    </span>
+  </label>
+</Fragment>
+`;
+
+exports[`<RadioGroup /> renders 1`] = `
+<Fragment>
+  <label
+    htmlFor="radio0"
+    key="radio0"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio0"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="xl"
+    />
+    <span>
+      XL
+    </span>
+  </label>
+  <label
+    htmlFor="radio1"
+    key="radio1"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio1"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="l"
+    />
+    <span>
+      L
+    </span>
+  </label>
+  <label
+    htmlFor="radio2"
+    key="radio2"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio2"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="m"
+    />
+    <span>
+      M
+    </span>
+  </label>
+</Fragment>
+`;
+
+exports[`<RadioGroup /> with classnames 1`] = `
+<Fragment>
+  <label
+    className="red"
+    htmlFor="radio0"
+    key="radio0"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio0"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="xl"
+    />
+    <span>
+      XL
+    </span>
+  </label>
+  <label
+    className="red"
+    htmlFor="radio1"
+    key="radio1"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio1"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="l"
+    />
+    <span>
+      L
+    </span>
+  </label>
+  <label
+    className="red"
+    htmlFor="radio2"
+    key="radio2"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio2"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="m"
+    />
+    <span>
+      M
+    </span>
+  </label>
+</Fragment>
+`;
+
+exports[`<RadioGroup /> with gap 1`] = `
+<Fragment>
+  <label
+    htmlFor="radio0"
+    key="radio0"
+  >
+    <input
+      className="with-gap"
+      defaultChecked={false}
+      id="radio0"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="xl"
+    />
+    <span>
+      XL
+    </span>
+  </label>
+  <label
+    htmlFor="radio1"
+    key="radio1"
+  >
+    <input
+      className="with-gap"
+      defaultChecked={false}
+      id="radio1"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="l"
+    />
+    <span>
+      L
+    </span>
+  </label>
+  <label
+    htmlFor="radio2"
+    key="radio2"
+  >
+    <input
+      className="with-gap"
+      defaultChecked={false}
+      id="radio2"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="m"
+    />
+    <span>
+      M
+    </span>
+  </label>
+</Fragment>
+`;
+
+exports[`<RadioGroup /> with predefined value 1`] = `
+<Fragment>
+  <label
+    htmlFor="radio0"
+    key="radio0"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio0"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="xl"
+    />
+    <span>
+      XL
+    </span>
+  </label>
+  <label
+    htmlFor="radio1"
+    key="radio1"
+  >
+    <input
+      className=""
+      defaultChecked={true}
+      id="radio1"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="l"
+    />
+    <span>
+      L
+    </span>
+  </label>
+  <label
+    htmlFor="radio2"
+    key="radio2"
+  >
+    <input
+      className=""
+      defaultChecked={false}
+      id="radio2"
+      name="size"
+      onChange={[MockFunction]}
+      type="radio"
+      value="m"
+    />
+    <span>
+      M
+    </span>
+  </label>
+</Fragment>
+`;