Inputs
Rating
A star rating that is both an accessible input (whole or half steps) and a fractional read-only display.
Preview in your theme
Loading preview…
Installation
npx shadcn@latest add https://ui.zyeon.ai/r/rating.jsonPrompt
The prompt behind this component — paste it into your AI assistant to recreate or adapt it.
Build a React + TypeScript + Tailwind "Rating" component (lucide-react Star).
Contract
- Export a forwardRef div extending HTMLAttributes (omit native onChange).
- Props: value (number), onChange? (value => void), max (default 5),
allowHalf (default false), size ("sm" | "md" | "lg", default "md"),
label (aria name, default "Rating").
- Mode is derived, not configured: onChange present → interactive input;
absent → read-only display that supports fractional values like 3.7.
Behavior
- Every star renders from one primitive: an outline Star underneath and a
filled Star inside an overflow-hidden overlay whose width is
fraction × 100% — the same math draws hover previews, half steps and
read-only decimals.
- Interactive: hover previews the prospective value (mousemove; left half of
a star = x.5 when allowHalf), mouseleave reverts to the committed value,
click commits via onChange.
- Keyboard (WAI-ARIA radiogroup): the container listens for
ArrowRight/Up (+step), ArrowLeft/Down (−step), Home (min step), End (max);
step is 0.5 when allowHalf. Clamp to [step, max], call onChange, and move
focus to the star holding the new value.
- Roving tabindex: only the star matching ceil(value) is tabbable
(the first when value is 0); every star is a role="radio" button with
aria-checked and an "N of max" aria-label.
Rendering & styling
- Semantic tokens only: filled stars fill-primary text-primary, empty
outlines text-muted-foreground/40 — the stars adopt any host theme.
- Read-only mode is role="img" with aria-label "value out of max"
(one summary, not five radios).
- Hover scale (hover:scale-110) is disabled under motion-reduce; focus uses
the focus-visible ring tokens. Merge className via cn().
Customization levers
- Scale: the SIZES map (size-4/5/7) — add an "xl" entry for hero placements.
- Color: swap primary for another token (e.g. fill-chart-4) when stars
should not carry the brand accent; keep fill and text paired.
- Icon: replace Star with Heart / ThumbsUp from lucide — the fill-overlay
math is icon-agnostic.
- Count: max is free (3, 5, 10); keyboard and fill logic follow it.
- Density: gap-0.5 on the container controls how tight the row reads.Concepts
- Input / display duality — the presence of
onChangepicks the mode, so a form input and a review-average display share one component and one visual language. - Width-clipped fill — a filled star inside an
overflow-hiddenspan atfraction × 100%width renders whole stars, half steps and decimals like 3.7 with the same three lines of math. - Radiogroup pattern — stars are
role="radio"buttons inside a labelledradiogroup, matching the WAI-ARIA rating idiom that screen readers announce as "3 of 5, selected". - Roving tabindex — one Tab stop for the whole control; arrows move the value and focus together, so keyboard users aren't tabbing through five buttons.
- Hover preview vs committed value — mouse position previews a prospective rating that evaporates on mouseleave; only click commits, mirroring how users expect star widgets to behave.
Add to Calendar
A split button that writes one event to Google, Outlook, Office 365 or Yahoo — and generates a spec-correct .ics in the browser for Apple Calendar and everything else.
Tags Input
A chips input for free-form multi-value entry — Enter or comma commits, paste splits, duplicates shake, maxTags caps with a counter.