- Created reusable UI components (Card, Button, Badge, Form, Icon) - Added PageIcon and NavIcon components with consistent styling - Refactored all pages to use new UI components - Added non-blocking image loading with skeleton for book covers - Created LibraryActions dropdown for library settings - Added emojis to buttons for better UX - Fixed Client Component issues with getBookCoverUrl
49 lines
1.2 KiB
TypeScript
49 lines
1.2 KiB
TypeScript
import { ButtonHTMLAttributes, ReactNode } from "react";
|
|
|
|
type ButtonVariant = "primary" | "secondary" | "danger" | "warning" | "ghost";
|
|
|
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
children: ReactNode;
|
|
variant?: ButtonVariant;
|
|
size?: "sm" | "md" | "lg";
|
|
}
|
|
|
|
const variantStyles: Record<ButtonVariant, string> = {
|
|
primary: "bg-primary text-white hover:bg-primary/90",
|
|
secondary: "border border-line text-muted hover:bg-muted/5",
|
|
danger: "bg-error text-white hover:bg-error/90",
|
|
warning: "bg-warning text-white hover:bg-warning/90",
|
|
ghost: "text-muted hover:text-foreground hover:bg-muted/5",
|
|
};
|
|
|
|
const sizeStyles: Record<string, string> = {
|
|
sm: "h-8 px-3 text-xs",
|
|
md: "h-10 px-4 text-sm",
|
|
lg: "h-12 px-6 text-base",
|
|
};
|
|
|
|
export function Button({
|
|
children,
|
|
variant = "primary",
|
|
size = "md",
|
|
className = "",
|
|
disabled,
|
|
...props
|
|
}: ButtonProps) {
|
|
return (
|
|
<button
|
|
className={`
|
|
inline-flex items-center justify-center font-medium rounded-lg transition-colors
|
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
${variantStyles[variant]}
|
|
${sizeStyles[size]}
|
|
${className}
|
|
`}
|
|
disabled={disabled}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|