Skip to content

components: Button props #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions packages/components/src/Button/Default/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
.button {
@apply outline-none text-white font-semibold leading-relaxed;

&:focus {
@apply outline outline-button-2;
}

&:active {
box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.25);
}

&:disabled {
@apply cursor-default bg-[#C1C3D0] text-acc-darkgrey;

&:hover {
@apply bg-[#C1C3D0];
}
}
}

/* COLOR VARIANTS */

.color-default {
@apply bg-button-1 hover:bg-button-2;
}

.color-dark {
@apply bg-primary hover:bg-ld-darkestblue;
}

.color-red {
@apply bg-acc-red hover:bg-acc-hoverred;
}

.color-green {
@apply bg-acc-green hover:bg-acc-hovergreen;
}

.color-white {
@apply bg-white text-link-1 shadow-none;

&:hover {
@apply bg-white/70;
}
}

.color-gradient {
background: linear-gradient(92.21deg, #6db0fc 11.79%, #5deda2 113.81%);

&:hover {
background: linear-gradient(92.21deg, #6db0fc 30.79%, #5deda2 113.81%);
}

&:disabled {
background: linear-gradient(92.21deg, #6db0fc 11.79%, #5deda2 113.81%);
}
}

/* SHAPE VARIANTS */

.shape-default {
@apply rounded;
}

.shape-pill {
@apply rounded-full;
}

/* SIZE VARIANTS */

.size-small {
@apply px-4 py-2 text-sm;
}

.size-medium {
@apply px-6 py-2 text-base;
}

.size-large {
@apply px-8 py-2 text-lg;
}

/* ICON */

.withIcon {
@apply flex items-center justify-center;

svg {
@apply mr-2;
}
}

/* LOADING */

.loader {
@apply flex items-center;
}

.invis {
@apply invisible;
}
47 changes: 47 additions & 0 deletions packages/components/src/Button/Default/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import cx from "classnames";
import React from "react";
import ButtonLoader from "../Loader";
import { Props } from "../types";
import css from "./index.module.css";

function Button({
children,
className,
icon,
color = "default",
size = "medium",
shape = "default",
loading = false,
...props
}: Props) {
return (
<button
className={cx(
css.button,
css[`color-${color}`],
css[`shape-${shape}`],
css[`size-${size}`],
{ [css.withIcon]: !!icon },
className,
)}
type="button"
data-testid="default-button"
// These props need to come last
{...props}
>
{loading ? (
<div className={css.loader}>
<ButtonLoader loaded={false} />
<div className={css.invis}>{children}</div>
</div>
) : (
<>
{icon}
{children}
</>
)}
</button>
);
}

export default Button;
5 changes: 5 additions & 0 deletions packages/components/src/Button/Group/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.group {
button:not(:last-of-type) {
@apply mr-3;
}
}
18 changes: 18 additions & 0 deletions packages/components/src/Button/Group/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import cx from "classnames";
import React from "react";
import css from "./index.module.css";

type GroupProps = {
children: React.ReactNode;
className?: string;
};

function Group({ children, className }: GroupProps) {
return (
<div className={cx(css.group, className)} aria-label="button-group">
{children}
</div>
);
}

export default Group;
61 changes: 61 additions & 0 deletions packages/components/src/Button/Link/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.buttonLink {
@apply font-semibold text-sm leading-relaxed bg-transparent;

&:focus {
@apply outline-none widget-shadow-lightblue;
}

&:disabled {
@apply text-ld-darkgrey;

&:hover {
@apply text-ld-darkgrey;
}
}
}

.underlined {
@apply underline px-2;
}

/* COLOR VARIANTS */

.color-default {
@apply text-link-1 hover:text-link-2;
}

.color-dark {
@apply text-primary hover:text-acc-hoverblue;
}

.color-red {
@apply text-acc-red hover:text-acc-hoverred;
}

.color-green {
@apply text-acc-green hover:text-acc-hovergreen;
}

/* SIZE VARIANTS */

.size-small {
@apply text-sm;
}

.size-medium {
@apply text-base;
}

.size-large {
@apply text-lg;
}

/* ICON */

.withIcon {
@apply flex items-center justify-center;

svg {
@apply mr-2;
}
}
41 changes: 41 additions & 0 deletions packages/components/src/Button/Link/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import cx from "classnames";
import React from "react";
import { Props } from "../types";
import css from "./index.module.css";

type LinkProps = Props & {
underlined?: boolean;
};

function Link({
children,
className,
icon,
color = "default",
size = "medium",
underlined = false,
...props
}: LinkProps) {
return (
<button
className={cx(
css.buttonLink,
css[`color-${color}`],
css[`size-${size}`],
{
[css.withIcon]: !!icon,
[css.underlined]: underlined,
},
className,
)}
type="button"
// These props need to come last
{...props}
>
{icon}
{children}
</button>
);
}

export default Link;
65 changes: 65 additions & 0 deletions packages/components/src/Button/Loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
import ReactLoader from "react-loader";
import { useThemeContext } from "../tailwind/context";
import { staticColors } from "../tailwind/theme/base/colors";
import { IThemeColors } from "../tailwind/types";
import { Color } from "./types";

const loaderDefaultOptions = {
lines: 100,
length: 1,
width: 1,
radius: 4.5,
scale: 1.5,
corners: 1,
opacity: 0.25,
rotate: 0,
direction: 1,
speed: 0.75,
trail: 30,
fps: 20,
zIndex: 2e9,
shadow: false,
hwaccel: false,
position: "absolute",
fadeColor: "transparent",
};

type Props = {
loaded: boolean;
color?: Color;
};

export default function ButtonLoader(props: Props) {
const { convertThemeRGBToHex } = useThemeContext();
return (
<ReactLoader
{...props}
// uses default options, but overrides fields provided as props
options={{
...loaderDefaultOptions,
color:
getLoaderTailwindColor(convertThemeRGBToHex(), props.color) ?? "#fff",
}}
/>
);
}

function getLoaderTailwindColor(
convertedHex: IThemeColors,
color?: Color,
): string | undefined {
if (!color) return undefined;
switch (color) {
case "default":
return convertedHex["button-1"];
case "dark":
return convertedHex.primary;
case "red":
return staticColors["acc-red"];
case "green":
return staticColors["acc-green"];
default:
return "#fff";
}
}
Loading
Loading