Skip to content

Commit

Permalink
feat(Radio Button Group): Radio Button Group
Browse files Browse the repository at this point in the history
  • Loading branch information
ddsilva committed Apr 2, 2019
1 parent 88e7431 commit e963191
Show file tree
Hide file tree
Showing 11 changed files with 1,648 additions and 213 deletions.
28 changes: 14 additions & 14 deletions components/Button/buttonStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ const skin = props => {
border-color: ${hovered.border};
color: ${hovered.color};
}
`
: ''
}
&:focus {
box-shadow: ${focused.shadow};
background-color: ${focused.background};
border-color: ${focused.border};
color: ${focused.color};
}
&:focus {
box-shadow: ${focused.shadow};
background-color: ${focused.background};
border-color: ${focused.border};
color: ${focused.color};
}
&:active {
box-shadow: ${selected.shadow};
background-color: ${selected.background};
border-color: ${selected.border};
color: ${selected.color};
&:active {
box-shadow: ${selected.shadow};
background-color: ${selected.background};
border-color: ${selected.border};
color: ${selected.color};
}
`
: ''
}
`;
};
Expand Down
25 changes: 7 additions & 18 deletions components/RadioGroup/Radio.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import styled from 'styled-components';
import Colors from '../Colors';
import Label from '../shared/Label';
import HiddenRadio from './HiddenRadio';

const RadioMark = styled.span`
background-color: ${Colors.WHITE};
Expand All @@ -29,24 +30,11 @@ const RadioMark = styled.span`
}
`;

const StyledRadio = styled.input.attrs({
type: 'radio',
})`
border: 0;
height: 0;
margin: 0;
opacity: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 0;
`;

