Skip to content

Commit

Permalink
feat(RadioButtonGroup): add new legendText prop, refactor stories
Browse files Browse the repository at this point in the history
  • Loading branch information
tw15egan committed Feb 25, 2021
1 parent b633233 commit e133b4e
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
.#{$prefix}--radio-button-group {
display: flex;
align-items: center;
margin-top: rem(6px);
}

// Remove spacing above collection of radio buttons if label is present
Expand Down
3 changes: 3 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4505,6 +4505,9 @@ Map {
],
"type": "oneOf",
},
"legendText": Object {
"type": "node",
},
"name": Object {
"isRequired": true,
"type": "string",
Expand Down
114 changes: 70 additions & 44 deletions packages/react/src/components/RadioButton/RadioButton-story.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,70 +9,96 @@ import React from 'react';
import { action } from '@storybook/addon-actions';

import { withKnobs, boolean, select, text } from '@storybook/addon-knobs';
import RadioButtonGroup from '../RadioButtonGroup';
import RadioButton from '../RadioButton';
import { RadioButton as OGRadioButton } from './RadioButton';
import RadioButtonSkeleton from '../RadioButton/RadioButton.Skeleton';
import mdx from './RadioButton.mdx';

const values = {
'Option 1': 'radio-1',
'Option 2': 'radio-2',
'Option 3': 'radio-3',
};

const orientations = {
'Horizontal (horizontal)': 'horizontal',
'Vertical (vertical)': 'vertical',
};

const labelPositions = {
'Left (left)': 'left',
'Right (right)': 'right',
};

const radioProps = () => ({
className: 'some-class',
name: text('Form item name (name)', 'test'),
value: text('Value (value)', 'standard'),
labelText: text('Label text (labelText)', 'Standard Radio Button'),
labelPosition: select(
'Label position (labelPosition)',
labelPositions,
'right'
),
disabled: boolean('Disabled (disabled)', false),
onChange: action('onChange'),
});
const props = {
group: () => ({
legendText: text(
'The label (legend) of the RadioButtonGroup (legendText)',
'Radio button heading'
),
name: text(
'The form control name (name in <RadioButtonGroup>)',
'radio-button-group'
),
valueSelected: select(
'Value of the selected button (valueSelected in <RadioButtonGroup>)',
values,
'radio-3'
),
orientation: select(
'Radio button orientation (orientation)',
orientations,
'horizontal'
),
labelPosition: select(
'Label position (labelPosition)',
labelPositions,
'right'
),
onChange: action('onChange'),
}),
radio: () => ({
className: 'some-class',
disabled: boolean('Disabled (disabled in <RadioButton>)', false),
labelText: text('The label of the RadioButton (labelText)', 'Option 1'),
}),
};

export default {
title: 'Components/RadioButton',
decorators: [withKnobs],
component: OGRadioButton,
subcomponents: {
RadioButtonSkeleton,
},

parameters: {
component: RadioButtonGroup,
docs: {
page: mdx,
},
},
};

export const Default = () => <RadioButton id="radio-1" {...radioProps()} />;

Default.parameters = {
info: {
text: `
Radio buttons are used when a list of two or more options are mutually exclusive,
meaning the user must select only one option. The example below shows how the Radio Button component
can be used as an uncontrolled component that is initially checked by setting the defaultChecked property
to true. To use the component in a controlled way, set the checked property instead.
`,
subcomponents: {
RadioButton,
},
},
};

export const Skeleton = () => (
<div>
<RadioButtonSkeleton />
</div>
);

Skeleton.storyName = 'skeleton';
export const Default = () => {
return (
<RadioButtonGroup
legendText="Radio button heading"
name="radio-button-group"
defaultSelected="radio-1">
<RadioButton labelText="Option 1" value="radio-1" id="radio-1" />
<RadioButton labelText="Option 2" value="radio-2" id="radio-2" />
<RadioButton labelText="Option 3" value="radio-3" id="radio-3" />
</RadioButtonGroup>
);
};

Skeleton.parameters = {
info: {
text: `
Placeholder skeleton state to use when content is loading.
`,
},
export const Playground = () => {
const radioProps = props.radio();
return (
<RadioButtonGroup labelText="Radio Button group" {...props.group()}>
<RadioButton value="radio-1" id="radio-1" {...radioProps} />
<RadioButton labelText="Option 2" value="radio-2" id="radio-2" />
<RadioButton labelText="Option 3" value="radio-3" id="radio-3" />
</RadioButtonGroup>
);
};
13 changes: 13 additions & 0 deletions packages/react/src/components/RadioButton/RadioButton.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@ import { Props } from '@storybook/addon-docs/blocks';

## Table of Contents

- [Overview](#overview)
- [Component API](#component-api)
- [Feedback](#feedback)

## Overview

Radio buttons represent a group of mutually exclusive choices, compared to
checkboxes that allow users to make one or more selections from a group. In use
cases where only one selection from a group is allowed, use the radio button
component instead of the checkbox.

<Preview>
<Story id="radiobutton--default" />
</Preview>

## Component API

<Props />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,30 @@ const { prefix } = settings;
describe('RadioButtonGroup', () => {
describe('renders as expected', () => {
const wrapper = mount(
<RadioButtonGroup defaultSelected="female" name="gender">
<RadioButtonGroup
defaultSelected="female"
name="gender"
legendText="Radio legend">
<RadioButton labelText="Male" value="male" />
<RadioButton labelText="Female" value="female" />
</RadioButtonGroup>
);

describe('wrapping div', () => {
const div = wrapper.first('div');
describe('wrapping fieldset', () => {
const fieldset = wrapper.find('fieldset');
const legend = wrapper.find('legend');

it('renders a fieldset', () => {
expect(fieldset.length).toEqual(1);
});

it('renders a div', () => {
expect(div.length).toEqual(1);
it('renders a legend if legendText is provided', () => {
expect(legend.length).toEqual(1);
});

it('sets classes that are passed via className prop', () => {
wrapper.setProps({ className: 'extra-class' });
expect(div.hasClass('extra-class'));
expect(fieldset.hasClass('extra-class'));
});

it('sets disabled attribute if disabled prop is set', () => {
Expand Down
21 changes: 18 additions & 3 deletions packages/react/src/components/RadioButtonGroup/RadioButtonGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export default class RadioButtonGroup extends React.Component {
*/
labelPosition: PropTypes.oneOf(['left', 'right']),

/**
* Provide a legend to the RadioButtonGroup input that you are
* exposing to the user
*/
legendText: PropTypes.node,

/**
* Specify the name of the underlying `<input>` nodes
*/
Expand Down Expand Up @@ -116,7 +122,13 @@ export default class RadioButtonGroup extends React.Component {
};

render() {
const { disabled, className, orientation, labelPosition } = this.props;
const {
disabled,
className,
orientation,
labelPosition,
legendText,
} = this.props;

const wrapperClasses = classNames(
`${prefix}--radio-button-group`,
Expand All @@ -130,9 +142,12 @@ export default class RadioButtonGroup extends React.Component {

return (
<div className={`${prefix}--form-item`}>
<div className={wrapperClasses} disabled={disabled}>
<fieldset className={wrapperClasses} disabled={disabled}>
{legendText && (
<legend className={`${prefix}--label`}>{legendText}</legend>
)}
{this.getRadioButtons()}
</div>
</fieldset>
</div>
);
}
Expand Down

This file was deleted.

0 comments on commit e133b4e

Please sign in to comment.