Skip to content

Commit 2864fea

Browse files
committed
refactor(actions): port typescript (see notes)
the problem here is that when <Action> is used, it can be a <Button> or a <Link> or it can be an obfuscated version of those (see `withObfucscation`). What it becomes is dependent on the combination of props and its values that passed to <Action>. i'm either not good enough at typescript to know what to do here or maybe we would have to revisit this approach????
1 parent 929fa49 commit 2864fea

File tree

6 files changed

+207
-159
lines changed

6 files changed

+207
-159
lines changed
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
import React from "react";
2-
import PropTypes from "prop-types";
32
import { withTheme } from "styled-components";
43

54
import Button from "./Button";
65
import Link from "./Link";
76
import withObfuscation from "./withObfuscation";
87

8+
interface ActionProps extends React.PropsWithChildren {
9+
button: boolean
10+
obfuscated: boolean
11+
}
12+
913
const ObfButton = withObfuscation(Button);
1014
const ObfLink = withObfuscation(Link);
1115

12-
function Action(props) {
13-
const { obfuscated, button, ...restProps } = props;
16+
const Action: React.FC<ActionProps> = ({ obfuscated = false, button = false, ...props }) => {
1417
if (obfuscated) {
1518
if (button) {
16-
return <ObfButton {...restProps} />;
19+
return <ObfButton {...props} />;
1720
}
18-
return <ObfLink {...restProps} />;
21+
return <ObfLink {...props} />;
1922
}
23+
2024
if (button) {
21-
return <Button {...restProps} />;
25+
return <Button {...props} />;
2226
}
23-
return <Link {...restProps} />;
24-
}
2527

26-
Action.propTypes = {
27-
button: PropTypes.bool,
28-
obfuscated: PropTypes.bool
29-
};
28+
return <Link {...props} />;
29+
}
3030

3131
export default withTheme(Action);

lib/ui/components/actions/Button.js

Lines changed: 0 additions & 58 deletions
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React from "react";
2+
import { Link as GatsbyButton } from "gatsby";
3+
import styled from "styled-components";
4+
5+
import { defaultThm } from "ui/themes";
6+
import { font, time, track } from "ui/settings";
7+
import { setSpace } from "ui/mixins";
8+
9+
interface ButtonElProps {
10+
readonly $primary: boolean;
11+
readonly $block: boolean;
12+
}
13+
14+
interface ButtonProps extends React.PropsWithChildren {
15+
href: string;
16+
to: string;
17+
primary?: boolean;
18+
block?: boolean;
19+
onClick: () => void;
20+
theme?: {
21+
actionColor: string;
22+
};
23+
}
24+
25+
const ButtonEl = styled.a<ButtonElProps>`
26+
${setSpace("pam")};
27+
background-color: ${({ theme, $primary }) =>
28+
$primary ? (theme.actionColor ?? defaultThm.actionColor) : `transparent`};
29+
border: 2px solid ${({ theme }) => theme.decor};
30+
color: ${({ $primary, theme }) =>
31+
$primary
32+
? (theme.background ?? defaultThm.background)
33+
: (theme.actionColor ?? defaultThm.actionColor)};
34+
cursor: pointer;
35+
display: inline-block;
36+
font-family: ${font.sans};
37+
font-size: inherit;
38+
font-weight: 800;
39+
letter-spacing: ${track.x};
40+
line-height: 1em;
41+
outline: none;
42+
text-align: center;
43+
text-decoration: none;
44+
text-transform: uppercase;
45+
transition:
46+
box-shadow ${time.s},
47+
transform ${time.s};
48+
white-space: nowrap;
49+
width: ${({ $block }) => ($block ? `100%` : `auto`)};
50+
&:hover {
51+
box-shadow: 4px 4px 0 0 ${({ theme }) => theme.actionDecor};
52+
transform: translateX(-1px) translateY(-1px);
53+
}
54+
`;
55+
56+
const Button: React.FC<ButtonProps> = ({
57+
to,
58+
onClick,
59+
primary = false,
60+
block = false,
61+
...props
62+
}) => {
63+
if (to) {
64+
return (
65+
<ButtonEl
66+
as={GatsbyButton}
67+
to={to}
68+
theme={undefined}
69+
$primary={primary}
70+
$block={block}
71+
{...props}
72+
/>
73+
);
74+
}
75+
76+
if (onClick) {
77+
return (
78+
<ButtonEl
79+
as="button"
80+
type="button"
81+
onClick={onClick}
82+
$primary={primary}
83+
$block={block}
84+
{...props}
85+
/>
86+
);
87+
}
88+
89+
return <ButtonEl $primary={primary} $block={block} {...props} />;
90+
};
91+
92+
export default Button;
Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
1-
/* eslint jsx-a11y/anchor-has-content: 0 */
2-
import PropTypes from "prop-types";
3-
import { Link as GatsbyLink } from "gatsby";
41
import React from "react";
2+
import { Link as GatsbyLink } from "gatsby";
53
import styled from "styled-components";
64

