{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "focus-cards",
  "title": "Focus Cards",
  "description": "Image grid where the hovered card stays sharp while the others blur and step back.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/focus-cards.tsx",
      "content": "import { cn } from \"@/lib/utils\";\n\ninterface FocusCard {\n  /** Shown over the card while it has the focus; always read by screen readers */\n  title: string;\n  /** Image URL */\n  src: string;\n  /** Describes the photo; leave empty when the title says enough */\n  alt?: string;\n  /** Makes the card a link */\n  href?: string;\n}\n\ninterface FocusCardsProps extends React.HTMLAttributes<HTMLUListElement> {\n  /** The cards, in order */\n  cards: FocusCard[];\n  /** Extra classes for every card, e.g. a different aspect ratio */\n  cardClassName?: string;\n}\n\n// Blur and shrink every card while a sibling is hovered or keyboard-focused;\n// the card under the pointer or focus opts back out.\nconst card = cn(\n  \"group/focus-card relative block aspect-[4/3] overflow-hidden rounded-2xl bg-muted shadow-sm transition-[filter,scale] duration-300 ease-out motion-reduce:transition-none\",\n  \"group-has-[[data-focus-card]:hover]/focus-cards:blur-[3px] group-has-[[data-focus-card]:focus-visible]/focus-cards:blur-[3px]\",\n  \"motion-safe:group-has-[[data-focus-card]:hover]/focus-cards:scale-[0.97] motion-safe:group-has-[[data-focus-card]:focus-visible]/focus-cards:scale-[0.97]\",\n  // `!` because the :has() selectors above out-rank a plain :hover/:focus-visible.\n  \"hover:scale-100! hover:blur-none! focus-visible:scale-100! focus-visible:blur-none!\",\n  \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n);\n\n// Titles show on hover and keyboard focus, and always on touch screens.\nconst reveal =\n  \"opacity-0 transition duration-300 group-hover/focus-card:opacity-100 group-focus-visible/focus-card:opacity-100 pointer-coarse:opacity-100 motion-reduce:transition-none\";\n\n/**\n * Image grid where the card you point at (or tab to) stays sharp while the\n * rest soften and step back, and its title rises over a gradient. Pure CSS —\n * no client JavaScript. Cards with an `href` are links; the others are\n * focusable figures so keyboard users can reveal their titles too.\n */\nexport function FocusCards({\n  cards,\n  cardClassName,\n  className,\n  ...props\n}: FocusCardsProps) {\n  return (\n    <ul\n      data-slot=\"focus-cards\"\n      className={cn(\"group/focus-cards grid gap-4 sm:grid-cols-2 md:grid-cols-3\", className)}\n      {...props}\n    >\n      {cards.map(({ title, src, alt = \"\", href }) => {\n        const Caption = href ? \"span\" : \"figcaption\";\n        const body = (\n          <>\n            {/* eslint-disable-next-line @next/next/no-img-element */}\n            <img\n              src={src}\n              alt={alt}\n              loading=\"lazy\"\n              decoding=\"async\"\n              className=\"absolute inset-0 size-full object-cover transition-transform duration-500 ease-out motion-safe:group-hover/focus-card:scale-105 motion-safe:group-focus-visible/focus-card:scale-105\"\n            />\n            <div\n              aria-hidden\n              className={cn(\"absolute inset-0 bg-linear-to-t from-black/75 via-black/20 to-transparent\", reveal)}\n            />\n            <Caption\n              className={cn(\n                \"absolute inset-x-0 bottom-0 p-5 text-lg font-semibold tracking-tight text-white pointer-fine:motion-safe:translate-y-2 motion-safe:group-hover/focus-card:translate-y-0 motion-safe:group-focus-visible/focus-card:translate-y-0\",\n                reveal\n              )}\n            >\n              {title}\n            </Caption>\n          </>\n        );\n        return (\n          <li key={src + title}>\n            {href ? (\n              <a href={href} data-focus-card=\"\" className={cn(card, cardClassName)}>\n                {body}\n              </a>\n            ) : (\n              <figure tabIndex={0} data-focus-card=\"\" className={cn(card, cardClassName)}>\n                {body}\n              </figure>\n            )}\n          </li>\n        );\n      })}\n    </ul>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/focus-cards.tsx"
    }
  ],
  "type": "registry:ui"
}