STARS INPUT: Interactive 5-star rating radiogroup
COMPOSES: .stars color tokens (save-yellow) | native radio group (keyboard + AT for free)

Each star is a real radio input, visually hidden inside its own label — Arrow keys move between stars and select as you go, Tab moves in/out of the group as one stop, and Space selects the focused star. stars_input_controller.js only keeps the fill in sync (hover preview, native change) and, when explicitly opted in via data-stars-input-clearable-value="true", adds one thing radios can't do alone: activating the already-selected star a second time (click or Space) clears the rating back to blank. Off by default — see the dedicated "Clearable" scenario below.

Blank

Unrated: no radio is checked. Hover or tab in to preview a rating; click or press Space on a star to commit it.

Rate how satisfied you were with the teaching quality.

<div class="stars-input" role="radiogroup" aria-labelledby="…" data-controller="stars-input"><label class="stars-input-star" data-value="1"><input type="radio" class="tw:sr-only" aria-label="1 star"><i class="fa-light fa-star"></i></label>…</div>

Preset (4 of 5)

Pre-filled from data: the 4th radio carries checked in the markup — connect() reads it and fills stars 1–4 on load, no click required. This scenario is not clearable (the default) — once set, a rating can only be changed to a different star, matching plain native radiogroup behavior. See the "Clearable" scenario below for the opt-in clear-on-reclick behavior.

Clearable

data-stars-input-clearable-value="true": explicit opt-in. Click (or press Space on) the already-selected star a second time to clear the rating back to blank — the one thing a plain radiogroup can't do on its own. Works identically from mouse and keyboard; either way the controller fires a genuine change event on the underlying radio so form logic and assistive tech see the clear, not just this controller's own stars-input:changed event.

Click your rating again to clear it.

<div class="stars-input" role="radiogroup" data-controller="stars-input" data-stars-input-clearable-value="true">…</div>

Sizes

.stars-input-sm / .stars-input-lg: same behaviour, smaller/larger glyph and gap. Default sits between the two.

Read-only display

Not a disabled .stars-input: once a rating is submitted and only ever displayed (a review card, a summary table), use the read-only .stars component instead of a locked interactive radiogroup — it needs no controller and carries a plain aria-label rather than five named radios.

<div class="stars" role="img" aria-label="4 out of 5 stars">…</div>