75
import { defaultThm } from "ui/themes";
86
import { font, time, track } from "ui/settings";
97
import { setSpace } from "ui/mixins";
108

11-
const LinkEl = styled.a`
9+
interface LinkElProps {
10+
theme:
11+
| {
12+
actionColor: string;
13+
}
14+
| undefined;
15+
readonly $isActive: boolean;
16+
}
17+
18+
interface LinkProps extends React.PropsWithChildren {
19+
href: string;
20+
isActive: boolean;
21+
theme?: {
22+
actionColor: string;
23+
};
24+
onClick?: () => void;
25+
to?: string;
26+
}
27+
28+
const LinkEl = styled.a<LinkElProps>`
1229
${setSpace("pvx")};
1330
background: transparent;
14-
border-color: ${({ theme }) => theme.actionColorLt};
31+
border-color: ${({ theme }) => theme.actionColorLt ?? null};
1532
border-style: solid;
1633
border-width: 0 0 2px;
1734
color: ${({ theme }) => theme.actionColor ?? defaultThm.actionColor};
@@ -24,44 +41,38 @@ const LinkEl = styled.a`
2441
line-height: inherit;
2542
text-align: center;
2643
text-transform: uppercase;
27-
transition: border ${time.s}, transform ${time.s};
44+
transition:
45+
border ${time.s},
46+
transform ${time.s};
2847
white-space: nowrap;
2948
&:hover {
3049
border-color: ${({ theme }) => theme.actionColor ?? defaultThm.actionColor};
3150
transform: translateX(-1px) translateY(-1px);
3251
}
3352
${({ $isActive, theme }) =>
3453
$isActive
35-
? `
36-
border-color: ${theme.actionColor ?? defaultThm.actionColor};
37-
`
54+
? `border-color: ${theme.actionColor ?? defaultThm.actionColor};`
3855
: ``};
3956
`;
4057

41-
function Link(props) {
42-
const { onClick, to, isActive, ...restProps } = props;
58+
const Link: React.FC<LinkProps> = ({ to, onClick, isActive, ...props }) => {
4359
if (to) {
44-
return <LinkEl to={to} as={GatsbyLink} $isActive={isActive} {...restProps} theme={null} />;
60+
return (
61+
<LinkEl
62+
to={to}
63+
as={GatsbyLink}
64+
$isActive={isActive}
65+
{...props}
66+
theme={undefined}
67+
/>
68+
);
4569
}
70+
4671
if (onClick) {
47-
return <LinkEl onClick={onClick} as="a" $isActive={isActive} {...restProps} />;
72+
return <LinkEl onClick={onClick} as="a" $isActive={isActive} {...props} />;
4873
}
49-
return <LinkEl $isActive={isActive} {...restProps} />;
50-
}
5174

52-
Link.propTypes = {
53-
children: PropTypes.oneOfType([
54-
PropTypes.array,
55-
PropTypes.object,
56-
PropTypes.string
57-
]),
58-
href: PropTypes.string,
59-
onClick: PropTypes.func,
60-
theme: PropTypes.shape({
61-
actionColor: PropTypes.string
62-
}),
63-
to: PropTypes.string,
64-
isActive: PropTypes.bool
75+
return <LinkEl $isActive={isActive} {...props} />;
6576
};
6677

6778
export default Link;

lib/ui/components/actions/withObfuscation.js

Lines changed: 0 additions & 61 deletions
This file was deleted.

0 commit comments

Comments
 (0)