{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "ratings-review-badges",
  "title": "Ratings & Review Badges",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/ratings-review-badges/RatingsReviewBadges.vue",
      "content": "<script setup lang=\"ts\">\nimport { Star } from 'lucide-vue-next'\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</script>\n\n<template>\n  <section data-slot=\"ratings-review-badges\" class=\"bg-background\">\n    <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n      <div class=\"max-w-2xl\">\n        <Badge variant=\"secondary\">Reviews</Badge>\n        <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Rated by the people who run it daily</h2>\n        <p class=\"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 class=\"mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        <Card v-for=\"platform in platforms\" :key=\"platform.name\">\n          <CardContent class=\"p-5\">\n            <div class=\"flex items-baseline justify-between gap-3\">\n              <p class=\"text-sm font-semibold\">{{ platform.name }}</p>\n              <p class=\"text-muted-foreground font-mono text-xs\">{{ platform.reviews }} reviews</p>\n            </div>\n\n            <div class=\"mt-3 flex items-center gap-2\">\n              <div class=\"flex items-center gap-0.5\" role=\"img\" :aria-label=\"`${platform.score} out of 5`\">\n                <span v-for=\"slot in STAR_SLOTS\" :key=\"slot\" class=\"relative inline-flex\">\n                  <Star class=\"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                    class=\"absolute inset-y-0 left-0 overflow-hidden\"\n                    :style=\"{ width: fillFor(platform.score, slot) }\"\n                    aria-hidden=\"true\"\n                  >\n                    <Star class=\"fill-primary text-primary size-4\" />\n                  </span>\n                </span>\n              </div>\n              <span class=\"text-sm font-medium\">{{ platform.score.toFixed(1) }}</span>\n            </div>\n\n            <p class=\"text-muted-foreground mt-4 text-xs leading-relaxed\">{{ platform.award }}</p>\n          </CardContent>\n        </Card>\n      </div>\n\n      <Separator class=\"my-10\" />\n\n      <div class=\"grid gap-10 lg:grid-cols-[1fr_1.4fr] lg:items-center\">\n        <div>\n          <p class=\"font-display text-5xl font-bold tracking-tight\">4.8</p>\n          <p class=\"text-muted-foreground mt-2 text-sm\">\n            Weighted average across 2,117 verified reviews on four platforms.\n          </p>\n          <Button variant=\"outline\" class=\"mt-5\">Read the reviews</Button>\n        </div>\n\n        <dl class=\"space-y-3\">\n          <div v-for=\"row in distribution\" :key=\"row.stars\" class=\"flex items-center gap-4\">\n            <dt class=\"text-muted-foreground w-12 shrink-0 font-mono text-xs\">{{ row.stars }} star</dt>\n            <dd class=\"flex min-w-0 grow items-center gap-4\">\n              <Progress :model-value=\"row.share\" class=\"h-1.5\" :aria-label=\"`${row.stars} star reviews`\" />\n              <span class=\"text-muted-foreground w-10 shrink-0 text-right font-mono text-xs\">{{ row.share }}%</span>\n            </dd>\n          </div>\n        </dl>\n      </div>\n    </div>\n  </section>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/RatingsReviewBadges.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/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"
  ]
}