Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(RadioButtonGroup): add new legendText prop, refactor stories #7846

Merged
merged 3 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.