cooking/components/RecipeGridCard.tsx
Olomana (multica agent) c58e09db1d PWS-15: Capitalize tags for display
Tags render with their first letter uppercased on the recipe page, grid
cards, sidebar facet, and active-filter chips, matching categories. The
shared capitalize helper moves to lib/format.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-11-12 15:48:30 -08:00

74 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Link from 'next/link';
import Image from 'next/image';
import type { RecipeMetadata } from '@/lib/recipes';
import { resolveRecipeAssetUrl } from '@/lib/recipe-urls';
import { capitalize } from '@/lib/format';
interface RecipeCardProps {
recipe: RecipeMetadata;
}
export default function RecipeGridCard({ recipe }: RecipeCardProps) {
const imageSrc = recipe.displayPhoto ? resolveRecipeAssetUrl(recipe, recipe.displayPhoto) : null;
return (
<Link
href={`/recipes/${recipe.category}/${recipe.slug}`}
className="group block bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden hover:shadow-lg transition-shadow"
aria-label={`View recipe: ${recipe.title}`}
>
<div className="aspect-video bg-gray-200 dark:bg-gray-700 relative overflow-hidden">
{imageSrc ? (
<Image
src={imageSrc}
alt={`${recipe.title} - Recipe photo`}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
unoptimized
/>
) : (
<div className="flex items-center justify-center h-full text-4xl text-gray-400 dark:text-gray-600">
🍽️
</div>
)}
</div>
<div className="p-4 space-y-2">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
{recipe.title}
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
{recipe.description}
</p>
<div className="flex items-center gap-3 text-xs text-gray-500 dark:text-gray-500" role="list" aria-label="Recipe details">
<span className="flex items-center gap-1" role="listitem">
<span aria-hidden="true">👥</span>
<span className="sr-only">Servings: </span>
{recipe.servings} servings
</span>
</div>
<div className="flex flex-wrap gap-1" role="list" aria-label="Recipe tags">
{recipe.tags.slice(0, 3).map((tag) => (
<span
key={tag}
role="listitem"
className="px-2 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded"
>
{capitalize(tag)}
</span>
))}
{recipe.tags.length > 3 && (
<span role="listitem" className="px-2 py-1 text-xs text-gray-500 dark:text-gray-500">
+{recipe.tags.length - 3} more
</span>
)}
</div>
</div>
</Link>
);
}