{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "testimonial",
  "type": "registry:ui",
  "title": "Testimonial",
  "description": "A quote with the name of the person who said it, and an optional star rating that screen readers announce as text.",
  "categories": [
    "atom"
  ],
  "dependencies": [
    "lucide-react@^1.47.0"
  ],
  "registryDependencies": [
    "https://facadeui.dev/r/types.json",
    "https://facadeui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/ui/testimonial.tsx",
      "type": "registry:ui",
      "target": "components/ui/testimonial.tsx",
      "content": "/**\n * Testimonial — a quotation with its attribution.\n *\n * a11y: the quote is a `<blockquote>` and the attribution sits in a `<figcaption>`\n * outside it, because the person's name is not part of what they said. The\n * avatar is `alt=\"\"` — the name is already text beside it, so a second\n * announcement would be noise. A star rating renders as visually hidden text\n * (\"Rated 5 out of 5\") rather than as five icons a screen reader would read one\n * at a time.\n *\n * Dependencies: lucide-react, react, @/lib/types, @/lib/utils.\n */\n\nimport { StarIcon } from \"lucide-react\"\nimport type { ElementType, ReactNode } from \"react\"\n\nimport type { ImageComponent } from \"@/lib/types\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface TestimonialAuthor {\n  name: string\n  /** Job title, company, or both — rendered as one line. */\n  title?: string\n  avatarSrc?: string\n}\n\nexport interface TestimonialItem {\n  /** The quotation, without surrounding quote marks. */\n  quote: string\n  author: TestimonialAuthor\n  /** Whole stars out of 5. Omit to hide the rating. */\n  rating?: 1 | 2 | 3 | 4 | 5\n  /** Stable key when rendering a list. */\n  id?: string\n}\n\nexport interface TestimonialProps extends TestimonialItem {\n  image?: ImageComponent\n  size?: \"sm\" | \"md\" | \"lg\"\n  /**\n   * `card` adds a border and background. `plain` has neither, for a single featured\n   * quote.\n   */\n  variant?: \"card\" | \"plain\"\n  className?: string\n  children?: ReactNode\n}\n\nconst quoteSizes = {\n  sm: \"text-base\",\n  md: \"text-lg\",\n  lg: \"text-xl sm:text-2xl\",\n} as const\n\nexport function Testimonial({\n  quote,\n  author,\n  rating,\n  image,\n  size = \"md\",\n  variant = \"card\",\n  className,\n  children,\n}: TestimonialProps) {\n  const Image = (image ?? \"img\") as ElementType\n\n  return (\n    <figure\n      className={cn(\n        \"flex h-full flex-col gap-6\",\n        variant === \"card\" && \"bg-card text-card-foreground rounded-xl border p-6 sm:p-8\",\n        className,\n      )}\n    >\n      {rating ? (\n        <p className=\"flex items-center gap-0.5\">\n          <span className=\"sr-only\">Rated {rating} out of 5</span>\n          {Array.from({ length: 5 }, (_, index) => (\n            <StarIcon\n              key={index}\n              aria-hidden\n              focusable=\"false\"\n              className={cn(\n                \"size-4\",\n                index < rating\n                  ? \"text-foreground fill-current\"\n                  : \"text-muted-foreground/40\",\n              )}\n            />\n          ))}\n        </p>\n      ) : null}\n\n      <blockquote className={cn(\"text-foreground flex-1 text-pretty\", quoteSizes[size])}>\n        <p>{quote}</p>\n      </blockquote>\n\n      {children}\n\n      <figcaption className=\"flex items-center gap-3\">\n        {author.avatarSrc ? (\n          <Image\n            src={author.avatarSrc}\n            alt=\"\"\n            width={40}\n            height={40}\n            loading=\"lazy\"\n            decoding=\"async\"\n            className=\"size-10 shrink-0 rounded-full object-cover\"\n          />\n        ) : null}\n        <span className=\"flex flex-col\">\n          <span className=\"text-foreground text-sm font-semibold\">{author.name}</span>\n          {author.title ? (\n            <span className=\"text-muted-foreground text-sm\">{author.title}</span>\n          ) : null}\n        </span>\n      </figcaption>\n    </figure>\n  )\n}\n"
    }
  ],
  "docs": "Import styles/facade-tokens.css in your global stylesheet, after @import \"tailwindcss\". Docs: https://facadeui.dev/components/testimonial"
}
