Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Commerce

Reviews

Commerce

Reviews React component for Tailwind CSS v4

Quantity stepperSeller card
Live props
Layout
layout
showSummary
showDistribution
maxLines4
Behavior
filterable
sortable
photoLightbox
locale
State
defaultSort
loading
skeletonCount3
hasMore
loadingMore
Appearance
size
tone
color
Code
import { Reviews } from "@/components/ui/reviews"

<Reviews />
  1. Home
  2. Components
  3. Commerce
  4. Reviews
Pro

Reviews React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React reviews section for products and sellers: average, stars, a 5 to 1 filter breakdown, and sortable reviews with photos and replies.

The summary shows the average, its stars and how many reviews there are; the five bars grow in one after another the first time they scroll into view. Tap or click a bar to see only that many stars (it stays highlighted, the other bars dim), tap it again to see all; the chips above the list do the same and add "With photos", and the list reflows with the reviews sliding into place. Sort opens a menu on a laptop and a bottom sheet on a phone. Long reviews stop after a few lines with "Show more", which springs the rest open. Tap a photo to open it full screen (swipe between photos, pinch or double tap to zoom, swipe down or press Escape to close, and focus returns to the photo). "Helpful" votes at once and rolls back if saving fails; the count moves by one with it. On a wide container the summary sits in a sticky column beside the list; below that it stacks above. Keyboard: Tab through the bars, the sort, the chips (arrow keys move between chips), each review's photos, Show more, Helpful and Report; Space or Enter toggles a bar, a chip or Helpful and opens a photo; in the photo viewer Left and Right change the photo and Escape closes it; in the sort menu the arrow keys pick an order and Enter confirms. Every bar, chip and button has a 44px target on touch.

Reviews is a Pro React component in the React commerce components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add reviews, together with Avatar, Badge, Button, Collapsible, Empty State and 16 more and the npm packages lucide-react and motion.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add reviews

Reviews is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import Reviews from @/components/ui/reviews.

import { Reviews, type ReviewData, type ReviewsLabels } from "@/components/ui/reviews"

const labels: Partial<ReviewsLabels> = {
  title: "Customer reviews",
  write: "Review this product",
}

const reviews: ReviewData[] = [
  {
    id: "r1",
    author: { name: "Julia Davis", avatar: "/demo/ioana-dumitrescu.jpg" },
    rating: 5,
    title: "Exactly what I wanted",
    body: "Fast delivery with UPS, and the bike arrived almost assembled.",
    date: "2026-09-22T10:15:00",
    photos: ["/demo/bicycle.jpg"],
    verified: true,
    helpfulCount: 12,
  },
]

export function ProductReviews() {
  return (
    <Reviews
      reviews={reviews}
      summary={{ average: 4.6, count: 126, distribution: [92, 21, 7, 3, 3] }}
      tone="warning"
      labels={labels}
      onHelpfulChange={async (id, helpful) => {
        const res = await fetch(`/api/reviews/${id}/helpful`, { method: helpful ? "POST" : "DELETE" })
        if (!res.ok) throw new Error("vote failed")
      }}
      onWriteReview={() => {}}
    />
  )
}

