{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "review-card12",
  "title": "Review",
  "description": "Review built with shadcn/ui.",
  "files": [
    {
      "path": "contents/examples/cards/review/12/index.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { StarIcon, Share2Icon, ArrowUpIcon, ArrowDownIcon } from \"lucide-react\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nfunction Stars({ value }: { value: number }) {\n  return (\n    <div className=\"flex items-center gap-0.5\">\n      {Array.from({ length: 5 }).map((_, i) => {\n        const fill = Math.min(Math.max(value - i, 0), 1);\n        return (\n          <span key={i} className=\"relative inline-block size-4\">\n            <StarIcon className=\"size-4 fill-muted text-muted\" />\n            <span\n              className=\"absolute inset-0 overflow-hidden\"\n              style={{ width: `${fill * 100}%` }}>\n              <StarIcon className=\"size-4 fill-amber-400 text-amber-400\" />\n            </span>\n          </span>\n        );\n      })}\n    </div>\n  );\n}\n\nconst advantages = [\n  \"Fast and reliable shipping\",\n  \"Excellent build quality\",\n  \"Great value for money\",\n];\n\nconst disadvantages = [\n  \"Limited color options\",\n  \"Slightly bulky design\",\n  \"No carrying case included\",\n];\n\nexport default function ReviewCard() {\n  const [votes, setVotes] = React.useState(12);\n  const [vote, setVote] = React.useState<\"up\" | \"down\" | null>(null);\n\n  function handleVote(type: \"up\" | \"down\") {\n    if (vote === type) {\n      setVote(null);\n      type === \"up\" ? setVotes((n) => n - 1) : setVotes((n) => n + 1);\n    } else {\n      if (vote === \"up\") setVotes((n) => n - 1);\n      if (vote === \"down\") setVotes((n) => n + 1);\n      setVote(type);\n      type === \"up\" ? setVotes((n) => n + 1) : setVotes((n) => n - 1);\n    }\n  }\n\n  return (\n    <Card className=\"w-full shadow-none md:w-[380px]\">\n      <CardContent className=\"space-y-4\">\n        {/* Header */}\n        <div className=\"flex items-start justify-between gap-3\">\n          <div className=\"flex items-center gap-2.5\">\n            <img\n              src=\"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=80&h=80&fit=crop&crop=face\"\n              alt=\"Joe Hawkins\"\n              className=\"size-10 rounded-full object-cover\"\n            />\n            <div>\n              <div className=\"flex items-center gap-1.5 flex-wrap\">\n                <span className=\"text-sm font-semibold\">Joe Hawkins</span>\n                <span className=\"text-sm text-muted-foreground\">gave it</span>\n                <Stars value={4.5} />\n              </div>\n              <p className=\"text-xs text-muted-foreground\">Nov 15, 2023</p>\n            </div>\n          </div>\n          <Button\n            variant=\"secondary\"\n            size=\"icon\"\n            className=\"size-8 shrink-0 rounded-full text-primary\">\n            <Share2Icon className=\"size-3.5\" />\n          </Button>\n        </div>\n\n        {/* Attributes */}\n        <div className=\"grid grid-cols-2 gap-2\">\n          <div>\n            <p className=\"text-sm font-semibold\">Price</p>\n            <p className=\"text-sm font-medium text-primary\">Competitive</p>\n          </div>\n          <div>\n            <p className=\"text-sm font-semibold\">Build Quality</p>\n            <p className=\"text-sm font-medium text-primary\">Excellent</p>\n          </div>\n        </div>\n\n        {/* Pros & Cons */}\n        <div className=\"grid grid-cols-2 gap-4\">\n          <div className=\"space-y-1\">\n            <p className=\"text-sm font-semibold\">Advantages</p>\n            {advantages.map((item) => (\n              <p key={item} className=\"text-xs text-muted-foreground\">\n                &bull; {item}\n              </p>\n            ))}\n          </div>\n          <div className=\"space-y-1\">\n            <p className=\"text-sm font-semibold\">Disadvantages</p>\n            {disadvantages.map((item) => (\n              <p key={item} className=\"text-xs text-muted-foreground\">\n                &bull; {item}\n              </p>\n            ))}\n          </div>\n        </div>\n\n        {/* Comment */}\n        <div className=\"space-y-1\">\n          <p className=\"text-sm font-semibold\">Comment</p>\n          <p className=\"text-sm leading-relaxed text-muted-foreground\">\n            Ordered these for a long-haul trip and they held up perfectly. Sound\n            quality is impressive for the price point, and the noise cancellation\n            works well in busy environments. Battery life exceeded expectations\n            on back-to-back travel days.\n          </p>\n        </div>\n\n        {/* Vote */}\n        <div className=\"flex items-center justify-center gap-3 pt-1\">\n          <Button\n            variant=\"secondary\"\n            size=\"icon\"\n            className={cn(\n              \"size-9 rounded-full\",\n              vote === \"up\" && \"bg-primary/10 text-primary\"\n            )}\n            onClick={() => handleVote(\"up\")}>\n            <ArrowUpIcon className=\"size-4\" />\n          </Button>\n          <span className=\"min-w-6 text-center text-sm font-medium\">{votes}</span>\n          <Button\n            variant=\"secondary\"\n            size=\"icon\"\n            className={cn(\n              \"size-9 rounded-full\",\n              vote === \"down\" && \"bg-primary/10 text-primary\"\n            )}\n            onClick={() => handleVote(\"down\")}>\n            <ArrowDownIcon className=\"size-4\" />\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/review-card12.tsx"
    }
  ],
  "type": "registry:block"
}