From e2e8185d4c6c0d4b6e2212c11d5af35b2b342fa4 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 20 Nov 2023 12:04:17 +0100 Subject: [PATCH 1/2] feat(components): add support for anchor tag buttons --- package-lock.json | 8 ++-- package.json | 2 +- src/components/button/button.stories.tsx | 6 +++ src/components/button/button.tsx | 54 ++++++++++++++++-------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1bbab502..9cfa3609 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,7 @@ "eslint-plugin-tsdoc": "0.2.17", "jsdom": "^22.1.0", "prettier": "^3.0.3", - "prettier-plugin-tailwindcss": "0.5.5", + "prettier-plugin-tailwindcss": "0.5.7", "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -21636,9 +21636,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.5.tgz", - "integrity": "sha512-voy0CjWv/CM8yeaduv5ZwovovpTGMR5LbzlhGF+LtEvMJt9wBeVTVnW781hL38R/RcDXCJwN2rolsgr94B/n0Q==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.7.tgz", + "integrity": "sha512-4v6uESAgwCni6YF6DwJlRaDjg9Z+al5zM4JfngcazMy4WEf/XkPS5TEQjbD+DZ5iNuG6RrKQLa/HuX2SYzC3kQ==", "dev": true, "engines": { "node": ">=14.21.3" diff --git a/package.json b/package.json index a28d7b95..6b82449c 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "eslint-plugin-tsdoc": "0.2.17", "jsdom": "^22.1.0", "prettier": "^3.0.3", - "prettier-plugin-tailwindcss": "0.5.5", + "prettier-plugin-tailwindcss": "0.5.7", "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/components/button/button.stories.tsx b/src/components/button/button.stories.tsx index 2f633cce..0a89715b 100644 --- a/src/components/button/button.stories.tsx +++ b/src/components/button/button.stories.tsx @@ -44,6 +44,12 @@ export const WithIcons: Story = { RightIcon: icons.LockIcon, }, }; +export const AsAnchor: Story = { + args: { + as: "a", + href: "https://www.google.com", + }, +}; export const Loading: Story = { args: { loading: true }, }; diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index 1de4d42d..6b994ba5 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -25,12 +25,20 @@ const iconVariants = { "danger-secondary": "", }; -export interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> { +type ButtonOrLinkProps = + | (React.ButtonHTMLAttributes & { + as?: "button"; + }) + | (React.AnchorHTMLAttributes & { + as: "a"; + }); + +export type ButtonProps = { variant?: keyof typeof buttonVariants; loading?: boolean; LeftIcon?: React.ElementType; RightIcon?: React.ElementType; -} +} & ButtonOrLinkProps; const Button = ({ variant = "primary", @@ -41,24 +49,36 @@ const Button = ({ RightIcon, ...props }: ButtonProps) => { - return ( - ); }; From efe34efa516259ca3fc4283da162e3350e4b645f Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 20 Nov 2023 15:14:54 +0100 Subject: [PATCH 2/2] feat(components): use dynamic anchor tag and restrict href to anchor --- src/components/button/button.tsx | 35 ++++++++++---------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index 6b994ba5..18cf5faa 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -28,6 +28,7 @@ const iconVariants = { type ButtonOrLinkProps = | (React.ButtonHTMLAttributes & { as?: "button"; + href?: undefined; }) | (React.AnchorHTMLAttributes & { as: "a"; @@ -49,37 +50,23 @@ const Button = ({ RightIcon, ...props }: ButtonProps) => { + const HtmlTag = (props.as || "button") as React.ElementType; + const commonClasses = classNames( `group flex h-8 items-center gap-2 whitespace-nowrap rounded px-4 text-xs font-semibold focus:outline-none disabled:cursor-not-allowed`, buttonVariants[variant], className ); - const content = () => { - return ( - <> - {loading ? : null} - {LeftIcon && !loading ? ( - - ) : null} - {children} - {RightIcon ? : null} - - ); - }; - - if (props.as === "a") { - return ( - - {content()} - - ); - } - return ( - + + {loading ? : null} + {LeftIcon && !loading ? ( + + ) : null} + {children} + {RightIcon ? : null} + ); };