Star Ratings
The following rating component is single component meant to be used in a form or a feedback area. It takes allows to set any icons (Not just stars) and allows you set how many stars you want to display. It can be easily paired with an API or database and update in real time. You can also style it however you want quite easily.
No extra libraries required. Assuming you have Tailwind CSS installed
// App.jsximport React, { useState } from 'react';import Rating from './components/rating';
const FilledStar = () => ( <svg className="w-6 h-6 text-yellow-500" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 17.27L18.18 21 16.54 13.97 22 9.24 14.81 8.63 12 2 9.19 8.63 2 9.24 7.46 13.97 5.82 21z" /> </svg>);
const EmptyStar = () => ( <svg className="w-6 h-6 text-gray-300" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 17.27L18.18 21 16.54 13.97 22 9.24 14.81 8.63 12 2 9.19 8.63 2 9.24 7.46 13.97 5.82 21z" /> </svg>);
const App = () => { const handleRatingChange = (newRating) => { console.log(`New rating: ${newRating}`); // You can add more logic here, like updating a database or state }; return ( <div className="p-8"> <h1 className="text-2xl font-bold">Product Rating</h1> <Rating totalStars={5} initialRating={3} filledIcon={FilledStar} emptyIcon={EmptyStar} iconClassName="hover:text-yellow-400 transition" onClick={handleRatingChange} /> </div> );}
export default App;
// Rating.jsximport React, { useState } from 'react';
const Rating = ({ totalStars = 5, initialRating = 0, filledIcon: FilledIcon, emptyIcon: EmptyIcon, iconClassName = '', readOnly = false, onClick}) => { const [rating, setRating] = useState(initialRating);
const handleMouseEnter = (value) => { if (!readOnly) setRating(value); }; const handleMouseLeave = () => { if (!readOnly) setRating(initialRating); };
const handleClick = (value) => { if (!readOnly) { setRating(value); if (onClick) onClick(value); } };
return ( <div className="flex items-center"> {[...Array(totalStars)].map((_, index) => { const value = index + 1; return ( <button key={index} onClick={() => handleClick(value)} onMouseEnter={() => handleMouseEnter(value)} onMouseLeave={handleMouseLeave} className={`focus:outline-none ${iconClassName}`} > {value <= rating ? <FilledIcon /> : <EmptyIcon />} </button> ); })} <span className="ml-2 text-gray-700">{rating} / {totalStars}</span> </div> );};
export default Rating;