tailwind-ui-library/components/layout/Button.tsx
Benjamin Toby f73b56cdc4 Updates
2024-10-17 09:06:54 +01:00

159 lines
5.1 KiB
TypeScript

import {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
DetailedHTMLProps,
HTMLAttributeAnchorTarget,
} from "react";
import { twMerge } from "tailwind-merge";
import Loading from "../elements/Loading";
/**
* # Buttons
* @className twui-button-general
* @className twui-button-content-wrapper
* @className twui-button-primary
* @className twui-button-primary-outlined
* @className twui-button-primary-ghost
* @className twui-button-secondary
* @className twui-button-secondary-outlined
* @className twui-button-secondary-ghost
* @className twui-button-accent
* @className twui-button-accent-outlined
* @className twui-button-accent-ghost
* @className twui-button-gray
* @className twui-button-gray-outlined
* @className twui-button-gray-ghost
*/
export default function Button({
href,
target,
variant,
color,
linkProps,
loading,
...props
}: DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> & {
variant?: "normal" | "ghost" | "outlined";
color?: "primary" | "secondary" | "accent" | "gray";
href?: string;
target?: HTMLAttributeAnchorTarget;
loading?: boolean;
linkProps?: DetailedHTMLProps<
AnchorHTMLAttributes<HTMLAnchorElement>,
HTMLAnchorElement
>;
}) {
const finalClassName: string = (() => {
if (variant == "normal" || !variant) {
if (color == "primary" || !color)
return twMerge(
"bg-blue-500 hover:bg-blue-600 text-white",
"twui-button-primary"
);
if (color == "secondary")
return twMerge(
"bg-emerald-500 hover:bg-emerald-600 text-white",
"twui-button-secondary"
);
if (color == "accent")
return twMerge(
"bg-violet-500 hover:bg-violet-600 text-white",
"twui-button-accent"
);
if (color == "gray")
return twMerge(
"bg-slate-300 hover:bg-slate-200 text-slate-800",
"twui-button-gray"
);
} else if (variant == "outlined") {
if (color == "primary" || !color)
return twMerge(
"bg-transparent outline outline-1 outline-blue-500",
"text-blue-500",
"twui-button-primary-outlined"
);
if (color == "secondary")
return twMerge(
"bg-transparent outline outline-1 outline-emerald-500",
"text-emerald-500",
"twui-button-secondary-outlined"
);
if (color == "accent")
return twMerge(
"bg-transparent outline outline-1 outline-violet-500",
"text-violet-500",
"twui-button-accent-outlined"
);
if (color == "gray")
return twMerge(
"bg-transparent outline outline-1 outline-slate-300",
"text-slate-600",
"twui-button-gray-outlined"
);
} else if (variant == "ghost") {
if (color == "primary" || !color)
return twMerge(
"bg-transparent outline-none p-2",
"text-blue-500",
"twui-button-primary-ghost"
);
if (color == "secondary")
return twMerge(
"bg-transparent outline-none p-2",
"text-emerald-500",
"twui-button-secondary-ghost"
);
if (color == "accent")
return twMerge(
"bg-transparent outline-none p-2",
"text-violet-500",
"twui-button-accent-ghost"
);
if (color == "gray")
return twMerge(
"bg-transparent outline-none p-2",
"text-slate-600",
"twui-button-gray-ghost"
);
}
return "";
})();
const buttonComponent = (
<button
{...props}
className={twMerge(
"bg-blue-600 text-white text-base font-medium px-4 py-2 rounded",
"flex items-center justify-center relative transition-all",
"twui-button-general",
finalClassName,
props.className,
loading ? "pointer-events-none opacity-80" : "l"
)}
>
<div
className={twMerge(
"flex items-center gap-2",
loading ? "opacity-0" : "",
"twui-button-content-wrapper"
)}
>
{props.children}
</div>
{loading && <Loading className="absolute" />}
</button>
);
if (href)
return (
<a {...linkProps} href={href} target={target}>
{buttonComponent}
</a>
);
return buttonComponent;
}