Ratings & Review Badges
blockmarketingThird-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.
Installation
$pnpm dlx uipkge-ng@latest add ratings-review-badges$npx uipkge-ng@latest add ratings-review-badges$yarn dlx uipkge-ng@latest add ratings-review-badges$bunx uipkge-ng@latest add ratings-review-badgesManifest:
https://uipkge.dev/r/angular/ratings-review-badges.jsonInstalls to:src/app/components/blocks/ratings-review-badges/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
Platforminterface Platform {
name: string
score: number
reviews: number
award: string
}DistributionRowinterface DistributionRow {
stars: number
share: number
}Files installed (2)
src/app/components/blocks/ratings-review-badges/ratings-review-badges.component.ts5.9 kB
// 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. Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { LucideAngularModule, Star } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component' import { UiProgressComponent } from '@/ui/progress/progress.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' interface Platform { name: string score: number reviews: number award: string } interface DistributionRow { stars: number share: number } const platforms: Platform[] = [ { name: 'G2', score: 4.8, reviews: 412, award: 'Leader — Analytics Platforms, Winter 2026' }, { name: 'Capterra', score: 4.7, reviews: 268, award: 'Best Value — Business Intelligence' }, { name: 'Product Hunt', score: 4.9, reviews: 1340, award: '#1 Product of the Day' }, { name: 'TrustRadius', score: 4.6, reviews: 97, award: 'Top Rated — Data Governance' }, ] const distribution: DistributionRow[] = [ { stars: 5, share: 78 }, { stars: 4, share: 16 }, { stars: 3, share: 4 }, { stars: 2, share: 1 }, { stars: 1, share: 1 }, ] const STAR_SLOTS = [1, 2, 3, 4, 5] /** Fill percentage for one star slot, so a 4.6 renders a real partial star. */ function fillFor(score: number, slot: number): string { return `${Math.min(Math.max(score - (slot - 1), 0), 1) * 100}%` } @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-ratings-review-badges, [ui-ratings-review-badges]', standalone: true, // The block renders its own root <section>: keep this wrapper out of the layout. host: { '[attr.class]': '"contents"' }, imports: [ LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent, UiProgressComponent, UiSeparatorComponent, ], template: ` <section data-slot="ratings-review-badges" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-20 lg:py-28"> <div class="max-w-2xl"> <span ui-badge variant="secondary">Reviews</span> <h2 class="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">Rated by the people who run it daily</h2> <p class="text-muted-foreground mt-3 text-lg"> Every score below is pulled from a public review platform. None of them are ours to edit. </p> </div> <div class="mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-4"> @for (platform of platforms; track platform.name) { <div ui-card> <div ui-card-content class="p-5"> <div class="flex items-baseline justify-between gap-3"> <p class="text-sm font-semibold">{{ platform.name }}</p> <p class="text-muted-foreground font-mono text-xs">{{ platform.reviews }} reviews</p> </div> <div class="mt-3 flex items-center gap-2"> <div class="flex items-center gap-0.5" role="img" [attr.aria-label]="platform.score + ' out of 5'"> @for (slot of starSlots; track slot) { <span class="relative inline-flex"> <lucide-icon [img]="Star" class="text-muted-foreground/30 size-4" aria-hidden="true" /> <!-- Dynamic clip width is the only way to draw a partial star. --> <span class="absolute inset-y-0 left-0 overflow-hidden" [style.width]="fillFor(platform.score, slot)" aria-hidden="true" > <lucide-icon [img]="Star" class="fill-primary text-primary size-4" /> </span> </span> } </div> <span class="text-sm font-medium">{{ platform.score.toFixed(1) }}</span> </div> <p class="text-muted-foreground mt-4 text-xs leading-relaxed">{{ platform.award }}</p> </div> </div> } </div> <ui-separator class="my-10" /> <div class="grid gap-10 lg:grid-cols-[1fr_1.4fr] lg:items-center"> <div> <p class="font-display text-5xl font-bold tracking-tight">4.8</p> <p class="text-muted-foreground mt-2 text-sm"> Weighted average across 2,117 verified reviews on four platforms. </p> <button ui-button variant="outline" class="mt-5">Read the reviews</button> </div> <dl class="space-y-3"> @for (row of distribution; track row.stars) { <div class="flex items-center gap-4"> <dt class="text-muted-foreground w-12 shrink-0 font-mono text-xs">{{ row.stars }} star</dt> <dd class="flex min-w-0 grow items-center gap-4"> <div ui-progress [value]="row.share" class="h-1.5" [aria-label]="row.stars + ' star reviews'"></div> <span class="text-muted-foreground w-10 shrink-0 text-right font-mono text-xs">{{ row.share }}%</span> </dd> </div> } </dl> </div> </div> </section> `, }) export class UiRatingsReviewBadgesComponent { protected readonly Star = Star protected readonly platforms = platforms protected readonly distribution = distribution protected readonly starSlots = STAR_SLOTS @Input('class') className?: string get rootClass(): string { return cn('bg-background', this.className) } fillFor(score: number, slot: number): string { return fillFor(score, slot) } }src/app/components/blocks/ratings-review-badges/index.ts0.1 kB
export { UiRatingsReviewBadgesComponent } from './ratings-review-badges.component'
Raw manifest:https://uipkge.dev/r/angular/ratings-review-badges.json