React Rating Stars: Half Values, Hover and Keyboard

You need React rating stars for a product review, a seller rating or a feedback form. Five star icons and a click handler take ten minutes. Then someone asks for half stars, a keyboard user tabs to the row and nothing moves, a phone user drags a thumb across the stars and the page scrolls instead, and the product page still has to turn 126 ratings into an average and a breakdown. This guide covers what a React star rating component has to handle, how the common packages compare, and full examples with the Wingo UI Rating and Reviews.
What should a React rating component handle?
Six things. Five icons with a click handler cover only the first:
- Click or tap to rate, with a way to clear the rating again.
- Half values chosen by where the pointer lands on the star.
- A hover preview, so the stars and the label show what a click will pick before it happens.
- Keyboard control with a value a screen reader can speak ("Good", "3.5 of 5").
- A touch layout: targets of at least 44px and a finger scrub that does not scroll the page.
- A read-only mode for averages like 4.3, drawn as a fraction of a star.
The last one connects the input to the output. The stars people pick in a form are the same stars a product page shows next to the average, so one component should do both.
How do the React star rating packages compare?
MUI Rating is the most complete if you already use Material UI, the small npm packages are fine for a quick display, and the Wingo UI Rating is a Pro source component built for touch and forms. Facts below come from each project's docs, README and the npm registry, checked October 2026.
If your app is on Material UI, use MUI Rating: it is well documented and its hover label example (onChangeActive) covers the preview. If you only display a score, a small package or a read-only component is enough, though react-rating-stars-component has not been published since 2020. The rest of this guide is about the Wingo UI Rating.
How do I add a React star rating to a form?
Give it a label, a controlled value and a name. With name, a hidden input submits the value, so a plain form or a Server Action reads it like any other field: "0" when empty, "4.5" with halves.
labels does two jobs: with showLabel the hovered or chosen label shows beside the stars, and each label is what a screen reader hears for that value. required only draws the mark after the label, so the check stays in your form, as above. error tints the empty stars red and sets aria-invalid. The label, description and error come from the free Field anatomy, the same one every Wingo UI input uses.
Hover over the stars, then click one. Try Send rating without choosing anything first.
$ npx wingo-ui@latest add ratingHow do half star ratings work in React?
Each star is split at its midpoint. With allowHalf, a pointer on the left half of a star gives x.5 and the right half gives the whole star (mirrored on right-to-left pages). The fill is the same icon drawn twice: an empty layer at low opacity and a colored layer clipped to a percentage, so a half star is a 50% clip of the full icon. That is why any lucide icon works through the icon prop, such as <Heart />. Another half star rating React pattern is a separate half glyph (react-rating-stars-component takes a halfIcon prop); the clip makes that unnecessary.
tone="warning" gives the classic amber stars; the default neutral is black in light mode and white in dark mode, and color takes any CSS color. showValue prints the number through Intl ("3.5" in en-US, "3,5" in de-DE) and reserves the width of the widest number, so the stars never shift while the value changes.
The hover preview follows the pointer. The part of the preview beyond the chosen value is dimmed, so you can see both the current rating and the one a click would set. After a click, the preview waits until the mouse reaches another value, so the result is not hidden under a still cursor.
$ npx wingo-ui@latest add ratingWhat do keyboard and screen reader users get?
The row is one Tab stop with role="slider", aria-valuemin, aria-valuemax, aria-valuenow and aria-valuetext. The keys:
- Right or Up adds one step (0.5 with
allowHalf), Left or Down removes one. Right and Left swap on right-to-left pages. - PageUp and PageDown move a whole star.
- Home clears, or goes to the lowest value when
clearable={false}. End jumps to the top. - Digits 1 to 9 pick a value directly. 0, Backspace and Delete clear.
Radio groups are the other common pattern, and they are a fine choice: MUI uses hidden native radios, and @smastrom/react-rating an ARIA radio group. We picked one slider because the half steps, the Page keys and the digit shortcuts map onto a single value, and because aria-valuetext lets each value speak a word. Without labels, getValueText decides what is read (by default "3.5 of 5"); with them, whole values read the label ("Good"). Pass your own function to translate it.
A read-only rating is display only. It gets role="img" and a name from getReadOnlyLabel ("Rated 4.8 of 5"), leaves the tab order and draws fractions like 4.3 proportionally.
How does the rating work on a phone?
A finger has no hover, so touch gets a scrub instead. Press on the stars, drag across them and lift to commit; the stars follow the finger, and touch-action: none on the row keeps the page from scrolling during the drag. Sliding past the first star clears the rating when clearable is on (the default).
On a coarse pointer every star becomes a 44px target, and the row spreads its icons to that pitch. If ten stars would overflow a narrow screen, the row shrinks the spacing between them so it still fits, and the number stays on the same line. The reasoning behind the 44px number is in our post on minimum touch target size in React and Tailwind. On release, the filled stars pop on a small staggered spring; with reduced motion turned on in the system settings they fill without the animation.
How do I show review stars and the summary they feed?
Collect ratings with the Rating, show them with the Reviews component. React review stars on a product page are the same Rating in read-only mode, placed inside a summary and a list. Reviews takes the list of reviews and a summary with the average, the count and the distribution as counts for 5, 4, 3, 2 and 1 stars. It renders the average with read-only half stars, five bars that filter the list on tap, a sort menu (a bottom sheet on phones), photos that open full screen, and Helpful votes that roll back if saving fails.
Pass summary from the server when the list is paged. Without it, Reviews calls summarizeRatings(reviews), which only sees the loaded page: ratings round to the nearest star for the bars and the average keeps two decimals. The ReviewsSummary part renders the summary on its own, for a seller card or a product header.
Tap the 4 star bar, then tap it again. Open the sort menu and a review photo.
$ npx wingo-ui@latest add reviewsHow do review stars show up in Google?
Through AggregateRating structured data in the page; the component itself adds none. Google's review snippet documentation (opens in a new tab) requires ratingValue and at least one of ratingCount or reviewCount, assumes a best rating of 5 and a worst of 1 when you omit them, and excludes pages where a LocalBusiness or Organization controls the reviews about itself (checked October 2026). The same numbers you pass to summary fill it:
Rendering it safely in the App Router is covered in the Next.js JSON-LD guide.
What are the common star rating pitfalls?
Five, and each one is fixed by a prop or by sending the right numbers from the server:
- No accessible name. A rating without
labelneeds anaria-label, or a screen reader announces an unnamed slider. - Halves with per-value icons.
icons(one face per value, like Frown, Meh, Smile, Laugh) lights up one icon at a time and ignoresallowHalf. Useiconfor halves. - Rounding the average. A 4.4 drawn as four stars hides real information. Use a read-only rating, which draws the fraction.
- Saving on every hover.
onValueChangefires on commit only: on the release of a tap or scrub and on each key press. Save there, never in a pointer handler. - Summaries from one page.
summarizeRatingson the first page of reviews is not the product's average. Send the totals from the server.
How do I add it to my project?
Run npx wingo-ui@latest add rating (or reviews). The CLI copies the source into components/ui, adds the hooks and helpers it imports, and installs motion and lucide-react. Rating and Reviews are Pro components (pricing); the Textarea, Field and Button used in the form above are free. For the rest of the form, the React form components guide applies the same keyboard, touch and error rules to every input, and the component guides category has more single-component deep dives.
FAQ
How do I make a half star rating in React?
Split each star at its midpoint: a click on the left half gives x.5, the right half a whole star, and the fill is the same icon clipped to a percentage. In the Wingo UI Rating that is the allowHalf prop, which also makes the arrow keys move by 0.5.
Should a star rating be a radio group or a slider?
Both are used. MUI Rating and @smastrom/react-rating build a radio group, while the Wingo UI Rating is one slider with aria-valuetext, so a screen reader hears "Good" or "3.5 of 5" instead of a bare number. Whichever you pick, give every value a text label and keep the current value announced.
How do I show an average like 4.3 stars?
Render the rating read-only and let it draw the fraction. A read-only Wingo UI Rating paints 4.3 proportionally, keeps one decimal in the number and is announced as "Rated 4.3 of 5".
Can Google show my review stars in search results?
It can, if the page has valid AggregateRating or Review structured data with ratingValue and a ratingCount or reviewCount. Pages where a LocalBusiness or Organization reviews itself are not eligible for the star feature.
Is the Wingo UI Rating free?
No. Rating and Reviews are Pro components. The Field, Textarea and Button they are used with in this guide are free.
- Rating
- Reviews
- Forms
- Accessibility
- React