const RadioLabel = styled(Label)`
cursor: pointer;
user-select: none;
${StyledRadio} {
${HiddenRadio} {
:checked {
~ ${RadioMark} {
border-color: ${Colors.BLUE[500]};
Expand Down Expand Up @@ -76,7 +64,7 @@ const RadioLabel = styled(Label)`
${({ error }) =>
error &&
`
${StyledRadio} {
${HiddenRadio} {
:checked {
~ ${RadioMark} {
border-color: ${Colors.ERROR[500]};
Expand Down Expand Up @@ -118,7 +106,7 @@ const RadioLabel = styled(Label)`
cursor: not-allowed;
}
${StyledRadio} {
${HiddenRadio} {
:disabled {
~ ${RadioMark} {
background-color: ${Colors.BLACK[200]};
Expand Down Expand Up @@ -159,7 +147,7 @@ const RadioLabel = styled(Label)`
}
`}
${StyledRadio}:checked:disabled ~ ${RadioMark} {
${HiddenRadio}:checked:disabled ~ ${RadioMark} {
background-color: ${Colors.BLACK[400]};
border-color: ${Colors.BLACK[400]};
box-shadow: inset 0 0 0 3.5px ${Colors.WHITE};
Expand All @@ -176,9 +164,10 @@ const Radio = ({
...rest
}) => (
<RadioLabel error={error} disabled={disabled}>
<StyledRadio
<HiddenRadio
disabled={disabled}
onChange={e => onChange({ value, label }, e)}
value={value}
{...rest}
/>
<RadioMark />
Expand Down
83 changes: 55 additions & 28 deletions components/RadioGroup/RadioButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,34 @@ import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import ButtonGroupLabel from '../shared/ButtonGroupLabel';
import HiddenRadio from './HiddenRadio';
import Icon from '../Icon';

const StyledRadio = styled.input.attrs({
type: 'radio',
})`
border: 0;
height: 0;
margin: 0;
opacity: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 0;
const LockIcon = styled(Icon).attrs({
name: 'lock',
})``;

const ButtonIcon = styled(Icon)`
margin-right: 8px;
`;

const Wrapper = styled.div`
${({ inline }) =>
inline &&
`
display: inline-block;
vertical-align: top;
margin-right: 16px;
:last-child {
margin-right: 0;
}
`}
${LockIcon} {
margin-left: 8px;
font-size: 17px;
}
`;

const Radio = ({
Expand All @@ -24,47 +40,58 @@ const Radio = ({
onChange,
value,
checked,
icon,
inline,
...rest
}) => {
const skin = checked ? 'primary' : 'secondary';

return (
<ButtonGroupLabel
error={error}
disabled={disabled}
skin={skin}
checked={checked}
>
<StyledRadio
checked={checked}
<Wrapper inline={inline}>
<ButtonGroupLabel
error={error}
disabled={disabled}
onChange={e => onChange({ value, label }, e)}
{...rest}
/>
{children || label}
</ButtonGroupLabel>
skin={skin}
checked={checked}
>
{icon && <ButtonIcon name={icon} />}
<HiddenRadio
checked={checked}
disabled={disabled}
onChange={e => onChange({ value, label }, e)}
value={value}
{...rest}
/>
{children || label}
{disabled && <LockIcon />}
</ButtonGroupLabel>
</Wrapper>
);
};

Radio.displayName = 'RadioGroup.Radio';
Radio.displayName = 'RadioGroup.Button';

Radio.defaultProps = {
checked: false,
children: undefined,
disabled: false,
error: false,
children: undefined,
icon: undefined,
inline: false,
label: undefined,
onChange: () => {},
};

Radio.propTypes = {
checked: PropTypes.bool,
children: PropTypes.string,
disabled: PropTypes.bool,
error: PropTypes.bool,
children: PropTypes.string,
icon: PropTypes.string,
inline: PropTypes.bool,
label: PropTypes.string,
value: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string.isRequired,
};

export default Radio;
42 changes: 42 additions & 0 deletions components/RadioGroup/RadioButton.unit.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import renderer from 'react-test-renderer';
import RadioButton from './RadioButton';

describe('<RadioGroup.Radio />', () => {
describe('snapshot', () => {
it('simple', () => {
const component = <RadioButton value="Foo" label="Foo" />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('checked', () => {
const component = <RadioButton value="Foo" label="Foo" checked />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('inline', () => {
const component = <RadioButton value="Foo" label="Foo" inline />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('icon', () => {
const component = <RadioButton value="Foo" label="Foo" icon="check" />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('disabled', () => {
const component = <RadioButton value="Foo" label="Foo" disabled />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('error', () => {
const component = <RadioButton value="Foo" label="Foo" error />;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});

it('children', () => {
const component = <RadioButton value="Foo">Foo</RadioButton>;
expect(renderer.create(component).toJSON()).toMatchSnapshot();
});
});
});
26 changes: 17 additions & 9 deletions components/RadioGroup/RadioGroup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import RadioButton from './RadioButton';
const Group = styled(FieldGroup).attrs({
role: 'radiogroup',
})`
display: flex;
flex-direction: column;
position: relative;
`;

Expand All @@ -21,9 +19,11 @@ const ErrorLabel = styled(ErrorMessage)`
ErrorLabel.displayName = 'ErrorLabel';

const RadioGroup = ({
type,
children,
name,
error,
inline,
name,
onChange,
options,
value,
Expand All @@ -33,6 +33,7 @@ const RadioGroup = ({
name,
error: Boolean(error),
onChange,
inline,
};
const radioOptions = options.map(option =>
Object.assign({}, option, {
Expand All @@ -48,7 +49,10 @@ const RadioGroup = ({
checked: child.props.value === value ? true : undefined,
...commonProps,
}),
) || radioOptions.map(props => <Radio {...props} />);
) ||
radioOptions.map(props =>
type === 'button' ? <RadioButton {...props} /> : <Radio {...props} />,
);

return (
<Group {...rest}>
Expand All @@ -65,14 +69,17 @@ RadioGroup.Button = RadioButton;
* Group for Radio components.
*/
RadioGroup.defaultProps = {
value: undefined,
error: undefined,
type: 'radio',
children: undefined,
options: [],
error: undefined,
inline: false,
onChange: () => {},
options: [],
value: undefined,
};

RadioGroup.propTypes = {
type: PropTypes.oneOf(['radio', 'button']),
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
Expand All @@ -81,9 +88,10 @@ RadioGroup.propTypes = {
}),
),
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
PropTypes.arrayOf(PropTypes.element),
PropTypes.element,
]),
inline: PropTypes.bool,
onChange: PropTypes.func,
/** Initialize RadioGroup with a value */
value: PropTypes.string,
Expand Down
Loading

0 comments on commit e963191

Please sign in to comment.