/** * Component: Author Grid * Documentation: documentation/frontend/components.md * * Premium grid layout for author cards with loading skeletons and empty state. * Mirrors AudiobookGrid patterns with author-appropriate column counts. */ 'use client'; import React from 'react'; import { AuthorCard } from './AuthorCard'; import { Author } from '@/lib/hooks/useAuthors'; interface AuthorGridProps { authors: Author[]; isLoading?: boolean; emptyMessage?: string; cardSize?: number; } // Authors use wider spacing since circular portraits need room to breathe. // Slightly fewer columns than AudiobookGrid at each breakpoint since circles // are visually wider than 2:3 portrait covers. function getGridClasses(size: number): string { const sizeMap: Record = { 1: 'grid-cols-4 md:grid-cols-5 lg:grid-cols-7 xl:grid-cols-9', 2: 'grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8', 3: 'grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-7', 4: 'grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6', 5: 'grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5', 6: 'grid-cols-2 md:grid-cols-3 lg:grid-cols-4', 7: 'grid-cols-2 md:grid-cols-3', 8: 'grid-cols-2', 9: 'grid-cols-1', }; return sizeMap[size] || sizeMap[5]; } export function AuthorGrid({ authors, isLoading = false, emptyMessage = 'No authors found', cardSize = 5, }: AuthorGridProps) { const gridClasses = getGridClasses(cardSize); if (isLoading) { return (
{Array.from({ length: 10 }).map((_, i) => ( ))}
); } if (authors.length === 0) { return (

{emptyMessage}

); } return (
{authors.map(author => ( ))}
); } function AuthorSkeletonCard({ index = 0 }: { index?: number }) { return (
{/* Circular portrait skeleton */}
{/* Text skeleton */}
); }