Skip to content

Commit c4bb628

Browse files
WesSouzaarturbien
authored andcommitted
feat(radio): convert to TypeScript and export types
1 parent 0b29e5f commit c4bb628

File tree

5 files changed

+73
-80
lines changed

5 files changed

+73
-80
lines changed

src/Radio/Radio.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Radio
33
menu: Components
44
---
55

6-
import Radio from './Radio';
6+
import { Radio } from './Radio';
77
import Fieldset from '../Fieldset/Fieldset';
88
import Window from '../Window/Window';
99
import WindowContent from '../WindowContent/WindowContent';

src/Radio/Radio.spec.js renamed to src/Radio/Radio.spec.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import React from 'react';
21
import { renderWithTheme } from '../../test/utils';
3-
import Radio from './Radio';
2+
import { Radio } from './Radio';
43

54
describe('<Radio />', () => {
65
describe('label', () => {
@@ -51,7 +50,7 @@ describe('<Radio />', () => {
5150
);
5251

5352
rerender(<Radio checked readOnly />);
54-
const checkbox = getByRole('radio');
53+
const checkbox = getByRole('radio') as HTMLInputElement;
5554

5655
expect(checkbox.checked).toBe(true);
5756
expect(getByRole('radio')).toHaveAttribute('checked');
@@ -66,7 +65,7 @@ describe('<Radio />', () => {
6665
<Radio checked readOnly />
6766
);
6867
rerender(<Radio checked={false} readOnly />);
69-
const checkbox = getByRole('radio');
68+
const checkbox = getByRole('radio') as HTMLInputElement;
7069

7170
expect(checkbox.checked).toBe(false);
7271
expect(getByRole('radio')).not.toHaveAttribute('checked');

src/Radio/Radio.stories.js renamed to src/Radio/Radio.stories.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import React, { useState } from 'react';
2-
import styled from 'styled-components';
1+
import { ComponentMeta } from '@storybook/react';
2+
import { useState } from 'react';
33
import {
4-
Radio,
54
Cutout,
5+
Divider,
66
Fieldset,
7-
Window,
8-
WindowContent,
97
List,
108
ListItem,
11-
Divider
9+
Radio,
10+
Window,
11+
WindowContent
1212
} from 'react95';
13+
import styled from 'styled-components';
1314

1415
const Wrapper = styled.div`
1516
padding: 5rem;
@@ -28,7 +29,7 @@ export default {
2829
title: 'Radio',
2930
component: Radio,
3031
decorators: [story => <Wrapper>{story()}</Wrapper>]
31-
};
32+
} as ComponentMeta<typeof Radio>;
3233

3334
export function Default() {
3435
const [state, setState] = useState('Pear');
Lines changed: 60 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1-
import React from 'react';
2-
import propTypes from 'prop-types';
1+
import React, { forwardRef } from 'react';
2+
import styled, { css, CSSProperties } from 'styled-components';
33

4-
import styled, { css } from 'styled-components';
54
import { createFlatBoxStyles } from '../common';
65
import { StyledCutout } from '../Cutout/Cutout';
76
import { StyledListItem } from '../ListItem/ListItem';
8-
97
import {
8+
LabelText,
109
size,
1110
StyledInput,
12-
StyledLabel,
13-
LabelText
11+
StyledLabel
1412
} from '../SwitchBase/SwitchBase';
13+
import { CommonStyledProps } from '../types';
14+
15+
type RadioVariant = 'default' | 'flat' | 'menu';
16+
17+
type RadioProps = {
18+
checked?: boolean;
19+
className?: string;
20+
disabled?: boolean;
21+
label?: string | number;
22+
name?: string;
23+
onChange?: React.ChangeEventHandler<HTMLInputElement>;
24+
style?: CSSProperties;
25+
value?: string | number | boolean;
26+
variant?: RadioVariant;
27+
} & React.InputHTMLAttributes<HTMLInputElement> &
28+
CommonStyledProps;
1529

1630
const sharedCheckboxStyles = css`
1731
width: ${size}px;
@@ -22,11 +36,15 @@ const sharedCheckboxStyles = css`
2236
justify-content: space-around;
2337
margin-right: 0.5rem;
2438
`;
25-
// had to overwrite box-shadow for StyledCheckbox since the default made checkbox too dark
26-
const StyledCheckbox = styled(StyledCutout)`
39+
40+
type StyledCheckboxProps = {
41+
$disabled: boolean;
42+
};
43+
44+
const StyledCheckbox = styled(StyledCutout)<StyledCheckboxProps>`
2745
${sharedCheckboxStyles}
28-
background: ${({ theme, isDisabled }) =>
29-
isDisabled ? theme.material : theme.canvas};
46+
background: ${({ $disabled, theme }) =>
47+
$disabled ? theme.material : theme.canvas};
3048
3149
&:before {
3250
content: '';
@@ -39,12 +57,12 @@ const StyledCheckbox = styled(StyledCutout)`
3957
box-shadow: none;
4058
}
4159
`;
42-
const StyledFlatCheckbox = styled.div`
60+
const StyledFlatCheckbox = styled.div<StyledCheckboxProps>`
4361
${createFlatBoxStyles()}
4462
${sharedCheckboxStyles}
4563
outline: none;
46-
background: ${({ theme, isDisabled }) =>
47-
isDisabled ? theme.flatLight : theme.canvas};
64+
background: ${({ $disabled, theme }) =>
65+
$disabled ? theme.flatLight : theme.canvas};
4866
&:before {
4967
content: '';
5068
display: inline-block;
@@ -66,9 +84,16 @@ const StyledMenuCheckbox = styled.div`
6684
outline: none;
6785
background: none;
6886
`;
87+
88+
type IconProps = {
89+
'data-testid': 'checkmarkIcon';
90+
$disabled: boolean;
91+
variant: RadioVariant;
92+
};
93+
6994
const Icon = styled.span.attrs(() => ({
7095
'data-testid': 'checkmarkIcon'
71-
}))`
96+
}))<IconProps>`
7297
position: absolute;
7398
content: '';
7499
display: inline-block;
@@ -78,23 +103,23 @@ const Icon = styled.span.attrs(() => ({
78103
height: 6px;
79104
transform: translate(-50%, -50%);
80105
border-radius: 50%;
81-
${({ variant, theme, isDisabled }) =>
106+
${({ $disabled, theme, variant }) =>
82107
variant === 'menu'
83108
? css`
84-
background: ${isDisabled
109+
background: ${$disabled
85110
? theme.materialTextDisabled
86111
: theme.materialText};
87112
filter: drop-shadow(
88113
1px 1px 0px
89-
${isDisabled ? theme.materialTextDisabledShadow : 'transparent'}
114+
${$disabled ? theme.materialTextDisabledShadow : 'transparent'}
90115
);
91116
`
92117
: css`
93-
background: ${isDisabled ? theme.checkmarkDisabled : theme.checkmark};
118+
background: ${$disabled ? theme.checkmarkDisabled : theme.checkmark};
94119
`}
95120
${StyledListItem}:hover & {
96-
${({ theme, isDisabled, variant }) =>
97-
!isDisabled &&
121+
${({ $disabled, theme, variant }) =>
122+
!$disabled &&
98123
variant === 'menu' &&
99124
css`
100125
background: ${theme.materialTextInvert};
@@ -108,28 +133,25 @@ const CheckboxComponents = {
108133
menu: StyledMenuCheckbox
109134
};
110135

111-
const Radio = React.forwardRef(function Radio(props, ref) {
112-
const {
113-
onChange,
114-
label,
115-
disabled,
116-
variant,
136+
const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(
137+
{
117138
checked,
118-
className,
119-
style,
139+
className = '',
140+
disabled = false,
141+
label = '',
142+
onChange,
143+
style = {},
144+
variant = 'default',
120145
...otherProps
121-
} = props;
122-
146+
},
147+
ref
148+
) {
123149
const CheckboxComponent = CheckboxComponents[variant];
124150

125151
return (
126-
<StyledLabel isDisabled={disabled} className={className} style={style}>
127-
<CheckboxComponent
128-
checked={checked}
129-
isDisabled={disabled}
130-
role='presentation'
131-
>
132-
{checked && <Icon isDisabled={disabled} variant={variant} />}
152+
<StyledLabel $disabled={disabled} className={className} style={style}>
153+
<CheckboxComponent $disabled={disabled} role='presentation'>
154+
{checked && <Icon $disabled={disabled} variant={variant} />}
133155
</CheckboxComponent>
134156
<StyledInput
135157
disabled={disabled}
@@ -145,33 +167,4 @@ const Radio = React.forwardRef(function Radio(props, ref) {
145167
);
146168
});
147169

148-
Radio.defaultProps = {
149-
onChange: undefined,
150-
name: null,
151-
value: undefined,
152-
checked: undefined,
153-
label: '',
154-
disabled: false,
155-
variant: 'default',
156-
className: '',
157-
style: {}
158-
};
159-
160-
Radio.propTypes = {
161-
onChange: propTypes.func,
162-
name: propTypes.string,
163-
value: propTypes.oneOfType([
164-
propTypes.string,
165-
propTypes.number,
166-
propTypes.bool
167-
]),
168-
label: propTypes.oneOfType([propTypes.string, propTypes.number]),
169-
checked: propTypes.bool,
170-
disabled: propTypes.bool,
171-
variant: propTypes.oneOf(['default', 'flat', 'menu']),
172-
// eslint-disable-next-line react/forbid-prop-types
173-
style: propTypes.any,
174-
className: propTypes.string
175-
};
176-
177-
export default Radio;
170+
export { Radio, RadioProps };

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export { default as LoadingIndicator } from './LoadingIndicator/LoadingIndicator
2222
export { default as NumberField } from './NumberField/NumberField';
2323
export * from './Panel/Panel';
2424
export { default as Progress } from './Progress/Progress';
25-
export { default as Radio } from './Radio/Radio';
25+
export * from './Radio/Radio';
2626
export { default as Select } from './Select/Select';
2727
export { default as Slider } from './Slider/Slider';
2828
export { default as Tab } from './Tab/Tab';

0 commit comments

Comments
 (0)