app-s01qyw/frontend/src/components/StarRating.tsx
2026-09-29 20:17:53 +05:30

49 lines
1.4 KiB
TypeScript

import { useState } from 'react';
import { Star } from 'lucide-react';
interface StarRatingProps {
value: number;
onChange?: (rating: number) => void;
size?: number;
readonly?: boolean;
className?: string;
}
export function StarRating({
value,
onChange,
size = 20,
readonly = false,
className = '',
}: StarRatingProps) {
const [hover, setHover] = useState(0);
const interactive = !readonly && !!onChange;
return (
<div className={`flex items-center gap-1 ${className}`}>
{[1, 2, 3, 4, 5].map((star) => {
const filled = (hover || value) >= star;
return (
<button
key={star}
type="button"
disabled={!interactive}
onClick={() => interactive && onChange && onChange(star)}
onMouseEnter={() => interactive && setHover(star)}
onMouseLeave={() => interactive && setHover(0)}
className={`${interactive ? 'cursor-pointer transition-transform hover:scale-110' : 'cursor-default'} rounded p-0.5 focus:outline-none focus-visible:ring-1 focus-visible:ring-sky-500`}
aria-label={`${star} star${star > 1 ? 's' : ''}`}
>
<Star
size={size}
className={filled ? 'fill-amber-400 text-amber-500' : 'fill-none text-slate-300 dark:text-slate-600'}
/>
</button>
);
})}
</div>
);
}
export default StarRating;