Category tiles

Three category link tiles with a zooming render, mono count and an arrow that nudges on hover.

blockcategoriesanynavigation
$npx shadcn@latest add @storekit/collection-categories
collection-categories

Live and interactive. Switch the brand in the frame header to see the same source under another token file.

Installation

$npx shadcn@latest add @storekit/collection-categories
$pnpm dlx shadcn@latest add @storekit/collection-categories
$yarn dlx shadcn@latest add @storekit/collection-categories
$bunx --bun shadcn@latest add @storekit/collection-categories

Source

components/storekit/collection/collection-categories.tsx
57 lines
import { ArrowUpRight } from "lucide-react"
import { cn } from "@/components/storekit/lib/cn"

/* Three category tiles. Each tile is one link: the render zooms, the arrow
   nudges and the count sits in mono, all on the same hover. */

type Category = { title: string; count: number; image: string; href: string }

export function CollectionCategories({
  categories = [
    { title: "Powders", count: 12, image: "/placeholder.webp", href: "#" },
    { title: "Capsules & gummies", count: 8, image: "/placeholder.webp", href: "#" },
    { title: "Drinks", count: 4, image: "/placeholder.webp", href: "#" },
  ],
  className,
}: {
  categories?: Category[]
  className?: string
}) {
  return (
    <ul data-sk-section="collection" data-sk-variant="collection-categories" className={cn("grid gap-4 sm:grid-cols-3", className)}>
      {categories.map((c) => (
        <li key={c.title}>
          <a
            href={c.href}
            className="group flex h-full flex-col overflow-hidden rounded-sk-card border border-sk-line bg-sk-surface outline-none focus-visible:ring-2 focus-visible:ring-sk-accent focus-visible:ring-offset-2 focus-visible:ring-offset-sk-paper"
          >
            <div className="relative aspect-[4/3] overflow-hidden sm:aspect-[4/5]">
              <img
                src={c.image}
                alt=""
                loading="lazy"
                className="absolute inset-0 h-full w-full object-cover transition-transform duration-700 ease-sk-out group-hover:scale-[1.04] motion-reduce:group-hover:scale-100"
              />
            </div>
            <div className="flex items-center justify-between gap-4 border-t border-sk-line bg-sk-card px-5 py-4">
              <div>
                <h3 className="font-sk-display text-xl font-semibold leading-[1.1] tracking-[-0.02em] text-sk-ink">{c.title}</h3>
                <p className="mt-1 font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted tabular-nums">
                  {c.count} {c.count === 1 ? "product" : "products"}
                </p>
              </div>
              <span className="grid h-11 w-11 shrink-0 place-items-center rounded-full border border-sk-line text-sk-ink transition-[transform,background-color,color] duration-200 ease-sk-out group-hover:bg-sk-accent group-hover:text-sk-accent-ink">
                <ArrowUpRight
                  size={18}
                  aria-hidden
                  className="transition-transform duration-200 ease-sk-out group-hover:-translate-y-0.5 group-hover:translate-x-0.5 motion-reduce:transform-none"
                />
              </span>
            </div>
          </a>
        </li>
      ))}
    </ul>
  )
}

Usage

Import from "@/components/storekit/collection/collection-categories" and pass your product data. The demo above exercises the full prop surface with sample values.

Category tiles, StoreKit