Skip to content

Commit 07eb2b1

Browse files
committed
Button and IconButton add types --no-verify
1 parent 0b05e4f commit 07eb2b1

File tree

2 files changed

+83
-86
lines changed

2 files changed

+83
-86
lines changed

client/common/Button.tsx

Lines changed: 81 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import styled from 'styled-components';
4-
import { Link } from 'react-router-dom';
5-
4+
import { Link, LinkProps } from 'react-router-dom';
65
import { remSize, prop } from '../theme';
76

87
const kinds = {
98
primary: 'primary',
10-
secondary: 'secondary'
11-
};
9+
secondary:'secondary'
10+
// eslint-disable-next-line prettier/prettier
11+
} as const;
12+
13+
type Kind = keyof typeof kinds
1214

1315
const displays = {
1416
block: 'block',
1517
inline: 'inline'
16-
};
18+
} as const;
19+
20+
type Display = keyof typeof displays
21+
22+
type StyledButtonProps = {
23+
kind: Kind,
24+
display: Display
25+
}
1726

1827
// The '&&&' will increase the specificity of the
1928
// component's CSS so that it overrides the more
2029
// general global styles
21-
const StyledButton = styled.button`
30+
const StyledButton = styled.button<StyledButtonProps>`
2231
&&& {
2332
font-weight: bold;
2433
display: ${({ display }) =>
@@ -108,22 +117,76 @@ const StyledInlineButton = styled.button`
108117
}
109118
`;
110119

120+
const buttonTypes = {
121+
button: 'button',
122+
submit: 'submit'
123+
} as const;
124+
125+
type ButtonType = keyof typeof buttonTypes
126+
export type ButtonProps = {
127+
/**
128+
* The visible part of the button, telling the user what
129+
* the action is
130+
*/
131+
children?: React.ReactNode,
132+
/**
133+
If the button can be activated or not
134+
*/
135+
disabled?: boolean,
136+
/**
137+
* The display type of the button—inline or block
138+
*/
139+
display?: Display,
140+
/**
141+
* SVG icon to place after child content
142+
*/
143+
iconAfter?: React.ReactNode,
144+
/**
145+
* SVG icon to place before child content
146+
*/
147+
iconBefore?: React.ReactNode,
148+
/**
149+
* If the button content is only an SVG icon
150+
*/
151+
iconOnly?: boolean,
152+
/**
153+
* The kind of button - determines how it appears visually
154+
*/
155+
kind?: Kind,
156+
/**
157+
* Specifying an href will use an <a> to link to the URL
158+
*/
159+
href?: string | null,
160+
/**
161+
* An ARIA Label used for accessibility
162+
*/
163+
'aria-label'?: string | null,
164+
/**
165+
* Specifying a to URL will use a react-router Link
166+
*/
167+
to?: string | null,
168+
/**
169+
* If using a button, then type is defines the type of button
170+
*/
171+
type?: ButtonType,
172+
}
173+
111174
/**
112175
* A Button performs an primary action
113176
*/
114177
const Button = ({
115-
children,
116-
display,
117-
href,
118-
kind,
119-
iconBefore,
120-
iconAfter,
121-
iconOnly,
122-
'aria-label': ariaLabel,
123-
to,
124-
type,
178+
children = null,
179+
display = displays.block,
180+
href = null,
181+
kind = kinds.primary,
182+
iconBefore = null,
183+
iconAfter = null,
184+
iconOnly = false,
185+
'aria-label': ariaLabel = null,
186+
to = null,
187+
type = buttonTypes.button,
125188
...props
126-
}) => {
189+
}: ButtonProps) => {
127190
const hasChildren = React.Children.count(children) > 0;
128191
const content = (
129192
<>
@@ -132,11 +195,7 @@ const Button = ({
132195
{iconAfter}
133196
</>
134197
);
135-
let StyledComponent = StyledButton;
136-
137-
if (iconOnly) {
138-
StyledComponent = StyledInlineButton;
139-
}
198+
const StyledComponent: React.ElementType<any> = iconOnly ? StyledInlineButton : StyledButton;
140199

141200
if (href) {
142201
return (
@@ -181,69 +240,7 @@ const Button = ({
181240
);
182241
};
183242

184-
Button.defaultProps = {
185-
children: null,
186-
disabled: false,
187-
display: displays.block,
188-
iconAfter: null,
189-
iconBefore: null,
190-
iconOnly: false,
191-
kind: kinds.primary,
192-
href: null,
193-
'aria-label': null,
194-
to: null,
195-
type: 'button'
196-
};
197-
198243
Button.kinds = kinds;
199244
Button.displays = displays;
200245

201-
Button.propTypes = {
202-
/**
203-
* The visible part of the button, telling the user what
204-
* the action is
205-
*/
206-
children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
207-
/**
208-
If the button can be activated or not
209-
*/
210-
disabled: PropTypes.bool,
211-
/**
212-
* The display type of the button—inline or block
213-
*/
214-
display: PropTypes.oneOf(Object.values(displays)),
215-
/**
216-
* SVG icon to place after child content
217-
*/
218-
iconAfter: PropTypes.element,
219-
/**
220-
* SVG icon to place before child content
221-
*/
222-
iconBefore: PropTypes.element,
223-
/**
224-
* If the button content is only an SVG icon
225-
*/
226-
iconOnly: PropTypes.bool,
227-
/**
228-
* The kind of button - determines how it appears visually
229-
*/
230-
kind: PropTypes.oneOf(Object.values(kinds)),
231-
/**
232-
* Specifying an href will use an <a> to link to the URL
233-
*/
234-
href: PropTypes.string,
235-
/**
236-
* An ARIA Label used for accessibility
237-
*/
238-
'aria-label': PropTypes.string,
239-
/**
240-
* Specifying a to URL will use a react-router Link
241-
*/
242-
to: PropTypes.string,
243-
/**
244-
* If using a button, then type is defines the type of button
245-
*/
246-
type: PropTypes.oneOf(['button', 'submit'])
247-
};
248-
249246
export default Button;

client/common/IconButton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { ComponentType } from 'react';
22
import styled from 'styled-components';
3-
import Button from './Button';
3+
import Button, { ButtonProps } from './Button';
44
import { remSize } from '../theme';
55

66
const ButtonWrapper = styled(Button)`
@@ -16,7 +16,7 @@ export type IconProps = {
1616
};
1717

1818
export type IconButtonProps = Omit<
19-
React.ComponentProps<typeof Button>,
19+
ButtonProps,
2020
'iconBefore' | 'iconOnly' | 'display' | 'focusable'
2121
> & {
2222
icon?: ComponentType<IconProps> | null

0 commit comments

Comments
 (0)