Inputs
Rating
A star rating input built on native radio buttons, plus a read-only display mode for showing an average rating.
RatingPreview
Click a star, or the left half of one for a half rating.
Usage
tsx
import { Rating } from "@vesture/react";
function Example() {
const [rating, setRating] = useState(0);
return (
<Rating
aria-label="Rate this product"
allowHalf
value={rating}
onChange={setRating}
/>
);
}
// Displaying someone else's average rating:
// <Rating readOnly value={4.2} />Behavior
- Renders one native radio per star sharing a single (auto-generated, or explicit name) group — arrow keys move between whole stars using the browser's native radio-group focus behavior, so this is real form-participating input, not a div reimplementing keyboard handling.
- Hovering previews the rating up to and including the hovered star; the preview clears on mouse leave and the checked value's fill returns.
- allowHalf doubles the granularity: clicking the left half of a star commits a half value, the right half commits a whole value. Shift+ArrowRight/Left move by half a star on the keyboard, since a native radio has no concept of "half checked".
- readOnly renders max star outlines with a genuine partial-fill overlay per star (4.2/5 fills the 5th star to exactly 20%, it isn't rounded to 4) and swaps to role="img" with no inputs at all — for displaying an aggregate rating from other users' data.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue / onChange | number | — | Controlled / uncontrolled rating value. |
| max | number | 5 | Number of stars. |
| allowHalf | boolean | false | Enables half-star clicks and Shift+Arrow keyboard steps. |
| readOnly | boolean | false | Renders a static, non-interactive display with genuine partial fill for non-integer values. |
| disabled | boolean | — | Disables all stars; native radios stop responding to click and keyboard. |
| name | string | — | Radio group name. Auto-generated via useId when omitted, so multiple Rating instances on one page never collide. |
| aria-label | string | — | Required in practice — there's no visible text label by default. |