mirror of
https://github.com/Hackdex-App/hackdex-website.git
synced 2026-05-06 21:16:14 -05:00
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
|
|
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
variant?: "primary" | "secondary" | "ghost";
|
|
size?: "sm" | "md" | "lg";
|
|
isLoading?: boolean;
|
|
};
|
|
|
|
const base =
|
|
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-60 disabled:cursor-not-allowed";
|
|
|
|
const variants: Record<string, string> = {
|
|
primary:
|
|
"bg-[var(--accent)] text-[var(--accent-foreground)] hover:bg-[var(--accent-700)]",
|
|
secondary:
|
|
"bg-white/10 text-foreground border border-white/10 hover:bg-white/15",
|
|
ghost: "bg-transparent text-foreground hover:bg-white/5",
|
|
};
|
|
|
|
const sizes: Record<string, string> = {
|
|
sm: "h-9 px-3 text-sm",
|
|
md: "h-11 px-4 text-sm",
|
|
lg: "h-12 px-5 text-base",
|
|
};
|
|
|
|
export default function Button({
|
|
className,
|
|
variant = "primary",
|
|
size = "md",
|
|
isLoading,
|
|
children,
|
|
...props
|
|
}: ButtonProps) {
|
|
return (
|
|
<button
|
|
className={`${base} ${variants[variant]} ${sizes[size]} ${className ?? ""}`}
|
|
{...props}
|
|
>
|
|
{isLoading ? (
|
|
<span className="relative">
|
|
<span className="opacity-0">{children}</span>
|
|
<span className="absolute inset-0 flex items-center justify-center">
|
|
<span className="h-4 w-4 animate-spin rounded-full border-2 border-white/30 border-t-white" />
|
|
</span>
|
|
</span>
|
|
) : (
|
|
children
|
|
)}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
|