From 95d12b880588290e172bd63d6c8e3bd95d2351d9 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 9 Oct 2023 15:48:14 +0200 Subject: [PATCH] feat(component): use native props for button --- .eslintrc.cjs | 9 +-- src/components/button/button.stories.tsx | 6 +- src/components/button/button.test.tsx | 39 +++++------- src/components/button/button.tsx | 79 +++++++++--------------- 4 files changed, 53 insertions(+), 80 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 10ed42f1..14acb10c 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -21,7 +21,7 @@ module.exports = { plugins: ["react", "@typescript-eslint", "prettier"], rules: { "import/prefer-default-export": "off", - "no-restricted-exports": ["error", {restrictDefaultExports: {direct: true}}], + "no-restricted-exports": ["error", { restrictDefaultExports: { direct: true } }], "react/react-in-jsx-scope": "off", "react/require-default-props": "off", "no-alert": "off", @@ -39,6 +39,7 @@ module.exports = { devDependencies: ["**/*.stories.tsx", "**/*.test.tsx", "**/*.test.ts"], }, ], + "react/jsx-props-no-spreading": "off", }, overrides: [ { @@ -56,13 +57,13 @@ module.exports = { "no-restricted-exports": "off", "react/jsx-props-no-spreading": "off", "import/prefer-default-export": "off", - } + }, }, { files: ["src/util/class-names.tsx"], rules: { "import/no-extraneous-dependencies": "off", - } - } + }, + }, ], }; diff --git a/src/components/button/button.stories.tsx b/src/components/button/button.stories.tsx index f50c3c27..2f633cce 100644 --- a/src/components/button/button.stories.tsx +++ b/src/components/button/button.stories.tsx @@ -4,7 +4,7 @@ import { Button, ButtonProps } from "./button"; import { ChatIcon, DiagramTreeIcon, LockIcon } from "../../icons"; import { hiddenArgControl } from "../../util/storybook-utils"; -const types: ButtonProps["type"][] = [ +const variants: ButtonProps["variant"][] = [ "primary", "secondary", "minimal", @@ -55,8 +55,8 @@ export const Types: Story = { argTypes: { type: hiddenArgControl }, render: ({ children, ...args }) => (
- {types.map((type) => ( - ))} diff --git a/src/components/button/button.test.tsx b/src/components/button/button.test.tsx index ad21bcf3..ba3d4c39 100644 --- a/src/components/button/button.test.tsx +++ b/src/components/button/button.test.tsx @@ -8,7 +8,11 @@ describe("Button", () => { it("renders a button with text and button type", () => { const text = "Button Type"; // ARRANGE - render(); + render( + + ); // ASSERT const button = screen.getByText(text); @@ -20,7 +24,7 @@ describe("Button", () => { const text = "Submit Type"; // ARRANGE render( - ); @@ -35,7 +39,7 @@ describe("Button", () => { const text = "Left icon"; // ARRANGE render( - ); @@ -51,7 +55,7 @@ describe("Button", () => { const text = "Right icon"; // ARRANGE render( - ); @@ -67,7 +71,11 @@ describe("Button", () => { const text = "Onclick button"; const mock = vi.fn(); // ARRANGE - render(); + render( + + ); // ASSERT const button = screen.getByText(text); @@ -82,7 +90,7 @@ describe("Button", () => { const mock = vi.fn(); // ARRANGE render( - ); @@ -96,29 +104,12 @@ describe("Button", () => { expect(mock).toHaveBeenCalledTimes(0); }); - it("renders a button with text and form", () => { - const text = "Form button"; - const mock = vi.fn(); - // ARRANGE - render( - - ); - - // ASSERT - const button = screen.getByText(text); - expect(button).toBeInTheDocument(); - expect(button).toHaveAttribute("type", "submit"); - expect(button).toHaveAttribute("form", "form-test"); - }); - it("renders a button with loading state", () => { const text = "Loading button"; const mock = vi.fn(); // ARRANGE render( - ); diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index 8ea05d3d..1de4d42d 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react/button-has-type */ import React from "react"; import { classNames } from "../../util/class-names"; import { Spinner } from "../spinner"; @@ -14,8 +15,6 @@ const buttonVariants = { "bg-neutral-0 text-danger-500 border border-danger-400 hover:bg-danger-50 hover:text-danger-600 active:border-danger-700 active:text-danger-700 active:bg-danger-100 focus:ring-2 focus:ring-danger-100 focus:text-danger-600 disabled:border-danger-100 disabled:text-danger-100 disabled:bg-neutral-0 fill-danger-600 disabled:fill-danger-100", }; -export type ButtonType = keyof typeof buttonVariants; - const iconVariants = { primary: "text-neutral-0", secondary: @@ -26,60 +25,42 @@ const iconVariants = { "danger-secondary": "", }; -export interface ButtonProps { - className?: string; - children: string; - type?: ButtonType; - onClick: () => void; +export interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> { + variant?: keyof typeof buttonVariants; loading?: boolean; LeftIcon?: React.ElementType; RightIcon?: React.ElementType; - disabled?: boolean; - isSubmitButton?: boolean; - form?: string; } -const Button = React.forwardRef( - ( - { - className, - children, - onClick, - loading, - LeftIcon, - RightIcon, - disabled = false, - type = "primary", - isSubmitButton, - form, - }, - ref - ) => { - return ( - - ); - } -); + {RightIcon ? : null} + + ); +}; export { Button };