Reportado en produccion: con object-contain + margenes grandes (inset-x-6 top-6 bottom-24) la foto quedaba chica y centrada, con mucho espacio muerto del pastel alrededor -- no se parecia a la referencia real de Walmart que mando el usuario, donde la foto aprovecha casi toda la tarjeta. Cambia a object-cover (recorta en vez de contener) dentro de un marco mas delgado (inset-3 en vez de inset-x-6/top-6), dejando solo un margen fino del pastel visible como marco alrededor de la foto.
85 lines
4.2 KiB
TypeScript
85 lines
4.2 KiB
TypeScript
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { ArrowUpRight } from "lucide-react";
|
|
import type { Category } from "@/lib/headless/types";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type TileContent = { subtitle: string; image?: string; color: string };
|
|
|
|
// No hay fotografia real todavia para las 6 categorias raiz de la taxonomia
|
|
// (ver ADR 0005) -- solo se mapean imagen/subtitulo para las que ya tienen
|
|
// un asset en public/images/categories/. Las demas caen al tile de solo
|
|
// gradiente en vez de mostrar una imagen que no les corresponde.
|
|
// Fondos pastel solidos (patron Walmart-inspirado, ADR 0008 sub-fase 4)
|
|
// en vez de los gradientes saturados originales del esquema arcoiris --
|
|
// un tono pastel distinto por categoria, no una escala de marca (serian
|
|
// todos casi iguales), pero coordinados en la misma temperatura suave.
|
|
const tileContent: Record<string, TileContent> = {
|
|
juguetes: { subtitle: "Personajes que inspiran", image: "/images/categories/figuras.webp", color: "bg-amber-100" },
|
|
"mochilas-y-morrales": { subtitle: "Estilo para cada aventura", image: "/images/categories/mochilas.webp", color: "bg-sky-100" },
|
|
"bebes-y-primera-infancia": { subtitle: "Primeros descubrimientos", color: "bg-rose-100" },
|
|
educativos: { subtitle: "Aprender jugando", color: "bg-emerald-100" },
|
|
"accion-y-aventura": { subtitle: "Para explorar sin límites", color: "bg-orange-100" },
|
|
variedades: { subtitle: "Un poco de todo", color: "bg-violet-100" },
|
|
};
|
|
|
|
const defaultTile: TileContent = { subtitle: "Explora esta categoría", color: "bg-slate-100" };
|
|
|
|
// Tile individual reutilizado tanto por la seccion de mundos del home
|
|
// como por el grid del catalogo (tiles promocionales intercalados,
|
|
// ADR 0005 seccion 3, patron Walmart) -- mismo primitivo visual, no un
|
|
// componente nuevo.
|
|
export function PromoTile({ category, className = "" }: { category: Category; className?: string }) {
|
|
const content = tileContent[category.handle] ?? defaultTile;
|
|
|
|
return (
|
|
<Link
|
|
href={`/catalog?category=${encodeURIComponent(category.name)}`}
|
|
className={cn(`group relative min-h-64 overflow-hidden rounded-[2rem] ${content.color} shadow-sm ring-1 ring-slate-900/5`, className)}
|
|
>
|
|
{/* Patron Walmart: foto recortada (object-cover) llenando casi toda
|
|
la tarjeta, con solo un margen delgado del pastel como marco --
|
|
no flotando chica con espacio muerto alrededor (object-contain,
|
|
intento anterior, reportado como "no aprovecha el espacio"), ni
|
|
a pantalla completa sin marco (el intento antes de ese). */}
|
|
{content.image && (
|
|
<div className="absolute inset-3 bottom-24 overflow-hidden rounded-2xl">
|
|
<Image src={content.image} alt="" fill sizes="(max-width: 640px) 45vw, (max-width: 1024px) 25vw, 14vw" className="object-cover transition duration-500 group-hover:scale-105" />
|
|
</div>
|
|
)}
|
|
<div className="absolute inset-x-0 bottom-0 flex items-end justify-between p-6 text-slate-900">
|
|
<div>
|
|
<h3 className="text-xl font-black">{category.name}</h3>
|
|
<p className="mt-1 text-sm font-semibold text-slate-600">{content.subtitle}</p>
|
|
</div>
|
|
<span className="grid size-11 shrink-0 place-items-center rounded-full bg-ari-marino text-white transition group-hover:rotate-45">
|
|
<ArrowUpRight />
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export function CategoryTiles({ categories }: { categories: Category[] }) {
|
|
const roots = categories.filter((category) => !category.parentId);
|
|
|
|
if (roots.length === 0) return null;
|
|
|
|
return (
|
|
<section className="mx-auto max-w-7xl px-4 py-14">
|
|
<div className="mb-8 flex items-end justify-between gap-4">
|
|
<div>
|
|
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">Explora por mundos</span>
|
|
<h2 className="mt-2 text-4xl font-black tracking-tight sm:text-5xl">Encuentra tu próximo tesoro</h2>
|
|
</div>
|
|
<Link href="/catalog" className="hidden font-black text-ari-marino sm:block">Ver todo →</Link>
|
|
</div>
|
|
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6">
|
|
{roots.map((category) => (
|
|
<PromoTile key={category.id} category={category} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|