DEV Community

Cover image for Building a dead simple Rating component without any dependencies
Gabriel Linassi
Gabriel Linassi

Posted on

Building a dead simple Rating component without any dependencies

Hello guys ๐Ÿ‘‹ Today I want to share with you my solution to build a Rating component like the one bellow:

rating component react

This is a super simple component that has no interactivity functionality. It's just meant to display a rating. Initially I thought about using a 3rd party lib but the ones I found are outdated and super heavy (>70kb) for such a simple thing so I went ahead and built one myself.

The code:

import { useId } from "react";

const Star = ({ variant }: { variant: "filled" | "empty" | "half" }) => {
  const id = useId();

  let c1, c2;
  if (variant === "filled") {
    c1 = "#FBBC05";
    c2 = "#FBBC05";
  } else if (variant === "empty") {
    c1 = "#C4C4C4";
    c2 = "#C4C4C4";
  } else if (variant === "half") {
    c1 = "#FBBC05";
    c2 = "#C4C4C4";
  }

  return (
    <svg
      width="20"
      height="19"
      viewBox="0 0 20 19"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <defs>
        <linearGradient id={id}>
          <stop offset="50%" stopColor={c1} />
          <stop offset="50%" stopColor={c2} />
        </linearGradient>
      </defs>
      <path
        d="M10 0.148438L12.935 6.14144L19.5 7.10844L14.75 11.7704L15.871 18.3564L10 15.2454L4.129 18.3564L5.25 11.7704L0.5 7.10844L7.064 6.14144L10 0.148438Z"
        fill={`url(#${id})`}
      />
    </svg>
  );
};

const Rating = ({ rating, max = 5 }: { rating: number; max?: number }) => {
  return (
    <div className="flex items-center">
      {Array.from({ length: Math.floor(rating) }, (_, i) => (
        <Star key={i} variant="filled" />
      ))}
      {!Number.isInteger(rating) && <Star variant="half" />}
      {Array.from({ length: max - Math.ceil(rating) }, (_, i) => (
        <Star key={i} variant="empty" />
      ))}
    </div>
  );
};

export default Rating;
Enter fullscreen mode Exit fullscreen mode

๐Ÿšจ Realize I'm using React 18 useId hook because the lineargradient svg field needs a unique one.

Usage:

() => {
  return (
    <div>
      <Rating rating={1} />
      <Rating rating={1.5} />
      <Rating rating={2} />
      <Rating rating={2.5} />
      <Rating rating={3} />
      <Rating rating={3.5} />
      <Rating rating={4} />
      <Rating rating={4.5} />
      <Rating rating={5} />
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Sandbox:

Top comments (0)