值:4
'use client'
import { useState } from 'react'
import { Rating, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [score, setScore] = useState(4)
return (
<Stack gap="sm" align="start">
<Rating value={score} onValueChange={setScore} size="lg" aria-label="评分" />
<Text tone="muted" size="sm">
值:{score}
</Text>
</Stack>
)
}
tsx
用法
import { Rating } from '@hina-ui/react'
ts
评分由一排星组成,点击某颗星即选中该分值,悬停时前面的星预览为实心。value / onValueChange 绑定分值,max 指定满分,默认为 5。不传 stars 时星数与 max 相同;传入 stars 可独立指定显示的星数。未声明的属性都会传给包裹各星的组元素,请用 aria-label 或者 aria-labelledby 命名。
值:0
'use client'
import { useState } from 'react'
import { Rating, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [score, setScore] = useState(0)
return (
<Stack gap="sm" align="start">
<Rating value={score} onValueChange={setScore} aria-label="评分" />
<Text tone="muted" size="sm">
值:{score}
</Text>
</Stack>
)
}
tsx
示例
半星
step 设为 0.5 时每颗星分成左右两半,可以选出 2.5 这样的分值。
值:2.5
'use client'
import { useState } from 'react'
import { Rating, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [score, setScore] = useState(2.5)
return (
<Stack gap="sm" align="start">
<Rating value={score} onValueChange={setScore} step={0.5} aria-label="评分" />
<Text tone="muted" size="sm">
值:{score}
</Text>
</Stack>
)
}
tsx
分制与星数
max 为满分,stars 为显示的星数。设置 max={10} stars={5} 时,每颗星代表 2 分,值 7 显示为 3.5 颗星。
step 仍以星为单位:默认 1 表示整星,此时每次选择相差 2 分;设为 0.5 后每次相差 1 分。value、onValueChange 收到的值和通过 name 提交的表单值始终使用实际分值。只读展示按比例填充,不受 step 限制。
7 / 10
8.6 / 10 · 只读
'use client'
import { useState } from 'react'
import { Inline, Rating, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [score, setScore] = useState(7)
return (
<Stack gap="md" align="start">
<Inline gap="sm">
<Rating
value={score}
onValueChange={setScore}
max={10}
stars={5}
step={0.5}
aria-label="评分"
/>
<Text tone="muted" size="sm">
{score} / 10
</Text>
</Inline>
<Inline gap="sm">
<Rating value={8.6} max={10} stars={5} readonly />
<Text tone="muted" size="sm">
8.6 / 10 · 只读
</Text>
</Inline>
</Stack>
)
}
tsx
只读展示
readOnly 把评分渲染为只展示的图形,值可以是任意小数,星按比例填充,适合展示平均分。
4.3 分,共 128 人评分
import { Inline, Rating, Text } from '@hina-ui/react'
export default function Demo() {
return (
<Inline gap="sm">
<Rating value={4.3} readonly />
<Text tone="muted" size="sm">
4.3 分,共 128 人评分
</Text>
</Inline>
)
}
tsx
尺寸
size 有 sm、md、lg 三档。
import { Rating, Stack } from '@hina-ui/react'
export default function Demo() {
return (
<Stack align="start">
<Rating value={3} size="sm" aria-label="小号" />
<Rating value={3} size="md" aria-label="中号" />
<Rating value={3} size="lg" aria-label="大号" />
</Stack>
)
}
tsx
状态
disabled 禁用整组;clearable 默认开启,再次点击已选中的星会清零,关闭后不会。
'use client'
import { useState } from 'react'
import { Rating, Stack } from '@hina-ui/react'
export default function Demo() {
const [fixed, setFixed] = useState(3)
return (
<Stack align="start">
<Rating value={3} disabled aria-label="已禁用" />
<Rating value={fixed} onValueChange={setFixed} clearable={false} aria-label="不可清零" />
</Stack>
)
}
tsx
在表单中
放进 FormField 后,标签通过 aria-labelledby 关联到整组星,错误信息由字段渲染;校验规则与提交交给 Form。未打分时值是 0。
'use client'
import { useState } from 'react'
import * as v from 'valibot'
import { Button, Form, FormField, Rating, Text } from '@hina-ui/react'
const schema = v.object({
score: v.pipe(v.number(), v.minValue(1, '请先打分')),
})
export default function Demo() {
const [values, setValues] = useState({ score: 0 })
const [saved, setSaved] = useState('')
async function save(data: unknown) {
await new Promise(resolve => setTimeout(resolve, 600))
setSaved(JSON.stringify(data))
}
return (
<Form values={values} rules={schema} className="w-80" onSubmit={save}>
{({ submitting }) => (
<>
<FormField name="score" label="评分" required>
<Rating value={values.score} onValueChange={score => setValues({ ...values, score })} />
</FormField>
<Button type="submit" loading={submitting} className="self-start">
提交评价
</Button>
{saved && (
<Text tone="muted" size="sm">
已提交:{saved}
</Text>
)}
</>
)}
</Form>
)
}
tsx
行为
- 点击一颗星即选中该分值,再次点击同一颗星清零;悬停时前面的星预览为实心,移开后恢复。
- 焦点落在某颗星上时,左右方向键移动焦点并选中,与单选框组相同。
- 星的颜色变化有过渡。
无障碍
- 可交互时整组是
role="radiogroup",每颗星或者每半颗星是带本地化名称的role="radio"。 - 只读时整组是
role="img",名称是语言包给出的「n 星,满分 m 星」。星数与满分不同时,单选项与只读图形的名称使用实际分值,如「7 分,满分 10 分」。 - 通过
aria-label或者aria-labelledby为整组命名。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | number | 0 | 分值 |
max | number | 5 | 满分,须大于 0;未指定 stars 时也决定星数 |
stars | number | max | 显示的星数,须为正整数 |
step | 1 | 0.5 | 1 | 以星为单位的步长;实际分值步长为 max / stars * step |
clearable | boolean | true | 再次点击已选中的星是否清零 |
readOnly | boolean | false | 是否只展示 |
name | string | — | 表单字段名 |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
disabled | boolean | false | 是否禁用 |
className | string | — | 追加至根元素的类名 |
回调
| 回调 | 参数 | 说明 |
|---|---|---|
onValueChange | value: number | 分值变化 |