Skip to content

Commit

Permalink
feat(radio): convert to TypeScript and export types
Browse files Browse the repository at this point in the history
  • Loading branch information
WesSouza authored and arturbien committed Jul 26, 2022
1 parent 0b29e5f commit c4bb628
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/Radio/Radio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Radio
menu: Components
---

import Radio from './Radio';
import { Radio } from './Radio';
import Fieldset from '../Fieldset/Fieldset';
import Window from '../Window/Window';
import WindowContent from '../WindowContent/WindowContent';
Expand Down
7 changes: 3 additions & 4 deletions src/Radio/Radio.spec.js → src/Radio/Radio.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { renderWithTheme } from '../../test/utils';
import Radio from './Radio';
import { Radio } from './Radio';

describe('<Radio />', () => {
describe('label', () => {
Expand Down Expand Up @@ -51,7 +50,7 @@ describe('<Radio />', () => {
);

rerender(<Radio checked readOnly />);
const checkbox = getByRole('radio');
const checkbox = getByRole('radio') as HTMLInputElement;

expect(checkbox.checked).toBe(true);
expect(getByRole('radio')).toHaveAttribute('checked');
Expand All @@ -66,7 +65,7 @@ describe('<Radio />', () => {
<Radio checked readOnly />
);
rerender(<Radio checked={false} readOnly />);
const checkbox = getByRole('radio');
const checkbox = getByRole('radio') as HTMLInputElement;

expect(checkbox.checked).toBe(false);
expect(getByRole('radio')).not.toHaveAttribute('checked');
Expand Down
15 changes: 8 additions & 7 deletions src/Radio/Radio.stories.js → src/Radio/Radio.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { ComponentMeta } from '@storybook/react';
import { useState } from 'react';
import {
Radio,
Cutout,
Divider,
Fieldset,
Window,
WindowContent,
List,
ListItem,
Divider
Radio,
Window,
WindowContent
} from 'react95';
import styled from 'styled-components';

const Wrapper = styled.div`
padding: 5rem;
Expand All @@ -28,7 +29,7 @@ export default {
title: 'Radio',
component: Radio,
decorators: [story => <Wrapper>{story()}</Wrapper>]
};
} as ComponentMeta<typeof Radio>;

export function Default() {
const [state, setState] = useState('Pear');
Expand Down
127 changes: 60 additions & 67 deletions src/Radio/Radio.js → src/Radio/Radio.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import React from 'react';
import propTypes from 'prop-types';
import React, { forwardRef } from 'react';
import styled, { css, CSSProperties } from 'styled-components';

import styled, { css } from 'styled-components';
import { createFlatBoxStyles } from '../common';
import { StyledCutout } from '../Cutout/Cutout';
import { StyledListItem } from '../ListItem/ListItem';

import {
LabelText,
size,
StyledInput,
StyledLabel,
LabelText
StyledLabel
} from '../SwitchBase/SwitchBase';
import { CommonStyledProps } from '../types';

type RadioVariant = 'default' | 'flat' | 'menu';

type RadioProps = {
checked?: boolean;
className?: string;
disabled?: boolean;
label?: string | number;
name?: string;
onChange?: React.ChangeEventHandler<HTMLInputElement>;
style?: CSSProperties;
value?: string | number | boolean;
variant?: RadioVariant;
} & React.InputHTMLAttributes<HTMLInputElement> &
CommonStyledProps;

const sharedCheckboxStyles = css`
width: ${size}px;
Expand All @@ -22,11 +36,15 @@ const sharedCheckboxStyles = css`
justify-content: space-around;
margin-right: 0.5rem;
`;
// had to overwrite box-shadow for StyledCheckbox since the default made checkbox too dark
const StyledCheckbox = styled(StyledCutout)`

type StyledCheckboxProps = {
$disabled: boolean;
};

const StyledCheckbox = styled(StyledCutout)<StyledCheckboxProps>`
${sharedCheckboxStyles}
background: ${({ theme, isDisabled }) =>
isDisabled ? theme.material : theme.canvas};
background: ${({ $disabled, theme }) =>
$disabled ? theme.material : theme.canvas};
&:before {
content: '';
Expand All @@ -39,12 +57,12 @@ const StyledCheckbox = styled(StyledCutout)`
box-shadow: none;
}
`;
const StyledFlatCheckbox = styled.div`
const StyledFlatCheckbox = styled.div<StyledCheckboxProps>`
${createFlatBoxStyles()}
${sharedCheckboxStyles}
outline: none;
background: ${({ theme, isDisabled }) =>
isDisabled ? theme.flatLight : theme.canvas};
background: ${({ $disabled, theme }) =>
$disabled ? theme.flatLight : theme.canvas};
&:before {
content: '';
display: inline-block;
Expand All @@ -66,9 +84,16 @@ const StyledMenuCheckbox = styled.div`
outline: none;
background: none;
`;

type IconProps = {
'data-testid': 'checkmarkIcon';
$disabled: boolean;
variant: RadioVariant;
};

const Icon = styled.span.attrs(() => ({
'data-testid': 'checkmarkIcon'
}))`
}))<IconProps>`
position: absolute;
content: '';
display: inline-block;
Expand All @@ -78,23 +103,23 @@ const Icon = styled.span.attrs(() => ({
height: 6px;
transform: translate(-50%, -50%);
border-radius: 50%;
${({ variant, theme, isDisabled }) =>
${({ $disabled, theme, variant }) =>
variant === 'menu'
? css`
background: ${isDisabled
background: ${$disabled
? theme.materialTextDisabled
: theme.materialText};
filter: drop-shadow(
1px 1px 0px
${isDisabled ? theme.materialTextDisabledShadow : 'transparent'}
${$disabled ? theme.materialTextDisabledShadow : 'transparent'}
);
`
: css`
background: ${isDisabled ? theme.checkmarkDisabled : theme.checkmark};
background: ${$disabled ? theme.checkmarkDisabled : theme.checkmark};
`}
${StyledListItem}:hover & {
${({ theme, isDisabled, variant }) =>
!isDisabled &&
${({ $disabled, theme, variant }) =>
!$disabled &&
variant === 'menu' &&
css`
background: ${theme.materialTextInvert};
Expand All @@ -108,28 +133,25 @@ const CheckboxComponents = {
menu: StyledMenuCheckbox
};

const Radio = React.forwardRef(function Radio(props, ref) {
const {
onChange,
label,
disabled,
variant,
const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(
{
checked,
className,
style,
className = '',
disabled = false,
label = '',
onChange,
style = {},
variant = 'default',
...otherProps
} = props;

},
ref
) {
const CheckboxComponent = CheckboxComponents[variant];

return (
<StyledLabel isDisabled={disabled} className={className} style={style}>
<CheckboxComponent
checked={checked}
isDisabled={disabled}
role='presentation'
>
{checked && <Icon isDisabled={disabled} variant={variant} />}
<StyledLabel $disabled={disabled} className={className} style={style}>
<CheckboxComponent $disabled={disabled} role='presentation'>
{checked && <Icon $disabled={disabled} variant={variant} />}
</CheckboxComponent>
<StyledInput
disabled={disabled}
Expand All @@ -145,33 +167,4 @@ const Radio = React.forwardRef(function Radio(props, ref) {
);
});

Radio.defaultProps = {
onChange: undefined,
name: null,
value: undefined,
checked: undefined,
label: '',
disabled: false,
variant: 'default',
className: '',
style: {}
};

Radio.propTypes = {
onChange: propTypes.func,
name: propTypes.string,
value: propTypes.oneOfType([
propTypes.string,
propTypes.number,
propTypes.bool
]),
label: propTypes.oneOfType([propTypes.string, propTypes.number]),
checked: propTypes.bool,
disabled: propTypes.bool,
variant: propTypes.oneOf(['default', 'flat', 'menu']),
// eslint-disable-next-line react/forbid-prop-types
style: propTypes.any,
className: propTypes.string
};

export default Radio;
export { Radio, RadioProps };
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export { default as LoadingIndicator } from './LoadingIndicator/LoadingIndicator
export { default as NumberField } from './NumberField/NumberField';
export * from './Panel/Panel';
export { default as Progress } from './Progress/Progress';
export { default as Radio } from './Radio/Radio';
export * from './Radio/Radio';
export { default as Select } from './Select/Select';
export { default as Slider } from './Slider/Slider';
export { default as Tab } from './Tab/Tab';
Expand Down

0 comments on commit c4bb628

Please sign in to comment.