Build a StarRating component that lets the user pick a score by clicking on stars, like the ones you see under a product review.
<StarRating max={5} value={rating} onChange={setRating} />
Props:
max: how many stars to show. Defaults to 5.value: the current rating, from 0 (nothing picked) to max. The component is controlled: the parent owns the value.onChange(next): called with the new rating whenever the user picks one.Mouse behaviour:
onChange(N). Stars 1..N are drawn as filled.onChange(0).1..N look filled, but onChange is not called. When the mouse leaves the whole group, the stars go back to showing value.Every star has the class star. A star that is drawn filled (because of value or the hover preview) also has the class filled.
Accessibility:
A rating is a "pick one of N" control, so expose it like a radio group:
role="radiogroup" and aria-label="Rating".role="radio", aria-checked set to true only for the selected star, and an accessible name like "1 star", "2 stars", ... "5 stars".tabIndex={0} and every other star has tabIndex={-1}. If nothing is selected, the first star is the tabbable one.ArrowRight / ArrowUp selects the next star (stops at max).ArrowLeft / ArrowDown selects the previous star (stops at 1).Home selects the first star, End selects the last.function Review() {
const [rating, setRating] = useState(0);
return (
<>
<StarRating value={rating} onChange={setRating} />
<p>{rating ? `You rated this ${rating}/5` : "Not rated yet"}</p>
</>
);
}
Hover the 4th star and four stars light up. Move the mouse away and they go dark again. Click the 4th star and the text says "You rated this 4/5". Press ArrowLeft and it drops to 3, with focus on the 3rd star.
<StarRating max={5} value={rating} onChange={setRating} />function Review() {
const [rating, setRating] = useState(0);
return (
<>
<StarRating value={rating} onChange={setRating} />
<p>{rating ? `You rated this ${rating}/5` : "Not rated yet"}</p>
</>
);
}