Page Sections

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.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

1200
80
Active edited usageDefault props
<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.json

Or, 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

PropTypeDefaultDescription
testimonialsStarRatedReviewsItem[]—Testimonials; 3–4 recommended
eyebrowstring"Customer reviews"Eyebrow above the title
titlestring"What buyers are saying"Section title; also the section's accessible name
subtitlestring—Supporting text below the title
averagenumber—Average score (0–5); averaged from the testimonials' rating when omitted
totalCountnumber—Total review count; falls back to the distribution sum, then the number of testimonials
distributionnumber[]—Rating distribution, index 0 is the 1-star count up to 5 stars; rendered from 5 stars down
showDistributionbooleantrueShow the distribution bars (requires distribution)
showProductbooleantrueShow the product thumbnail at the bottom right of each card
filternumber | null—Controlled star filter (1–5, null for all); managed internally when omitted
defaultFilternumber | nullnullInitial filter in uncontrolled mode
onFilterChange(star: number | null) => void—Called when a distribution bar or "Show all reviews" is clicked
verifiedLabelstring"Verified purchase"Badge text
classNamestring—Class merged onto the root section

StarRatedReviewsItem

FieldTypeDefaultDescription
quotestring—Testimonial body
namestring—Reviewer name; the avatar shows initials (last two characters for CJK, first letters for Latin)
rolestring—Job title
companystring—Company or organization
ratingnumber—Rating 0–5, fractions such as 4.5 allowed; the card shows no stars when omitted
avatarHuenumber—Avatar gradient hue; assigned by index with the golden angle when omitted
highlightstring—Fragment of the quote to mark with the accent color
metric{ value: string; label: string }—Result metric shown below the quote
headlinestring—Bold one-line headline at the top of the card
productSrcstring—Product thumbnail URL; falls back to a gradient with an abstract SVG object
productNamestring—Product name, used as the thumbnail's alt text
verifiedboolean—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 (default 1200ms); the summary stars and each card's stars fill in sequence with a gap of --wb-star-rated-reviews-stagger (default 80ms), 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, #2dd4bf in 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 a figure / blockquote / figcaption
  • Every star group is role="img" with an aria-label such 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-pressed toggle buttons whose aria-label includes the star, count and share; filter results are announced through role="status"
  • The card row is a focusable region, so keyboard users can scroll it horizontally with the arrow keys; every button has a focus-visible ring
  • 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