feat(ui): Components refactoring with Tailwind - UI kit, icons, lazy loading images

- 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
This commit is contained in:
2026-03-06 14:11:23 +01:00
parent 05a18c3c77
commit d001e29bbc
24 changed files with 1235 additions and 459 deletions

View File

@@ -0,0 +1,61 @@
type BadgeVariant = "default" | "primary" | "success" | "warning" | "error" | "muted";
interface BadgeProps {
children: React.ReactNode;
variant?: BadgeVariant;
className?: string;
}
const variantStyles: Record<BadgeVariant, string> = {
default: "bg-muted/20 text-muted",
primary: "bg-primary-soft text-primary",
success: "bg-success-soft text-success",
warning: "bg-warning-soft text-warning",
error: "bg-error-soft text-error",
muted: "bg-muted/10 text-muted",
};
export function Badge({ children, variant = "default", className = "" }: BadgeProps) {
return (
<span className={`inline-flex px-2.5 py-1 rounded-full text-xs font-semibold ${variantStyles[variant]} ${className}`}>
{children}
</span>
);
}
type StatusVariant = "running" | "success" | "failed" | "cancelled" | "pending";
interface StatusBadgeProps {
status: string;
className?: string;
}
const statusVariants: Record<StatusVariant, BadgeVariant> = {
running: "primary",
success: "success",
failed: "error",
cancelled: "muted",
pending: "warning",
};
export function StatusBadge({ status, className = "" }: StatusBadgeProps) {
const variant = statusVariants[status as StatusVariant] || "default";
return <Badge variant={variant} className={className}>{status}</Badge>;
}
type JobTypeVariant = "rebuild" | "full_rebuild";
interface JobTypeBadgeProps {
type: string;
className?: string;
}
const jobTypeVariants: Record<JobTypeVariant, BadgeVariant> = {
rebuild: "primary",
full_rebuild: "warning",
};
export function JobTypeBadge({ type, className = "" }: JobTypeBadgeProps) {
const variant = jobTypeVariants[type as JobTypeVariant] || "default";
return <Badge variant={variant} className={className}>{type}</Badge>;
}