{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "testimonial-card",
  "title": "Testimonial Card",
  "description": "A quote with the person, role, organization, and an optional proof link.",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "avatar",
    "https://uaiblocks.dev/r/uai-theme.json",
    "https://uaiblocks.dev/r/uai-utils.json"
  ],
  "files": [
    {
      "path": "src/registry/uai/components/testimonial-card.tsx",
      "content": "\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { ArrowUpRight } from \"lucide-react\";\nimport { type ComponentProps, createContext, useContext } from \"react\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { cn } from \"@/lib/uai-utils\";\n\nexport const TESTIMONIAL_CARD_VARIANTS = [\"card\", \"editorial\", \"compact\"] as const;\nexport type TestimonialCardVariant = (typeof TESTIMONIAL_CARD_VARIANTS)[number];\nexport type TestimonialCardProps = ComponentProps<\"figure\"> & {\n  variant?: TestimonialCardVariant;\n};\nconst Context = createContext<TestimonialCardVariant | null>(null);\nfunction useVariant(part: string) {\n  const variant = useContext(Context);\n  if (!variant) throw new Error(`${part} must be used within TestimonialCard`);\n  return variant;\n}\n\nconst testimonialCardVariants = cva(\"m-0 grid min-w-0 text-[13px]/[18px] text-card-foreground\", {\n  variants: {\n    variant: {\n      card: \"gap-4 rounded-[14px] border bg-card p-5\",\n      editorial: \"gap-5 py-0.5 pr-0 pl-5 shadow-[inset_2px_0_0_var(--border-strong)]\",\n      compact: \"gap-3 rounded-xl border bg-card p-3.5\",\n    },\n  },\n});\n\nconst testimonialCardQuoteVariants = cva(\"m-0 grid gap-2 text-pretty text-card-foreground\", {\n  variants: {\n    variant: {\n      card: \"text-[15px]/[22px] font-normal\",\n      editorial: \"text-xl/7 font-medium tracking-[-0.012em]\",\n      compact: \"text-[13px]/[19px] font-normal\",\n    },\n  },\n});\n\nexport function TestimonialCard({\n  variant = \"card\",\n  className,\n  children,\n  ...props\n}: TestimonialCardProps) {\n  return (\n    <Context.Provider value={variant}>\n      <figure\n        data-slot=\"testimonial-card\"\n        data-variant={variant}\n        className={cn(testimonialCardVariants({ variant }), className)}\n        {...props}\n      >\n        {children}\n      </figure>\n    </Context.Provider>\n  );\n}\n\nexport function TestimonialCardQuote({ className, ...props }: ComponentProps<\"blockquote\">) {\n  const variant = useVariant(\"TestimonialCardQuote\");\n  return (\n    <blockquote\n      data-slot=\"testimonial-card-quote\"\n      className={cn(testimonialCardQuoteVariants({ variant }), className)}\n      {...props}\n    />\n  );\n}\n\nexport function TestimonialCardAuthor({ className, ...props }: ComponentProps<\"figcaption\">) {\n  return (\n    <figcaption\n      data-slot=\"testimonial-card-author\"\n      className={cn(\"grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function TestimonialCardAvatar({\n  src,\n  children,\n  className,\n  ...props\n}: ComponentProps<typeof Avatar> & { src?: string }) {\n  const variant = useVariant(\"TestimonialCardAvatar\");\n  const size = variant === \"compact\" ? 24 : variant === \"editorial\" ? 36 : 32;\n  return (\n    <Avatar\n      aria-hidden=\"true\"\n      data-slot=\"testimonial-card-avatar\"\n      className={cn(\n        \"row-[1/span_3] grid place-items-center overflow-hidden rounded-full bg-muted font-medium text-muted-foreground shadow-[0_0_0_1px_oklch(1_0_0/0.08)] select-auto\",\n        variant === \"compact\" && \"mr-2 size-6 text-[10.5px]\",\n        variant === \"editorial\" && \"mr-2.5 size-9 text-[11.5px]\",\n        variant === \"card\" && \"mr-2.5 size-8 text-[11.5px]\",\n        className,\n      )}\n      {...props}\n    >\n      {src ? (\n        <AvatarImage src={src} alt=\"\" width={size} height={size} className=\"object-cover\" />\n      ) : null}\n      <AvatarFallback className=\"bg-transparent text-[length:inherit] text-inherit\">\n        {children}\n      </AvatarFallback>\n    </Avatar>\n  );\n}\n\nconst line = \"col-start-2 block min-w-0\";\n\nexport function TestimonialCardName({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"testimonial-card-name\"\n      className={cn(line, \"font-medium\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function TestimonialCardRole({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"testimonial-card-role\"\n      className={cn(line, \"text-xs/4 text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function TestimonialCardOrganization({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"testimonial-card-organization\"\n      className={cn(line, \"text-xs/4 text-subtle-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function TestimonialCardProof({ children, className, ...props }: ComponentProps<\"a\">) {\n  return (\n    <a\n      data-slot=\"testimonial-card-proof\"\n      className={cn(\n        \"inline-flex items-center justify-self-start gap-1 text-[12.5px] font-medium text-muted-foreground no-underline transition-colors duration-120 ease-[ease-out] hover:text-foreground focus-visible:rounded-[4px] focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-ring motion-reduce:transition-none\",\n        \"[&_svg]:transition-transform [&_svg]:duration-140 [&_svg]:ease-out-quint hover:[&_svg]:translate-x-px hover:[&_svg]:-translate-y-px motion-reduce:[&_svg]:transition-none\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <ArrowUpRight size={14} className=\"size-3.5\" strokeWidth={1.75} aria-hidden=\"true\" />\n    </a>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@ui/uai/testimonial-card.tsx"
    }
  ],
  "categories": [
    "marketing",
    "social-proof"
  ],
  "type": "registry:ui"
}