フィードバック
Rating
クリックやホバーで選択できる星評価コンポーネント。
インストール
npx shadcn add https://d-ui.daigo-suhara.com/registry/rating.jsonサンプル
使い方
"use client";
import { Rating } from "@/components/ui/rating";
import { useState } from "react";
export default function Example() {
const [rating, setRating] = useState(3);
return <Rating value={rating} onChange={setRating} />;
}プロパティ
value任意number選択中の評価値
デフォルト:
0max任意number最大評価数
デフォルト:
5size任意"sm" | "md" | "lg"星のサイズ
デフォルト:
"md"readOnly任意boolean読み取り専用
デフォルト:
falseonChange必須(value: number) => void変更ハンドラ
| 名前 | 型 | デフォルト | 説明 | |
|---|---|---|---|---|
| 任意 | value | number | 0 | 選択中の評価値 |
| 任意 | max | number | 5 | 最大評価数 |
| 任意 | size | "sm" | "md" | "lg" | "md" | 星のサイズ |
| 任意 | readOnly | boolean | false | 読み取り専用 |
| 必須 | onChange | (value: number) => void | — | 変更ハンドラ |
ソースコード
"use client";
import * as React from "react";
import { Star } from "lucide-react";
import { cn } from "@/lib/utils";
interface RatingProps {
value?: number;
max?: number;
size?: "sm" | "md" | "lg";
readOnly?: boolean;
onChange?: (value: number) => void;
className?: string;
}
const sizes = {
sm: "h-4 w-4",
md: "h-5 w-5",
lg: "h-7 w-7",
};
export function Rating({
value = 0,
max = 5,
size = "md",
readOnly = false,
onChange,
className,
}: RatingProps) {
const [hovered, setHovered] = React.useState<number | null>(null);
const display = hovered ?? value;
return (
<div
className={cn("inline-flex items-center gap-0.5", className)}
onMouseLeave={() => setHovered(null)}
>
{Array.from({ length: max }, (_, i) => {
const filled = i + 1 <= display;
return (
<button
key={i}
type="button"
disabled={readOnly}
onClick={() => onChange?.(i + 1)}
onMouseEnter={() => !readOnly && setHovered(i + 1)}
className={cn(
"transition-transform focus-visible:outline-none",
!readOnly && "hover:scale-110 cursor-pointer",
readOnly && "cursor-default"
)}
>
<Star
className={cn(
sizes[size],
"transition-colors duration-150",
filled
? "fill-amber-400 text-amber-400"
: "fill-transparent text-muted-foreground/40"
)}
/>
</button>
);
})}
</div>
);
}