WebberUI

星級評分(React)

經典星星評分的 React 元件:支援半星、hover 預覽填色、方向鍵與數字鍵操作、點選時星星彈跳,唯讀模式可顯示平均分、評分人數與分佈長條;圖示、顏色與顆數皆可自訂。

補齊最基本卻最常用的星星評分:每顆星都是一顆按鈕,指到哪填到哪(半星模式指左半邊就是 .5),移開就還原成目前分數;點選當下那顆星會彈跳一下。填色用「底層灰、上層依百分比裁切」兩層圖示疊出來,所以不只半星,唯讀模式下平均 4.3 也會精準填三成。鍵盤可用方向鍵、Home/End 與數字鍵操作,readOnly 時不可聚焦、可搭配 count 顯示「4.5(1,234)」與 distribution 分佈長條;iconcolormax 都能換,用 Heart 就是愛心評分。

載入預覽⋯
npx shadcn@latest add https://webberui.com/r/star-rating.json

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

5
<StarRating />

安裝

npx shadcn@latest add https://webberui.com/r/star-rating.json

或在 components.json 設定 registries 後,改用 @webberui/star-rating 安裝。

使用

import { StarRating, ratingSummary } from "@/components/ui/star-rating";
import { Heart } from "lucide-react";

// 可互動:半星、再點一次清空、顯示讀數與文字標籤
<StarRating
  allowHalf
  allowClear
  showValue
  labels={["很差", "差", "普通", "好", "很好"]}
  onChange={(value) => console.log(value)}
/>

// 唯讀平均分 + 評分人數 + 分佈長條(distribution 索引 0 為 1 星)
const distribution = [12, 25, 88, 340, 812];
const { average, total } = ratingSummary(distribution);
<StarRating value={average} readOnly showValue count={total} distribution={distribution} />

// 換圖示、顏色與顆數
<StarRating icon={Heart} color="#f43f5e" max={3} size="sm" defaultValue={2} />

Props

Prop型別預設值說明
valuenumber受控值(0–max;允許半星時可為 .5);不提供時為非受控模式
defaultValuenumber0非受控模式的初始值
onChange(value: number) => void值變動時回呼(點選、鍵盤操作與清空都會觸發)
maxnumber5星星顆數
allowHalfbooleanfalse允許半星:指到星星左半邊即為 .5,鍵盤以 0.5 為單位增減
readOnlybooleanfalse唯讀:不可聚焦、不可操作,只呈現分數(可為任意小數,例如平均 4.3 會填三成)
disabledbooleanfalse停用:保留外觀但不可操作,整體降低透明度
size"sm" | "md" | "lg" | number"md"尺寸:sm 16px/md 24px/lg 32px,或直接給像素數
iconLucideIconStar星星圖示(lucide-react 元件);換成 Heart 就是愛心評分
colorstring"#f59e0b"填色(任何 CSS 顏色值,如 #f59e0brgb(…)var(--primary)),預設琥珀色
showValuebooleanfalse在星星右側顯示分數讀數;hover 預覽時同步變化,提供 labels 時一併顯示該星的文字
countnumber評分人數,顯示為「(1,234)」並納入無障礙播報;通常搭配 readOnly 呈現平均分
labelsstring[]每顆星的文字說明(索引 0 對應 1 星),例如 ["很差","差","普通","好","很好"];播報為「3 星:普通」
allowClearbooleanfalse再點一次目前的分數即清空為 0(鍵盤 Backspace/Delete/數字 0 亦可清空)
distributionnumber[]評分分佈:索引 0 為 1 星的則數、依序到 max 星;畫面由高星到低星排列長條
ariaLabelstring"評分"評分群組的無障礙名稱
classNamestring透傳到最外層容器

另外具名匯出 ratingSummary(distribution)(回傳 { average, total },把後端的分佈直接換成平均分與總則數)、formatRatingValue(value)(讀數格式:整數不帶小數、其餘保留一位)與 StarRatingSize 型別。

細節

  • 兩層圖示疊出任意比例:每顆星底層是整顆灰色圖示,上層是同一顆圖示、外框依百分比裁切寬度;半星就是 50%,唯讀模式下平均 4.3 的第五顆會填 30%,換成任何 lucide 圖示都適用
  • 半星是兩顆按鈕allowHalf 時每顆星的左右半邊各是一顆透明按鈕(值分別為 n−0.5 與 n),不做座標運算,觸控與滑鼠行為一致;互動模式的值一律對齊步進,才有唯一對應的按鈕可標記選中
  • hover 只預覽、不改值:指到哪顆就填到哪並更新讀數,指標離開群組即還原;觸控不預覽,避免點一下閃兩次
  • 點選彈跳只在互動時:被選中的那顆星(半星時為所屬整顆)以 keyframes 放大再回彈;用 useAnimationControls 觸發,連續選同一顆也會重播
  • 鍵盤操作:←/↓ 減一步、→/↑ 加一步(半星時一步為 0.5),Home 跳最低、End 跳滿分,數字鍵直接指定分數;allowClear 時 Backspace/Delete/0 清空。焦點會跟著新選中的星星走(roving tabindex)
  • readOnly 與互動模式互斥:唯讀完全不渲染按鈕,因此無法聚焦;disabled 則保留按鈕但停用,整體降低透明度

可及性

  • 互動模式為 role="radiogroup"aria-label 取自 ariaLabel),每顆星(半星時為每半顆)是 role="radio" 的按鈕,aria-checked 標記目前分數、aria-label 播報「3 星:普通」或「2.5 星」;僅目前選中的按鈕在 Tab 序列中,其餘以方向鍵切換
  • 唯讀模式整列為 role="img",標籤為「4.5 星,滿分 5 星,共 1,277 則評分」;分佈長條是語意化的 ul,每列附有「5 星:812 則(64%)」的隱藏文字,評分本體再以 aria-describedby 指向它作為補充說明
  • 停用時按鈕帶 disabled 且群組標記 aria-disabled;讀數與星星圖示皆 aria-hidden,避免與 radio 播報重複
  • 使用者系統開啟「減少動態效果」時:點選不彈跳、hover 不放大,只保留填色與讀數變化

本頁目錄