Skip to content

Commit

Permalink
Feature/button improvements (#19)
Browse files Browse the repository at this point in the history
* feat: Button style upgrades

* refactor(card): Moved theme values to component

* chore: Updated story

* refactor(Card): Moved theme to card folder

* refactor(button): Added button theme

* feat(theme): Split out base colors
  • Loading branch information
hachiojidev authored Oct 21, 2020
1 parent bb4c67e commit 576c2a1
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 119 deletions.
84 changes: 28 additions & 56 deletions src/components/Button/StyledButton.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,10 @@
import styled, { DefaultTheme } from "styled-components";
import { ButtonProps, variants } from "./types";
import { ButtonProps, ButtonThemeVariant, variants } from "./types";

interface ThemedProps extends ButtonProps {
theme: DefaultTheme;
}

const getBackground = ({ variant, disabled, theme }: ThemedProps) => {
if (disabled) {
return "#ddd";
}

switch (variant) {
case variants.OUTLINE:
case variants.TEXT:
return "transparent";
case variants.SECONDARY:
return theme.colors.tertiary;
case variants.PRIMARY:
default:
return theme.colors.primary;
}
};

const getBorder = ({ variant, disabled, theme }: ThemedProps) => {
if (disabled) {
return 0;
}

switch (variant) {
case variants.OUTLINE:
return `2px solid ${theme.colors.primary}`;
case variants.PRIMARY:
case variants.SECONDARY:
case variants.TEXT:
default:
return 0;
}
};

const getColor = ({ variant, disabled, theme }: ThemedProps) => {
if (disabled) {
return "#acaaaf";
}

switch (variant) {
case variants.PRIMARY:
return "#FFFFFF";
case variants.TEXT:
return theme.colors.text;
case variants.OUTLINE:
case variants.SECONDARY:
default:
return theme.colors.primary;
}
};

export const StartIcon = styled.span`
margin-right: 0.5em;
`;
Expand All @@ -63,12 +13,20 @@ export const EndIcon = styled.span`
margin-left: 0.5em;
`;

const getButtonVariantProp = (prop: keyof ButtonThemeVariant) => ({
theme,
variant = variants.PRIMARY,
}: ThemedProps) => {
return theme.button[variant][prop];
};

const StyledButton = styled.button<ButtonProps>`
align-items: center;
background-color: ${getBackground};
border: ${getBorder};
background-color: ${getButtonVariantProp("background")};
border: ${getButtonVariantProp("border")};
border-radius: 16px;
color: ${getColor};
box-shadow: ${getButtonVariantProp("boxShadow")};
color: ${getButtonVariantProp("color")};
cursor: pointer;
display: inline-flex;
font-family: inherit;
Expand All @@ -80,11 +38,25 @@ const StyledButton = styled.button<ButtonProps>`
outline: 0;
padding: ${({ size }) => (size === "sm" ? "0 16px" : "0 24px")};
&:hover:not(:disabled) {
opacity: 0.9;
&:hover:not(:disabled):not(:active) {
background-color: ${getButtonVariantProp("backgroundHover")};
border-color: ${getButtonVariantProp("borderColorHover")};
}
&:focus:not(:active) {
box-shadow: 0 0 0 2px ${({ theme }) => theme.colors.secondary};
}
&:active {
background-color: ${getButtonVariantProp("backgroundActive")};
box-shadow: ${getButtonVariantProp("boxShadowActive")};
}
&:disabled {
background-color: ${({ theme }) => theme.colors.backgroundDisabled};
border-color: ${({ theme }) => theme.colors.backgroundDisabled};
box-shadow: none;
color: ${({ theme }) => theme.colors.textDisabled};
cursor: not-allowed;
}
`;
Expand Down
6 changes: 3 additions & 3 deletions src/components/Button/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ export const Default: React.FC = () => {
</Button>
</Row>
<Row>
<Button variant="outline">Outline</Button>
<Button variant="outline" disabled>
<Button variant="tertiary">Tertiary</Button>
<Button variant="tertiary" disabled>
Disabled
</Button>
<Button variant="outline" size="sm">
<Button variant="tertiary" size="sm">
Small
</Button>
</Row>
Expand Down
16 changes: 7 additions & 9 deletions src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import React from "react";
import StyledButton, { StartIcon, EndIcon } from "./StyledButton";
import { ButtonProps, variants, sizes } from "./types";

const Button: React.FC<ButtonProps> = ({ startIcon, endIcon, children, ...props }) => {
return (
<StyledButton {...props}>
{startIcon && <StartIcon>{startIcon}</StartIcon>}
{children}
{endIcon && <EndIcon>{endIcon}</EndIcon>}
</StyledButton>
);
};
const Button: React.FC<ButtonProps> = ({ startIcon, endIcon, children, ...props }) => (
<StyledButton {...props}>
{startIcon && <StartIcon>{startIcon}</StartIcon>}
{children}
{endIcon && <EndIcon>{endIcon}</EndIcon>}
</StyledButton>
);

Button.defaultProps = {
variant: variants.PRIMARY,
Expand Down
67 changes: 67 additions & 0 deletions src/components/Button/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ButtonTheme, variants } from "./types";
import { lightColors, darkColors } from "../../theme/colors";

const { PRIMARY, SECONDARY, TERTIARY, TEXT } = variants;

export const light: ButtonTheme = {
[PRIMARY]: {
background: lightColors.primary,
backgroundActive: lightColors.primaryDark,
backgroundHover: lightColors.primaryBright,
border: 0,
borderColorHover: "currentColor",
boxShadow: "inset 0px -1px 0px rgba(14, 14, 44, 0.4)",
boxShadowActive: "inset 0px -1px 0px rgba(14, 14, 44, 0.4)",
color: "#FFFFFF",
},
[SECONDARY]: {
background: "transparent",
backgroundActive: "transparent",
backgroundHover: "transparent",
border: `2px solid ${lightColors.primary}`,
borderColorHover: lightColors.primaryBright,
boxShadow: "none",
boxShadowActive: "none",
color: lightColors.primary,
},
[TERTIARY]: {
background: lightColors.tertiary,
backgroundActive: lightColors.tertiary,
backgroundHover: lightColors.tertiary,
border: 0,
borderColorHover: "currentColor",
boxShadow: "none",
boxShadowActive: "none",
color: lightColors.primary,
},
[TEXT]: {
background: "transparent",
backgroundActive: "transparent",
backgroundHover: lightColors.tertiary,
border: 0,
borderColorHover: "currentColor",
boxShadow: "none",
boxShadowActive: "none",
color: lightColors.primary,
},
};

export const dark: ButtonTheme = {
[PRIMARY]: {
...light.primary,
},
[SECONDARY]: {
...light.secondary,
},
[TERTIARY]: {
...light.tertiary,
background: darkColors.tertiary,
backgroundActive: darkColors.tertiary,
backgroundHover: darkColors.tertiary,
color: darkColors.primary,
},
[TEXT]: {
...light.text,
backgroundHover: darkColors.tertiary,
},
};
17 changes: 16 additions & 1 deletion src/components/Button/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const sizes = {
export const variants = {
PRIMARY: "primary",
SECONDARY: "secondary",
OUTLINE: "outline",
TERTIARY: "tertiary",
TEXT: "text",
} as const;

Expand All @@ -21,3 +21,18 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
startIcon?: ReactNode;
endIcon?: ReactNode;
}

export type ButtonThemeVariant = {
background: string;
backgroundActive: string;
backgroundHover: string;
border: string | number;
borderColorHover: string;
boxShadow: string;
boxShadowActive: string;
color: string;
};

export type ButtonTheme = {
[key in Variants]: ButtonThemeVariant;
};
4 changes: 2 additions & 2 deletions src/components/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ interface CardProps {
}

const Card = styled.div<CardProps>`
background-color: ${({ theme }) => theme.colors.card.background};
border: 1px solid ${({ theme }) => theme.colors.card.borderColor};
background-color: ${({ theme }) => theme.card.background};
border: ${({ theme }) => theme.card.boxShadow};
border-radius: 32px;
box-shadow: ${({ theme }) => theme.shadows.level1};
color: ${({ theme }) => theme.colors.text};
Expand Down
11 changes: 11 additions & 0 deletions src/components/Card/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CardTheme } from "./types";

export const light: CardTheme = {
background: "#FFFFFF",
boxShadow: "1px solid rgba(14, 14, 44, 0.05)",
};

export const dark: CardTheme = {
background: "#2B223E",
boxShadow: "1px solid rgba(14, 14, 44, 0.05)",
};
4 changes: 4 additions & 0 deletions src/components/Card/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type CardTheme = {
background: string;
boxShadow: string;
};
39 changes: 23 additions & 16 deletions src/styled.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import "styled-components";
import { ButtonTheme } from "./components/Button/types";
import { CardTheme } from "./components/Card/types";

export type Breakpoints = string[];

Expand All @@ -10,24 +12,29 @@ export type MediaQueries = {
xl: string;
};

export type Colors = {
primary: string;
primaryBright: string;
primaryDark: string;
secondary: string;
tertiary: string;
success: string;
failure: string;
contrast: string;
input: string;
background: string;
backgroundDisabled: string;
text: string;
textDisabled: string;
textSubtle: string;
};

declare module "styled-components" {
export interface DefaultTheme {
colors: {
primary: string;
secondary: string;
tertiary: string;
success: string;
failure: string;
contrast: string;
input: string;
background: string;
text: string;
textSubtle: string;
card: {
background: string;
borderColor: string;
};
};
isDark: boolean;
colors: Colors;
button: ButtonTheme;
card: CardTheme;
scales: {
breakpoints: Breakpoints;
mediaQueries: MediaQueries;
Expand Down
35 changes: 35 additions & 0 deletions src/theme/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Colors } from "../styled.d";

export const baseColors = {
failure: "#ED4B9E",
primary: "#1FC7D4",
primaryBright: "#53DEE9",
primaryDark: "#0098A1",
secondary: "#7645D9",
success: "#31D0AA",
};

export const lightColors: Colors = {
...baseColors,
background: "#FAF9FA",
backgroundDisabled: "#E9EAEB",
contrast: "#191326",
input: "#F4F2F7",
tertiary: "#EFF4F5",
text: "#452A7A",
textDisabled: "#BDC2C4",
textSubtle: "#AEA0D6",
};

export const darkColors: Colors = {
...baseColors,
background: "#191326",
backgroundDisabled: "#524B63",
contrast: "#FFFFFF",
input: "#151021",
primaryDark: "#0098A1",
tertiary: "#293450",
text: "#ED4B9E",
textDisabled: "#302B38",
textSubtle: "#A28BD4",
};
23 changes: 7 additions & 16 deletions src/theme/dark.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import { DefaultTheme } from "styled-components";
import mediaQueries, { breakpoints } from "./mediaQueries";
import { dark as darkButton } from "../components/Button/theme";
import { dark as darkCard } from "../components/Card/theme";
import { darkColors } from "./colors";

const darkTheme: DefaultTheme = {
colors: {
primary: "#1FC7D4",
secondary: "#7645D9",
tertiary: "#293450",
success: "#31D0AA",
failure: "#ED4B9E",
contrast: "#FFFFFF",
input: "#151021",
background: "#191326",
text: "#ED4B9E",
textSubtle: "#ED4B9E",
card: {
background: "#2B223E",
borderColor: "rgba(14, 14, 44, 0.05)",
},
},
isDark: true,
button: darkButton,
colors: darkColors,
card: darkCard,
scales: {
breakpoints,
mediaQueries,
Expand Down
Loading

0 comments on commit 576c2a1

Please sign in to comment.