Star Rating

Develop a star rating component where users can set a rating by clicking on stars.

Solution

Select Rating

Explanation

The HTML Structure

An unordered list that displays 5 button elements. The text content of each button is either a filled in star or an empty one.

The rating state

The current rating of the star is set to 3 using useState.

Displaying the correct number of filled stars

The number of stars is created by using an array with values 1 to 5. The array is mapped over and the button attributes are determined using this index value.

If the rating stored in rating state, is higher than or equal to the current index value, the button text is set to a full star.

The button attributes

The aria-label ensures screen readers understand what the star on the button means.

The key is required on list items rendered by React.

The style attribute has a function, getStarRating to determine if it should be an empty or filled star.

The onClick function uses an arrow function to be able to send the index of the star to setRating.

The button content and style

The content is determined by a ternary operator that checks if the star isSelected.

A full star if it is, and empty if not.

The transform is a scale of 1.2 if selected so that it is clear which value is selected for user experience.

Code

import { useState } from "react";
import styles from "./Solution.module.css";

const Solution = () => {
  const [rating, setRating] = useState(3);

  const getStarStyle = (isSelected: boolean) => ({
    transform: isSelected ? "scale(1.2)" : "scale(1)",
  });

  return (
    <div>
      <h3>Select Rating</h3>
      <ul className={styles.list}>
        {[1, 2, 3, 4, 5].map((index) => {
          const isSelected = rating >= index;

          return (
            <button
              aria-label={`Rating ${index} out of 5`}
              key={index}
              className={styles.star}
              style={getStarStyle(isSelected)}
              onClick={() => setRating(index)}
            >
              {isSelected ? "" : ""}
            </button>
          );
        })}
      </ul>
    </div>
  );
};

export default Solution;

Styling

.list {
  display: flex;
  gap: 5px;
  margin-top: 10px;
}

.star {
  cursor: pointer;
  padding: 5px;
  font-size: 24px;
  border: none;
  background-color: transparent;
}

Links