Rating
Star rating — read-only by default, interactive when given a change handler.
import { Rating } from '@elirobinson/react/components/molecules/Rating';Styles: @elirobinson/react/styles/molecules/Rating.css — already included when you import @elirobinson/react/styles.css.
Weeknight Pasta
U10 Practice Plan
Sheet-Pan Dinners
Show code
import { Rating } from '@elirobinson/react/components/molecules/Rating';
export default function Basic() {
return (
<div className="demo-col">
<div className="demo-row">
<span>Weeknight Pasta</span>
<Rating value={4} />
</div>
<div className="demo-row">
<span>U10 Practice Plan</span>
<Rating value={5} />
</div>
<div className="demo-row">
<span>Sheet-Pan Dinners</span>
<Rating value={3} />
</div>
</div>
);
}When to use it
Rating switches its own mode based on whether you pass onValueChange: omit it and
you get a read-only star display for showing an existing score (a recipe card, a
testimonial); pass it and the stars become interactive buttons for collecting one. You
don't choose the mode explicitly — the prop you pass decides it.
Interactive
Tap a star to rate this recipe.
Show code
import { useState } from 'react';
import { Rating } from '@elirobinson/react/components/molecules/Rating';
export default function Interactive() {
const [value, setValue] = useState(0);
return (
<div className="demo-col">
<Rating value={value} onValueChange={setValue} />
<p>
{value > 0 ? `You rated this recipe ${value} out of 5.` : 'Tap a star to rate this recipe.'}
</p>
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | number | — | — |
max | number | 5 | — |
onValueChange | ((value: number) => void) | — | — |
Also accepts all Omit<HTMLAttributes<HTMLDivElement>, 'role'> props.
Accessibility
- Read-only mode (no
onValueChange): rendersrole="img"on the outer element witharia-label="{value} out of {max} stars"— a screen reader hears the whole rating as one static image-like value, not a list of individual stars. - Interactive mode (
onValueChangepassed): each star is a native<button type="button">witharia-label="Rate {n} out of {max} stars"andaria-pressedreflecting whether that star is filled. valueis clamped to the0–maxrange before it's used in the accessible label, so an out-of-range value (negative, or abovemax) never produces a nonsensical announcement.- Keyboard: in interactive mode, each star button is independently focusable —
Tabmoves star to star,EnterandSpaceactivate whichever one has focus. There's no arrow-key traversal between stars; this is a row of buttons, not a slider. - Star buttons follow dense inline sizing (MUI/shadcn scale), not the 44px primary-control minimum.
- The ref forwards to the outer element in both modes.
Do
- Omit onValueChange for a rating you're only displaying — it gets you the cheaper role="img" markup.
- Show the numeric value alongside the stars for anyone who can't easily count filled icons.
- Keep max consistent across a list of ratings so stars are visually comparable.
- Confirm a submitted rating with text, not just the filled stars — "You rated this 4 out of 5."
Don't
- Pass onValueChange to a rating the user shouldn't be able to change, like an aggregate average.
- Expect arrow-key adjustment — Rating is a button row, not an ARIA slider.
- Use Rating for a binary like/dislike — a single toggle or Chip fits that better.
- Rely on star color alone to convey the value; the aria-label already carries the number.