Props

  • reviewsdefault "[]"
    ReviewData[]

    The loaded page of reviews (empty shows the empty state): { id, author: { name, avatar?, href? }, rating, title?, body?, date, photos?, verified?, helpfulCount?, helpful?, reply?: { author, body, date? }, meta?, context? }.

  • summarydefault "summarizeRatings(reviews)"
    ReviewsSummaryData

    { average, count, distribution: [n5, n4, n3, n2, n1], aspects?, photoCount? }. Pass the server's numbers when the list is paged; the bars always use count for their proportions and the average shows one decimal.

  • layoutdefault "split"
    "split" | "stacked"

    split: on a container of 768px or more the summary becomes a sticky column beside the list. stacked: the summary sits above the list, with the average beside the bars once there is room.

  • showSummarydefault true
    boolean

    The average, the stars, the count and the breakdown.

  • showDistributiondefault true
    boolean

    The 5 to 1 star bars in the summary.

  • filterabledefault true
    boolean

    The bars become toggle buttons and the chips row appears (All, With photos, one chip per star).

  • sortabledefault true
    boolean

    The sort select above the list (a bottom sheet on phones).

  • defaultSortdefault "relevant"
    "relevant" | "newest" | "highest" | "lowest"

    The starting order. relevant keeps the order the reviews came in; the others sort the loaded reviews (ties newest first).

  • sort
    ReviewsSort

    Controlled sort.

  • onSortChange
    (sort: ReviewsSort) => void

    Called when a person picks an order. When given, the list is not sorted locally: reload it in the new order.

  • filter
    ReviewsFilter

    Controlled filter, { rating?: 1 to 5; withPhotos?: boolean }.

  • defaultFilterdefault "{}"
    ReviewsFilter

    The starting filter. Filters apply to the loaded reviews; a caller that reloads per filter gets the same result.

  • onFilterChange
    (filter: ReviewsFilter) => void

    Called when a bar or a chip changes the filter.

  • onHelpfulChange
    ((id: string, helpful: boolean) => void | Promise<unknown>)

    Shows the Helpful vote on every review. It flips at once; return a promise to keep it pending, and a rejection rolls it back and announces labels.helpfulError.

  • onReport
    (id: string) => void

    Shows a Report button on every review.

  • onWriteReview
    () => void

    Shows "Write a review" in the summary and in the empty state.

  • maxLinesdefault 4
    number

    Lines of a review's text before "Show more". The toggle only appears when the text is longer.

  • photoLightboxdefault true
    boolean

    Review photos are buttons that open a full-screen viewer (zoom, swipe, swipe down to close).

  • loadingdefault false
    boolean

    First load: a skeleton summary and skeleton reviews in the real shape.

  • skeletonCountdefault 3
    number

    Skeleton reviews while loading.

  • hasMoredefault false
    boolean

    Shows a full-width "Show more reviews" button with "Showing 8 of 126" under the list.

  • onLoadMore
    (() => void | Promise<unknown>)

    Loads the next page. A returned promise shows the loading state until it settles.

  • loadingMoredefault false
    boolean

    The next page is loading (for callers that do not return a promise). Shows with hasMore.

  • emptyState
    ReactNode

    Replaces the default empty state ("No reviews yet" with a Write a review action).

  • error
    ReactNode

    Shows an error state with the message in place of the list.

  • onRetry
    () => void

    Adds a Try again button to the error state.

  • sizedefault "md"
    "sm" | "md"

    md for a product page; sm for sheets, sidebars and seller cards (a 32px average, smaller stars, 56px photos).

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The stars, the bars and a voted Helpful chip. neutral is black / white; amber stars are tone="warning".

  • colordefault ""
    string

    Any CSS color for the stars and bars; replaces the tone.

  • nowdefault "useNow()"
    number | null

    The reference time in ms for "2 days ago"; older than 28 days prints the date. null prints dates only. A timestamp, so it stays out of the playground.

  • linkComponent
    (props: LinkComponentProps) => ReactNode

    The router link for author.href (pass next/link's Link). Defaults to the one given to LinkProvider (lib/navigation), else a plain <a>.

  • localedefault ""
    string

    Numbers and dates ("4.6", "126", "9/22/2026"). Empty uses the app's or the browser's locale.

  • labels
    Partial<ReviewsLabels>

    Every string, English by default: title, average(value), count(n, formatted), stars(n), all, withPhotos(n, formatted), filters, distribution, aspects, sort, sortOptions, verified, helpful, helpfulCount, helpfulError, report, reply, showMore, showLess, write, empty, emptyDescription, emptyFiltered, emptyFilteredDescription, showAll, errorTitle, retry, loadMore, loadingMore, remaining, showing, photos, photo(i, n), photoError.

  • lightboxLabels
    Partial<ImageLightboxLabels>

    Strings of the full-screen photo viewer (close, next, previous, zoom…).

  • classNames
    Partial<Record<"summary" | "distribution" | "bar" | "toolbar" | "list" | "review" | "photos" | "reply" | "footer", string>>

    Extra classes for the inner parts.

  • className
    string

    Extra classes for the root, merged last.

Parts

  • ReviewsSummary

    component

    The summary on its own (a seller card, a product header): summary, layout, size, tone, color, showDistribution, filterable, selectedRating, onSelectedRatingChange, onWriteReview, animated (default true: the bars grow in on first view; false shows them filled), locale, labels, classNames. Props: ReviewsSummaryProps.

  • ReviewItem

    component

    One review as an <article>: review, size, tone, color, maxLines, photoLightbox, onHelpfulChange, onReport, now, linkComponent, locale, labels, lightboxLabels, classNames. Props: ReviewItemProps.

  • summarizeRatings

    function

    { average, count, distribution: [n5, n4, n3, n2, n1] } from a list; ratings round to the nearest star. Signature: (reviews: { rating: number }[]) => ReviewsSummaryData.

  • DEFAULT_REVIEWS_LABELS

    constant

    The English copy of the summary, filters, sort menu, review items and empty states. Spread it into labels when you translate only a few keys.

  • ReviewData

    type

    One review: id, author { name, avatar?, href? }, rating, title, body, date, photos, verified, helpfulCount, helpful, reply { author, body, date? }, meta and context.

Examples

Stacked on a phone

The summary above the list, bars full width, chips that scroll sideways and a sort sheet.

Seller reviews

Aspect scores under the bars and what each buyer bought, as context on every review.

Loading, then content

Skeletons in the real shape, then the reviews fade in.

Empty

No reviews yet, with the action that writes the first one.

Filtered

Filtered to 1 star or to reviews with photos. The filter is controlled; bars and chips follow it.

Small, inside a drawer

size="sm" in a sheet on phones and a side panel on a laptop.

Error and retry

A failed load shows the message and a retry that brings the list back.

Summary with a custom color

ReviewsSummary on its own, stars and bars in any CSS color.

Dependencies

lucide-reactmotionavatarbadgebuttoncollapsibleempty-statefavorite-buttonimage-lightboxnavigationpaginationprogressratingselectskeletontaguse-controllable-stateuse-localemotionnumber-formatrelative-timetonesui-config

Files

  • components/ui/reviews.tsx

FAQ

Is the React Reviews component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Reviews?

Run npx wingo-ui@latest add reviews. It also adds the Wingo UI items it builds on (Avatar, Badge, Button, Collapsible, Empty State and 16 more) and the npm packages lucide-react and motion. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/reviews.

How does Reviews behave on phones?

Sort opens a menu on a laptop and a bottom sheet on a phone.

See also

RatingFavorite buttonImage LightboxComment ThreadListing cardProduct gallery

Used in

Home Services PageStorefront Page

More React commerce components

Seller cardQuantity stepperPriceCoupon inputCategory pickerFilter panel
All 16 React commerce components

Articles using this component

  • React Rating Stars: Half Values, Hover and Keyboard

    Component guides · Oct 19, 2026 · 9 min read

PreviousQuantity stepperNext Seller card

Reviews

4.6
126 reviews

4.6 out of 5, 126 reviews

126 reviews

  • Julia DavisVerified purchase
    2 days ago
    Color: Mint green · Wheels: 26"

    Exactly what I wanted

    Fast delivery with UPS, and the bike arrived almost assembled. I only fitted the pedals and the handlebar, and 15 minutes later it was ready to ride. It rolls very smoothly, the brakes are good and the saddle stays comfortable on longer rides too.
  • Ryan MitchellVerified purchase
    5 days ago

    Good for the city

    Great value for money. The only downside: the shifter needed an adjustment after the first week. Otherwise I recommend it for short rides around town.

    Acme MarketSeller's reply· 4 days ago

    Thanks, Ryan! Shifter tune-ups are free for the first 6 months at any partner shop.

  • Maria TorresVerified purchase
    1 wk. ago

    The box arrived damaged

    The box arrived damaged and the rear fender was bent. The bike itself seems fine, but I expected better packaging.

    Acme MarketSeller's reply· 1 wk. ago

    We are sorry about that. We sent you a new part; it should arrive tomorrow with FedEx.

  • Lucas GrantVerified purchase
    7 hr. ago
    Great bike, I ride it to the office every day.
  • Daniel Parker
    2 wk. ago

    Fine, but it has its downsides

    I bought it for short trips to the market and back. On asphalt it rides well, it is light and easy to get on. On the downtown cobblestones you feel every stone though; the tires are a bit thin for that. The front brake started squeaking after about two weeks. I adjusted it myself with a tutorial, but I did not expect to need that so soon. I bought the front basket separately and it fit without any trouble. In short: a fair choice for the price, just do not expect a premium city bike.
  • Olivia StoneVerified purchase
    2 wk. ago

    A gift for my daughter

    It was the perfect birthday present. The color is even nicer than in the photos.
  • GS
    George StewartVerified purchase
    3 wk. ago
    Looks exactly like the photos. A front basket would have been a plus.
  • CM
    Christina Moore
    08/20/2026

    Late delivery

    I waited 9 days instead of 2. The bike is fine, but the communication left a lot to be desired.

    Acme MarketSeller's reply· 08/21/2026

    We apologize for the delay. We refunded the shipping cost and changed the courier for your area.

filter: {} · defaultSort: relevant