Skip to content

Commit

Permalink
feat: implement Radio component
Browse files Browse the repository at this point in the history
  • Loading branch information
benny0642 committed May 3, 2022
1 parent cdfb6d4 commit df4e347
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 0 deletions.
76 changes: 76 additions & 0 deletions packages/core/src/Radio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import icBEM from './utils/icBEM';
import prefixClass from './utils/prefixClass';
import rowComp from './mixins/rowComp';
import Icon from './Icon';
import './styles/Radio.scss';

export const COMPONENT_NAME = prefixClass('radio');
const ROOT_BEM = icBEM(COMPONENT_NAME);
export const BEM = {
root: ROOT_BEM,
iconWrapper: ROOT_BEM.element('icon-wrapper'),
input: ROOT_BEM.element('input'),
button: ROOT_BEM.element('button'),
};

export const RADIO_BUTTON = <Icon type="empty" className={`${BEM.button}`} />;

function Radio({
input,
// <input> props
checked,
defaultChecked,
disabled,
onChange,
// React props
className,
children,
...otherProps
}) {
const inputProps = {
checked,
defaultChecked,
disabled,
onChange,
...input,
};
const rootClassName = classNames(className, COMPONENT_NAME);
return (
<div className={rootClassName} {...otherProps}>
<span className={BEM.iconWrapper}>
<input
type="radio"
className={BEM.input}
{...inputProps}
/>

{RADIO_BUTTON}
</span>
{children}
</div>
);
}

Radio.propTypes = {
input: PropTypes.objectOf(PropTypes.any),
checked: PropTypes.bool,
defaultChecked: PropTypes.bool,
disabled: PropTypes.bool,
onChange: PropTypes.func,
};

Radio.defaultProps = {
input: {},

checked: undefined,
defaultChecked: undefined,
disabled: false,
onChange: undefined,
};

export default rowComp()(Radio);
export { Radio as PureRadio };
29 changes: 29 additions & 0 deletions packages/core/src/styles/Radio.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@import "./mixins";

.#{$prefix}-radio {
&__icon-wrapper {
position: relative;
flex: 0 0 auto;
}

&__input {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
opacity: 0;
z-index: 2;
cursor: pointer;
}

&__button {
position: relative;
z-index: 1;
background: url('../icons/svg/radio-empty.svg');
}

&__input:checked + &__button,
&__input:checked + .#{$prefix}-iconlayout > &__button {
background: url('../icons/svg/radio-selected.svg');
}
}
86 changes: 86 additions & 0 deletions packages/storybook/examples/core/Radio.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import Radio, { PureRadio } from '@ichef/gypcrete/src/Radio';
import Avatar from '@ichef/gypcrete/src/Avatar';
import DebugBox from 'utils/DebugBox';

export default {
title: '@ichef/gypcrete|Radio',
component: PureRadio,
subcomponents: {
'rowComp()': Radio,
},
};

export function BasicUsage() {
const rdAvatar = (
<Avatar
type="square"
alt="John Doe"
src="https://api.adorable.io/avatars/285/johndoe@example.com"
/>
);

return (
<div>
<DebugBox>
<Radio basic="Checked Radio" checked />
</DebugBox>

<DebugBox>
<Radio
basic="Unchecked Radio"
aside="Secondary helps"
tag="New"
defaultChecked={false}
/>
</DebugBox>

<DebugBox>
<Radio
basic="Radio with avatar"
avatar={rdAvatar}
defaultChecked={false}
/>
</DebugBox>

<DebugBox>
<Radio
basic="Disabled Radio"
disabled
/>
</DebugBox>
</div>
);
}

export function RadioWithStatusExample() {
return (
<div>
<DebugBox>
<Radio
align="center"
basic="Count me in"
status="loading"
/>
</DebugBox>

<DebugBox>
<Radio
defaultChecked
align="reverse"
basic="Count me in"
status="success"
statusOptions={{ autohide: false }}
/>
</DebugBox>

<DebugBox>
<Radio
basic="Count me in"
status="error"
errorMsg="Unauthorized"
/>
</DebugBox>
</div>
);
}

0 comments on commit df4e347

Please sign in to comment.