{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"source-card","type":"registry:ui","title":"Source Card","description":"A cited source as a card — favicon, page title, domain, and the snippet the answer actually drew from.","author":"Scrim UI (https://scrimui.dev)","categories":["sources"],"docs":"https://scrimui.dev/components/source-card","dependencies":[],"registryDependencies":[],"files":[{"path":"src/showcase/source-card/source-card.tsx","content":"\"use client\";\n\nimport * as React from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Types                                                               */\n/* ------------------------------------------------------------------ */\n\nexport type SourceCardProps = {\n  title: string;\n  url: string;\n  domain?: string;\n  snippet?: string;\n  favicon?: string;\n  index?: number;\n  className?: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Helpers                                                             */\n/* ------------------------------------------------------------------ */\n\nconst FALLBACK_COLORS = [\n  \"bg-slate-500\",\n  \"bg-emerald-500\",\n  \"bg-amber-500\",\n  \"bg-rose-500\",\n  \"bg-indigo-500\",\n  \"bg-teal-500\",\n];\n\nfunction colorFor(title: string) {\n  let h = 0;\n  for (let i = 0; i < title.length; i++) h = (h * 31 + title.charCodeAt(i)) >>> 0;\n  return FALLBACK_COLORS[h % FALLBACK_COLORS.length];\n}\n\nfunction domainFromUrl(url: string) {\n  try {\n    return new URL(url).hostname.replace(/^www\\./, \"\");\n  } catch {\n    return url;\n  }\n}\n\n/* ------------------------------------------------------------------ */\n/* SourceCard                                                          */\n/* ------------------------------------------------------------------ */\n\nexport function SourceCard({\n  title,\n  url,\n  domain,\n  snippet,\n  favicon,\n  index,\n  className = \"\",\n}: SourceCardProps) {\n  const host = domain ?? domainFromUrl(url);\n\n  return (\n    <a\n      href={url}\n      target=\"_blank\"\n      rel=\"noreferrer noopener\"\n      className={`group block rounded-xl border border-zinc-200 bg-white p-3.5 transition-colors hover:border-zinc-300 hover:bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900 dark:hover:border-zinc-700 dark:hover:bg-zinc-800/60 ${className}`}\n    >\n      <div className=\"flex items-start gap-2.5\">\n        {favicon ? (\n          // eslint-disable-next-line @next/next/no-img-element\n          <img\n            src={favicon}\n            alt=\"\"\n            className=\"h-5 w-5 shrink-0 rounded\"\n            width={20}\n            height={20}\n          />\n        ) : (\n          <span\n            className={`flex h-5 w-5 shrink-0 select-none items-center justify-center rounded text-[9px] font-bold text-white ${colorFor(title)}`}\n          >\n            {title.slice(0, 1).toUpperCase()}\n          </span>\n        )}\n        <div className=\"min-w-0\">\n          <p className=\"truncate text-sm font-medium text-zinc-800 group-hover:underline dark:text-zinc-100\">\n            {title}\n          </p>\n          <p className=\"mt-0.5 text-xs text-zinc-500 dark:text-zinc-400\">{host}</p>\n          {snippet && (\n            <p className=\"mt-1.5 line-clamp-2 text-[13px] leading-5 text-zinc-500 dark:text-zinc-400\">\n              {snippet}\n            </p>\n          )}\n        </div>\n        {index !== undefined && (\n          <span className=\"ml-auto flex h-5 w-5 shrink-0 items-center justify-center rounded bg-zinc-100 text-[11px] font-medium text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400\">\n            {index}\n          </span>\n        )}\n      </div>\n    </a>\n  );\n}\n","type":"registry:ui","target":"components/ui/source-card.tsx"}]}