Star-Rated Reviews
A row of rated testimonials. The overall score counts up at the top while each card's stars fill one by one with fractional ratings, alongside a product thumbnail and a verified-purchase badge.
A review block for product pages and landing pages. The summary bar at the top shows a large average, five fractionally filled stars and "Based on 1,240 reviews"; the optional distribution bars on the right double as a filter. Below it sits a row of 3–4 cards, each with read-only stars (fractions like 4.5 supported), a bold headline, the quote, an initials avatar, and a product thumbnail with a "Verified purchase" badge at the bottom right. When the block scrolls into view the average counts up from 0 and the stars fill one at a time with a small spring; on narrow screens the card row becomes a horizontal snap scroller.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add star-rated-reviews.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<StarRatedReviews/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/star-rated-reviews.en.jsonOr, once registries are configured in components.json, install it as @webberui/star-rated-reviews.
Usage
import { StarRatedReviews } from "@/components/ui/star-rated-reviews";
<StarRatedReviews
eyebrow="Customer reviews"
title="What buyers are saying"
distribution={[8, 12, 28, 112, 1080]}
testimonials={[
{
headline: "Hot all day, still steaming at 4pm",
quote: "No leaks on the commute, and the lid opens one-handed.",
name: "Grace Lin",
role: "Designer",
rating: 5,
verified: true,
productName: "Travel tumbler",
},
{
headline: "Fits my drawer perfectly",
quote: "Three stacked for stationery and cables.",
name: "Ben Chen",
rating: 4.5,
verified: true,
productSrc: "/images/stacking-bin.jpg",
productName: "Stacking bin",
},
]}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
testimonials | StarRatedReviewsItem[] | — | Testimonials; 3–4 recommended |
eyebrow | string | "Customer reviews" | Eyebrow above the title |
title | string | "What buyers are saying" | Section title; also the section's accessible name |
subtitle | string | — | Supporting text below the title |
average | number | — | Average score (0–5); averaged from the testimonials' rating when omitted |
totalCount | number | — | Total review count; falls back to the distribution sum, then the number of testimonials |
distribution | number[] | — | Rating distribution, index 0 is the 1-star count up to 5 stars; rendered from 5 stars down |
showDistribution | boolean | true | Show the distribution bars (requires distribution) |
showProduct | boolean | true | Show the product thumbnail at the bottom right of each card |
filter | number | null | — | Controlled star filter (1–5, null for all); managed internally when omitted |
defaultFilter | number | null | null | Initial filter in uncontrolled mode |
onFilterChange | (star: number | null) => void | — | Called when a distribution bar or "Show all reviews" is clicked |
verifiedLabel | string | "Verified purchase" | Badge text |
className | string | — | Class merged onto the root section |
StarRatedReviewsItem
| Field | Type | Default | Description |
|---|---|---|---|
quote | string | — | Testimonial body |
name | string | — | Reviewer name; the avatar shows initials (last two characters for CJK, first letters for Latin) |
role | string | — | Job title |
company | string | — | Company or organization |
rating | number | — | Rating 0–5, fractions such as 4.5 allowed; the card shows no stars when omitted |
avatarHue | number | — | Avatar gradient hue; assigned by index with the golden angle when omitted |
highlight | string | — | Fragment of the quote to mark with the accent color |
metric | { value: string; label: string } | — | Result metric shown below the quote |
headline | string | — | Bold one-line headline at the top of the card |
productSrc | string | — | Product thumbnail URL; falls back to a gradient with an abstract SVG object |
productName | string | — | Product name, used as the thumbnail's alt text |
verified | boolean | — | Show the "Verified purchase" badge |
How it works
- Fractional stars: each star is a neutral base shape with the same star layered on top, clipped by a width percentage, so 4.5 or 4.3 render precisely.
- Entrance timing: when the block enters the viewport (once), the average counts up from 0 over
--wb-star-rated-reviews-count(default1200ms); the summary stars and each card's stars fill in sequence with a gap of--wb-star-rated-reviews-stagger(default80ms), and each star springs to 1.2 and back as it fills. The distribution bars grow from the left 60ms apart and the cards fade up 100ms apart. - Color: stars use
--wb-star-rated-reviews-star(default amber#f59e0b); the accent uses--wb-star-rated-reviews-accent(default#0d9488,#2dd4bfin dark mode) and is reserved for badges, marks and focus rings. - Filtering: the distribution bars are toggle buttons. Selecting one shows only cards whose rounded rating matches; select it again or press "Show all reviews" to clear.
- Layout: on narrow screens the card row is a horizontal snap scroller; from md up the cards share equal columns. Avatars and product placeholders are generated deterministically from the index, so server and browser output match.
Accessibility
- The root is a
<section aria-labelledby>named by its title; each testimonial is afigure/blockquote/figcaption - Every star group is
role="img"with anaria-labelsuch as "4.5 out of 5 stars" - The count-up is hidden from assistive tech; screen readers only hear the final "Average 4.8 out of 5"
- Distribution bars are
aria-pressedtoggle buttons whosearia-labelincludes the star, count and share; filter results are announced throughrole="status" - The card row is a focusable
region, so keyboard users can scroll it horizontally with the arrow keys; every button has afocus-visiblering - When the system "reduce motion" setting is on, the average shows its final value, stars and bars appear filled without the spring, and cards fade in over 150ms without moving
Flip Portrait Tiles
A wall of square portrait tiles that flip over in 3D on hover or tap to reveal the quote on the back, with touch and keyboard support.
Autoplay Quote Card
One large centred testimonial card that autoplays, with a bottom progress bar counting down to the next quote; content slides and fades between entries, with pause and manual controls.