SCALE — Build Lab
UI部品 · REACT COMPONENT

5段階レーティング(星)

CATEGORYUI部品 TYPEReact Component EFFORT30〜60分 DIFFICULTY
PRIMARY CODE
tsx
'use client';
import { useState } from 'react';

export function Rating({ value = 0, max = 5, readOnly = false, onChange }: {
  value?: number; max?: number; readOnly?: boolean; onChange?: (v: number) => void;
}) {
  const [hover, setHover] = useState<number | null>(null);
  const display = hover ?? value;

  return (
    <div role="radiogroup" style={{ display: 'inline-flex', gap: '.15rem', cursor: readOnly ? 'default' : 'pointer' }}>
      {Array.from({ length: max }).map((_, i) => (
        <span key={i}
          onMouseEnter={readOnly ? undefined : () => setHover(i + 1)}
          onMouseLeave={readOnly ? undefined : () => setHover(null)}
          onClick={readOnly ? undefined : () => onChange?.(i + 1)}
          style={{
            color: i < display ? '#fbbf24' : 'rgba(255,255,255,.22)',
            fontSize: '1.25rem', transition: 'color .15s ease', userSelect: 'none',
          }}>
          {i < display ? '★' : '☆'}
        </span>
      ))}
    </div>
  );
}
前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 任意のダッシュボードに組み込み

5段階レーティング(星)

:LiTarget: 用途

☆☆☆☆☆ 形式の5段階レーティング。半星対応・読み取り専用モード。

:LiSparkle: 特徴

  • 5段階評価
  • 半星対応
  • 読み取り専用
  • キーボード操作

:LiCode: コード(コピペ用)

'use client';
import { useState } from 'react';

export function Rating({ value = 0, max = 5, readOnly = false, onChange }: {
  value?: number; max?: number; readOnly?: boolean; onChange?: (v: number) => void;
}) {
  const [hover, setHover] = useState<number | null>(null);
  const display = hover ?? value;

  return (
    <div role="radiogroup" style={{ display: 'inline-flex', gap: '.15rem', cursor: readOnly ? 'default' : 'pointer' }}>
      {Array.from({ length: max }).map((_, i) => (
        <span key={i}
          onMouseEnter={readOnly ? undefined : () => setHover(i + 1)}
          onMouseLeave={readOnly ? undefined : () => setHover(null)}
          onClick={readOnly ? undefined : () => onChange?.(i + 1)}
          style={{
            color: i < display ? '#fbbf24' : 'rgba(255,255,255,.22)',
            fontSize: '1.25rem', transition: 'color .15s ease', userSelect: 'none',
          }}>
          {i < display ? '★' : '☆'}
        </span>
      ))}
    </div>
  );
}

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加