{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ratings-review-badges",
  "title": "Ratings & Review Badges",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/ratings-review-badges/RatingsReviewBadges.tsx",
      "content": "'use client'\n\nimport { Star } from 'lucide-react'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\n\nconst platforms = [\n  { name: 'G2', score: 4.8, reviews: 412, award: 'Leader — Analytics Platforms, Winter 2026' },\n  { name: 'Capterra', score: 4.7, reviews: 268, award: 'Best Value — Business Intelligence' },\n  { name: 'Product Hunt', score: 4.9, reviews: 1340, award: '#1 Product of the Day' },\n  { name: 'TrustRadius', score: 4.6, reviews: 97, award: 'Top Rated — Data Governance' },\n]\n\nconst distribution = [\n  { stars: 5, share: 78 },\n  { stars: 4, share: 16 },\n  { stars: 3, share: 4 },\n  { stars: 2, share: 1 },\n  { stars: 1, share: 1 },\n]\n\nconst STAR_SLOTS = [1, 2, 3, 4, 5]\n\n/** Fill percentage for one star slot, so a 4.6 renders a real partial star. */\nfunction fillFor(score: number, slot: number) {\n  return `${Math.min(Math.max(score - (slot - 1), 0), 1) * 100}%`\n}\n\nexport function RatingsReviewBadges() {\n  return (\n    <section data-slot=\"ratings-review-badges\" className=\"bg-background\">\n      <div className=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n        <div className=\"max-w-2xl\">\n          <Badge variant=\"secondary\">Reviews</Badge>\n          <h2 className=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">\n            Rated by the people who run it daily\n          </h2>\n          <p className=\"text-muted-foreground mt-3 text-lg\">\n            Every score below is pulled from a public review platform. None of them are ours to edit.\n          </p>\n        </div>\n\n        <div className=\"mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n          {platforms.map((platform) => (\n            <Card key={platform.name}>\n              <CardContent className=\"p-5\">\n                <div className=\"flex items-baseline justify-between gap-3\">\n                  <p className=\"text-sm font-semibold\">{platform.name}</p>\n                  <p className=\"text-muted-foreground font-mono text-xs\">{platform.reviews} reviews</p>\n                </div>\n\n                <div className=\"mt-3 flex items-center gap-2\">\n                  <div className=\"flex items-center gap-0.5\" role=\"img\" aria-label={`${platform.score} out of 5`}>\n                    {STAR_SLOTS.map((slot) => (\n                      <span key={slot} className=\"relative inline-flex\">\n                        <Star className=\"text-muted-foreground/30 size-4\" aria-hidden=\"true\" />\n                        {/* Dynamic clip width is the only way to draw a partial star. */}\n                        <span\n                          className=\"absolute inset-y-0 left-0 overflow-hidden\"\n                          style={{ width: fillFor(platform.score, slot) }}\n                          aria-hidden=\"true\"\n                        >\n                          <Star className=\"fill-primary text-primary size-4\" />\n                        </span>\n                      </span>\n                    ))}\n                  </div>\n                  <span className=\"text-sm font-medium\">{platform.score.toFixed(1)}</span>\n                </div>\n\n                <p className=\"text-muted-foreground mt-4 text-xs leading-relaxed\">{platform.award}</p>\n              </CardContent>\n            </Card>\n          ))}\n        </div>\n\n        <Separator className=\"my-10\" />\n\n        <div className=\"grid gap-10 lg:grid-cols-[1fr_1.4fr] lg:items-center\">\n          <div>\n            <p className=\"font-display text-5xl font-bold tracking-tight\">4.8</p>\n            <p className=\"text-muted-foreground mt-2 text-sm\">\n              Weighted average across 2,117 verified reviews on four platforms.\n            </p>\n            <Button variant=\"outline\" className=\"mt-5\">\n              Read the reviews\n            </Button>\n          </div>\n\n          <dl className=\"space-y-3\">\n            {distribution.map((row) => (\n              <div key={row.stars} className=\"flex items-center gap-4\">\n                <dt className=\"text-muted-foreground w-12 shrink-0 font-mono text-xs\">{row.stars} star</dt>\n                <dd className=\"flex min-w-0 grow items-center gap-4\">\n                  <Progress value={row.share} className=\"h-1.5\" aria-label={`${row.stars} star reviews`} />\n                  <span className=\"text-muted-foreground w-10 shrink-0 text-right font-mono text-xs\">{row.share}%</span>\n                </dd>\n              </div>\n            ))}\n          </dl>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/RatingsReviewBadges.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/progress.json",
    "https://uipkge.dev/r/react/separator.json"
  ],
  "description": "Third-party proof strip: four review-platform cards with star rating, score out of five, review count, and a category award line, over a rating-distribution bar and a verified-reviews footnote.",
  "categories": [
    "marketing"
  ]
}