How would you design a star rating component with half‑stars in React?

Build a flexible star rating component supporting half-stars, hover preview, keyboard accessibility, and controlled/uncontrolled usage.

intermediateUi patternsreactratingui component
Published: 11/23/2025
Updated: 11/23/2025

Advertisement

🧩 Scenario

You need a star rating component like Airbnb or Amazon that supports:

  • Half‑star ratings
  • Highlighting during hover
  • Keyboard accessibility (ArrowLeft/ArrowRight)
  • Controlled + uncontrolled modes
  • Customizable star icons

🧠 Answer (Design Overview)

Core Logic

  1. Value Representation
    Use values like 0, 0.5, 1, 1.5, ....

  2. Hover Preview
    During hover, temporarily show a preview before committing.

  3. Half-Star Detection

const rect = e.currentTarget.getBoundingClientRect();
const x = e.clientX - rect.left;
const isHalf = x < rect.width / 2;
  1. Keyboard Support Arrow keys adjust value by increments of 0.5.

  2. Controlled vs Uncontrolled If value prop is present → controlled; otherwise use internal state.

Tradeoffs:

  • SVG masking provides smoother visuals but more complex.
  • Pixel-perfect half-star alignment requires consistent icon aspect ratio.

🎯 Live Demo


🔍 Real-World Tips

  • Use SVG mask for smoother half-star gradients.
  • Add aria-label for accessibility.
  • Make the component pure + memoized for lists of ratings.
  • Add controlled form support (Formik/React Hook Form).

Quick Practice

  1. Add label tooltips on hover ("3.5 out of 5").
  2. Allow custom icons via render props.
  3. Add read-only mode.
  4. Add animations on selection.

Summary

  • Detect half-stars using mouse position.
  • Maintain hover state separate from value.
  • Support both controlled/uncontrolled usage.
  • Use SVG for precise and scalable star visuals.
Frequently Asked Questions

How do you detect half-star clicks?

Measure mouse position relative to star width. If x < 50%, treat as half.

Should the component be controlled or uncontrolled?

Support both — accept `value` + `onChange`, and also allow internal state.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement