button-component #29
10
frontend/package-lock.json
generated
10
frontend/package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.16",
|
||||
"clsx": "^2.1.1",
|
||||
"openapi-fetch": "^0.13.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
@ -2033,6 +2034,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.16",
|
||||
"clsx": "^2.1.1",
|
||||
"openapi-fetch": "^0.13.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { ButtonHTMLAttributes, ReactNode } from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
export type ButtonVariant = "primary" | "secondary" | "red" | "green";
|
||||
export type ButtonSize = "sm" | "md" | "lg";
|
||||
@ -10,35 +11,36 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
}
|
||||
|
||||
const variantClasses: Record<ButtonVariant, string> = {
|
||||
primary: `
|
||||
bg-primary text-base-canvas
|
||||
border border-primary
|
||||
hover:bg-secondary hover:text-base-canvas
|
||||
hover:border hover:border-primary
|
||||
focus-visible:bg-base-canvas focus-visible:text-base-ink-strong
|
||||
focus-visible:border focus-visible:border-primary
|
||||
focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100
|
||||
`.trim(),
|
||||
secondary: `bg-base-canvas text-base-ink-strong
|
||||
border-solid [border-width:var(--border-width-sm)] border-base-ink-soft
|
||||
hover:bg-base-canvas hover:text-base-ink-strong
|
||||
hover:border-base-ink-medium
|
||||
focus-visible:bg-base-canvas focus-visible:text-base-ink-strong
|
||||
focus-visible:border-primary
|
||||
focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100
|
||||
`.trim(),
|
||||
red: `
|
||||
bg-other-red-100 text-su-white
|
||||
focus-visible:bg-base-canvas focus-visible:text-base-ink-strong
|
||||
focus-visible:border-primary focus-visible:border
|
||||
focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100
|
||||
`.trim(),
|
||||
green: `
|
||||
bg-other-green text-su-white
|
||||
focus-visible:bg-base-canvas focus-visible:text-base-ink-strong
|
||||
focus-visible:border-primary focus-visible:border
|
||||
focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100
|
||||
`.trim(),
|
||||
primary: clsx(
|
||||
|
stne3960 marked this conversation as resolved
Outdated
|
||||
"bg-primary text-base-canvas",
|
||||
"border border-primary",
|
||||
"hover:bg-secondary hover:text-base-canvas",
|
||||
"hover:border hover:border-primary",
|
||||
"focus-visible:bg-base-canvas focus-visible:text-base-ink-strong",
|
||||
"focus-visible:border focus-visible:border-primary",
|
||||
"focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100",
|
||||
),
|
||||
secondary: clsx(
|
||||
"bg-base-canvas text-base-ink-strong",
|
||||
"border-solid [border-width:var(--border-width-sm)] border-base-ink-soft",
|
||||
"hover:bg-base-canvas hover:text-base-ink-strong",
|
||||
"hover:border-base-ink-medium",
|
||||
"focus-visible:bg-base-canvas focus-visible:text-base-ink-strong",
|
||||
"focus-visible:border-primary",
|
||||
"focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100",
|
||||
),
|
||||
red: clsx(
|
||||
"bg-other-red-100 text-su-white",
|
||||
"focus-visible:bg-base-canvas focus-visible:text-base-ink-strong",
|
||||
"focus-visible:border-primary focus-visible:border",
|
||||
"focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100",
|
||||
),
|
||||
green: clsx(
|
||||
"bg-other-green text-su-white",
|
||||
"focus-visible:bg-base-canvas focus-visible:text-base-ink-strong",
|
||||
"focus-visible:border-primary focus-visible:border",
|
||||
"focus-visible:outline focus-visible:outline-[length:var(--border-width-lg)] focus-visible:outline-sky-100",
|
||||
),
|
||||
};
|
||||
|
||||
const sizeClasses: Record<ButtonSize, string> = {
|
||||
@ -62,14 +64,12 @@ export default function Button({
|
||||
}: ButtonProps) {
|
||||
const baseClasses = "inline-flex items-center justify-center cursor-pointer";
|
||||
|
||||
const classes = [
|
||||
const classes = clsx(
|
||||
baseClasses,
|
||||
variantClasses[variant],
|
||||
sizeClasses[size],
|
||||
className,
|
||||
]
|
||||
.filter(Boolean) // Filter out empty strings and undefined values so they won't pollute the class list
|
||||
.join(" ");
|
||||
);
|
||||
|
||||
return (
|
||||
<button className={classes} {...props}>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user
This is unwieldy. Any way to break it down or group them somehow? Like the border styles, focus styles, colors, and so on.
Is it necessary to repeat the prefix or can you do something like
hover:[a, b, c]instead ofhover:a hover:b hover:c?