Skip to content

Commit

Permalink
components: Buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
tbantle22 committed Jan 24, 2024
1 parent a7a41a6 commit 2edb9bb
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@testing-library/jest-dom": "^6.2.0",
"@testing-library/react": "^14.1.2",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/babel__core": "^7",
"@types/babel__preset-env": "^7",
"@types/eslint": "^8",
Expand Down
42 changes: 42 additions & 0 deletions packages/components/src/Button/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* TODO(css): colors and shadows */
.button {
@apply rounded px-8 py-1 outline-none text-white font-semibold leading-relaxed button-shadow;

&:hover {
/* @apply bg-acc-linkblue; */
}

&:focus {
@apply outline-none;
}

&:disabled {
@apply cursor-default bg-gray-400;

&:hover {
@apply bg-gray-400;
}
}
}

.buttonLink {
@apply font-semibold leading-relaxed bg-transparent;

&:hover {
/* @apply text-acc-linkblue; */
}

&:disabled {
@apply text-gray-400;
}

&:focus {
@apply outline-none;
}
}

.buttonGroup {
button:not(:last-of-type) {
@apply mr-2;
}
}
89 changes: 89 additions & 0 deletions packages/components/src/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import cx from "classnames";
import React, { ButtonHTMLAttributes, ReactNode } from "react";
import css from "./index.module.css";

type ColorProps = {
// red?: boolean;
// green?: boolean;
// pill?: boolean;
// white?: boolean;
// gradientBg?: boolean;
};

type Props = ButtonHTMLAttributes<HTMLButtonElement> & ColorProps;

export default function Button({
children,
className,
// red = false,
// pill = false,
// green = false,
// gradientBg = false,
// white = false,
...props
}: Props) {
return (
<button
className={cx(
css.button,
// {
// [css.redBg]: red,
// [css.greenBg]: green,
// [css.pill]: pill,
// [css.gradientBg]: gradientBg,
// [css.whiteBg]: white,
// },
className,
)}
type="button"
// These props need to come last
{...props}
>
{children}
</button>
);
}

const Link = ({
children,
className,
// red = false,
// green = false,
...props
}: Props) => (
<button
className={cx(
css.buttonLink,
// {
// [css.redText]: red,
// [css.greenText]: green,
// },
className,
)}
type="button"
// These props need to come last
{...props}
>
{children}
</button>
);

Button.Link = Link;

type GroupProps = {
children: ReactNode;
className?: string;
["data-cy"]?: string;
};

const Group = ({ children, className, ...props }: GroupProps) => (
<div
className={cx(css.buttonGroup, className)}
aria-label="button-group"
data-cy={props["data-cy"]}
>
{children}
</div>
);

Button.Group = Group;
19 changes: 19 additions & 0 deletions packages/components/src/ButtonsNoError/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.stackedButton {
@apply flex flex-col;

button {
@apply mb-4 h-10;
}
}

.group {
@apply text-center mt-4;

> button:last-of-type {
@apply px-2;
}
}

.left {
@apply text-left;
}
36 changes: 36 additions & 0 deletions packages/components/src/ButtonsNoError/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import cx from "classnames";
import React, { ReactNode } from "react";
import Button from "../Button";
import css from "./index.module.css";

type Props = {
onCancel: () => void;
children: ReactNode;
left?: boolean;
className?: string;
["data-cy"]?: string;
stackedButton?: boolean;
};

export default function ButtonsNoError({
children,
onCancel,
left = false,
stackedButton = false,
...props
}: Props) {
return (
<div {...props} aria-label="buttons-no-error">
<Button.Group
className={cx(
css.group,
{ [css.left]: left },
{ [css.stackedButton]: stackedButton },
)}
>
{children}
<Button.Link onClick={onCancel}>cancel</Button.Link>
</Button.Group>
</div>
);
}
69 changes: 69 additions & 0 deletions packages/components/src/__tests__/ButtonsNoError.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import Button from "../Button";
import ButtonsNoError from "../ButtonsNoError";
import css from "./index.module.css";

function setup(jsx: React.ReactElement) {
return {
user: userEvent.setup(),
...render(jsx),
};
}

describe("test ButtonsNoError", () => {
it("renders buttons without error", async () => {
const onCancel = jest.fn();
const onClick = jest.fn();
const { user } = setup(
<ButtonsNoError onCancel={onCancel} className="class-name">
<button onClick={onClick} type="button">
Test Button
</button>
</ButtonsNoError>,
);

const container = screen.getByLabelText("buttons-no-error");
expect(container).toBeVisible();
expect(container).toHaveClass("class-name");

const cancelButton = screen.getByText("cancel");
expect(cancelButton).toBeVisible();
expect(onCancel).not.toHaveBeenCalled();
await user.click(cancelButton);
expect(onCancel).toHaveBeenCalled();

const testButton = screen.getByText("Test Button");
expect(testButton).toBeVisible();
expect(onClick).not.toHaveBeenCalled();
await user.click(testButton);
expect(onClick).toHaveBeenCalled();
});

it("renders buttons aligned left", () => {
render(
<ButtonsNoError onCancel={jest.fn()} left>
<button type="button">Test Button</button>
</ButtonsNoError>,
);

const buttonGroup = screen.getByLabelText("button-group");
expect(buttonGroup).toBeVisible();
expect(buttonGroup).toHaveClass(css.left);

expect(screen.getByText("cancel")).toBeVisible();
expect(screen.getByText("Test Button")).toBeVisible();
});

it("renders with data-cy attribute", () => {
render(
<ButtonsNoError data-cy="test-cy" onCancel={jest.fn()} left>
<Button>Test Button</Button>
</ButtonsNoError>,
);

const buttonGroup = screen.getByLabelText("buttons-no-error");
expect(buttonGroup).toHaveAttribute("data-cy", "test-cy");
});
});
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,7 @@ __metadata:
"@testing-library/jest-dom": "npm:^6.2.0"
"@testing-library/react": "npm:^14.1.2"
"@testing-library/react-hooks": "npm:^8.0.1"
"@testing-library/user-event": "npm:^14.5.2"
"@types/babel__core": "npm:^7"
"@types/babel__preset-env": "npm:^7"
"@types/eslint": "npm:^8"
Expand Down Expand Up @@ -2806,6 +2807,15 @@ __metadata:
languageName: node
linkType: hard

"@testing-library/user-event@npm:^14.5.2":
version: 14.5.2
resolution: "@testing-library/user-event@npm:14.5.2"
peerDependencies:
"@testing-library/dom": ">=7.21.4"
checksum: 68a0c2aa28a3c8e6eb05cafee29705438d7d8a9427423ce5064d44f19c29e89b5636de46dd2f28620fb10abba75c67130185bbc3aa23ac1163a227a5f36641e1
languageName: node
linkType: hard

"@tootallnate/once@npm:2":
version: 2.0.0
resolution: "@tootallnate/once@npm:2.0.0"
Expand Down

0 comments on commit 2edb9bb

Please sign in to comment.