Skip to content

Instantly share code, notes, and snippets.

@r1q
Last active June 14, 2022 04:48
Show Gist options
  • Select an option

  • Save r1q/cf8112f32b07991d7e62744acaa63f04 to your computer and use it in GitHub Desktop.

Select an option

Save r1q/cf8112f32b07991d7e62744acaa63f04 to your computer and use it in GitHub Desktop.
React Rating Stars Component
// Usage: <RatingStars init={0} />
import React, { useState } from "react";
// Icons used for the rating-icon
import fullStarImg from "./assets/stars/full.png";
import halfStarImg from "./assets/stars/half.png";
import emptyStarImg from "./assets/stars/empty.png";
// Helper to calculate the mouse position on the icon
const isLessThanHalf = (event) => {
const { target } = event;
const boundingClientRect = target.getBoundingClientRect();
let mouseAt = event.clientX - boundingClientRect.left;
mouseAt = Math.round(Math.abs(mouseAt));
return mouseAt <= boundingClientRect.width / 2;
};
const RatingStars = ({ init }) => {
const [rating, setRating] = useState(init || 0);
const [hover, setHover] = useState(0);
const renderIcon = (current) => {
if ((hover || rating) + 0.5 === current) {
return halfStarImg;
} else if ((hover || rating) >= current) {
return fullStarImg;
} else {
return emptyStarImg;
}
};
const renderSymbol = (index) => {
return (
<img
key={`star-${index}`}
src={renderIcon(index)}
className="rating-image"
data-testid="rating-icon"
onClick={(e) => (isLessThanHalf(e) === true ? setRating(index - 0.5) : setRating(index))}
onMouseMove={(e) => (isLessThanHalf(e) === true ? setHover(index - 0.5) : setHover(index))}
onMouseLeave={(e) => setHover(rating)}
alt={"Rate"}
/>
);
};
return (
<div tabIndex="0" className="star-rating" data-testid="star-rating-container">
{[...Array(5)].map((star, index) => {
return renderSymbol(index + 1);
})}
</div>
);
};
export default RatingStars;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment