A star rating on native radios — pick a value on a scale, or display one read-only.

Last updated

Show code
<Rating name="hero-rating" value={3} />

Add

npx @ava-ui/apogee add rating

Pulls in @lucide/astro for the star icon. No Apogee component dependencies.

Usage

---
import Rating from '@/components/apogee/Rating/Rating.astro'
---
<Rating name="stars" value={3} />

API

@composable — exposed to Content Editors in AVA. Any other attribute passes through to the root <div> (the radiogroup, or the read-only display wrapper).

Prop Type Default Description
name string 'rating' Radio group name (interactive mode only).
max number 5 Number of stars.
value number 0 Selected (interactive) or displayed (readonly) rating.
readonly boolean false Renders a static display instead of radio inputs. Fractional values (3.5) fill part of a star.
size 'small' | 'medium' | 'large' 'medium' Star size: 16 / 20 / 24px readonly, 20 / 24 / 28px interactive.
color 'primary' | 'neutral' | 'critical' | 'positive' | 'warning' 'warning' Hue of a filled star.
aria-label string 'Rating' (interactive) / `${value} out of ${max}` (readonly) Accessible label for the group/display.
class string — Extra classes on the root.

Variants

Interactive (a radiogroup of native radios) vs. read-only (a static role="img" display):

Show code
<Rating name="variant-interactive" value={3} />
<Rating readonly value={4} aria-label="4 out of 5" />

Every color:

Show code
<Rating readonly value={4} color="primary" aria-label="Primary: 4 out of 5" />
<Rating readonly value={4} color="neutral" aria-label="Neutral: 4 out of 5" />
<Rating readonly value={4} color="critical" aria-label="Critical: 4 out of 5" />
<Rating readonly value={4} color="positive" aria-label="Positive: 4 out of 5" />
<Rating readonly value={4} color="warning" aria-label="Warning: 4 out of 5" />

Fractional and sizes

Show code
<Rating readonly value={3.5} />
<Rating readonly value={4.2} />

Every size, readonly and interactive:

Show code
<Rating readonly value={4} size="small" />
<Rating readonly value={4} size="medium" />
<Rating readonly value={4} size="large" />
<Rating name="r-s" value={3} size="small" />
<Rating name="r-m" value={3} size="medium" />
<Rating name="r-l" value={3} size="large" />

States

  • Hover preview — hovering a star fills it and every star before it (CSS :has(), no JS); moving off clears the preview back to the checked value.
  • Checked — the selected star and every star before it fill with the color hue (amber by default).
  • Focus — a visible outline on the focused star’s label.
  • Read-only mode has no interactive states.
Show code
<Rating name="states-empty" value={0} />
<Rating name="states-checked" value={2} />
<Rating readonly value={5} aria-label="5 out of 5" />

Examples

A different max:

<Rating name="difficulty" max={3} value={2} aria-label="Difficulty" />

A read-only aggregate score:

<Rating readonly value={4} aria-label="4.2 out of 5, 328 reviews" />

Accessibility

Key Action
Tab Moves focus into the group (one stop, on the checked star).
→ ↓ Select one star higher; ← instead of → under dir="rtl".
← ↑ Select one star lower; → instead of ← under dir="rtl".
  • Each star is a 44px target on touch devices; the hover preview only runs on devices that hover.

  • Interactive mode is a native role="radiogroup" of radio inputs.

  • Each star’s <label> carries aria-label="N star(s)"; the group itself takes aria-label (default 'Rating').

  • Read-only mode uses role="img" with an aria-label describing the value (default "${value} out of ${max}") — screen readers get one summary, not five decorative icons.

  • The star glyphs are aria-hidden; the labels carry the meaning.

  • Native semantics otherwise — no extra ARIA needed.

Tokens

Token Used for
--border-neutral Unfilled star
--background-{hue} Filled star (checked or hovered), per color
--outline-color-focus Focus outline on the focused star

Do / Don’t

  • Do use Rating for a 1–5 (or max) scale where more stars mean a stronger rating.
  • Do pass readonly when displaying an aggregate or average score users can’t edit.
  • Don’t rely on color alone — the aria-labels already carry the numeric value for assistive tech.
  • Don’t use Rating as a generic multi-select — it’s one value on a scale, not several independent toggles.

Content

  • aria-label on interactive mode defaults to “Rating” — override with what’s being rated (“Rate this product”).
  • Read-only aria-label defaults to “{value} out of {max}” — override to add context (“4.2 out of 5, 128 reviews”).