Rating

Rates with stars or shows a score.

Value: 4

<script setup lang="ts">
  import { ref } from 'vue'
  import { Rating, Stack, Text } from '@hina-ui/vue'

  const score = ref(4)
</script>

<template>
  <Stack gap="sm" align="start">
    <Rating v-model="score" size="lg" aria-label="Rating" />
    <Text tone="muted" size="sm">Value: {{ score }}</Text>
  </Stack>
</template>
vue

Usage

import { Rating } from '@hina-ui/vue'
ts

A rating is a row of stars: clicking a star picks that score, and hovering previews the stars up to it as filled. v-model binds the score and max sets the maximum score, 5 by default. The star count defaults to max; set stars to control it independently. Attributes it does not declare land on the group element that wraps the stars, so name it with aria-label or aria-labelledby.

Value: 0

<script setup lang="ts">
  import { ref } from 'vue'
  import { Rating, Stack, Text } from '@hina-ui/vue'

  const score = ref(0)
</script>

<template>
  <Stack gap="sm" align="start">
    <Rating v-model="score" aria-label="Rating" />
    <Text tone="muted" size="sm">Value: {{ score }}</Text>
  </Stack>
</template>
vue

Examples

Half stars

With step set to 0.5 every star splits into two halves, so scores such as 2.5 can be picked.

Value: 2.5

<script setup lang="ts">
  import { ref } from 'vue'
  import { Rating, Stack, Text } from '@hina-ui/vue'

  const score = ref(2.5)
</script>

<template>
  <Stack gap="sm" align="start">
    <Rating v-model="score" :step="0.5" aria-label="Rating" />
    <Text tone="muted" size="sm">Value: {{ score }}</Text>
  </Stack>
</template>
vue

Score scale and star count

max sets the maximum score and stars sets the displayed star count. With :max="10" :stars="5", each star represents 2 points and a value of 7 displays 3.5 stars.

step remains measured in stars: the default 1 selects whole stars, changing the score by 2 points; 0.5 changes it by 1 point. v-model, update:modelValue, and form values submitted through name always use the actual score. Read-only ratings fill proportionally, regardless of step.

7 / 10

8.6 / 10 · Read only

<script setup lang="ts">
  import { ref } from 'vue'
  import { Inline, Rating, Stack, Text } from '@hina-ui/vue'

  const score = ref(7)
</script>

<template>
  <Stack gap="md" align="start">
    <Inline gap="sm">
      <Rating v-model="score" :max="10" :stars="5" :step="0.5" aria-label="Rating" />
      <Text tone="muted" size="sm">{{ score }} / 10</Text>
    </Inline>
    <Inline gap="sm">
      <Rating :model-value="8.6" :max="10" :stars="5" readonly />
      <Text tone="muted" size="sm">8.6 / 10 · Read only</Text>
    </Inline>
  </Stack>
</template>
vue

Read-only display

readonly renders the rating as a display-only graphic; the value may be any decimal and the stars fill proportionally, which suits average scores.

4.3 from 128 ratings

<script setup lang="ts">
  import { Inline, Rating, Text } from '@hina-ui/vue'
</script>

<template>
  <Inline gap="sm">
    <Rating :model-value="4.3" readonly />
    <Text tone="muted" size="sm">4.3 from 128 ratings</Text>
  </Inline>
</template>
vue

Sizes

size has three steps, sm, md and lg.

<script setup lang="ts">
  import { Rating, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack align="start">
    <Rating :model-value="3" size="sm" aria-label="Small" />
    <Rating :model-value="3" size="md" aria-label="Medium" />
    <Rating :model-value="3" size="lg" aria-label="Large" />
  </Stack>
</template>
vue

States

disabled disables the group; clearable is on by default, so clicking the picked star again resets to zero, and turning it off keeps the score.

<script setup lang="ts">
  import { ref } from 'vue'
  import { Rating, Stack } from '@hina-ui/vue'

  const fixed = ref(3)
</script>

<template>
  <Stack align="start">
    <Rating :model-value="3" disabled aria-label="Disabled" />
    <Rating v-model="fixed" :clearable="false" aria-label="Not clearable" />
  </Stack>
</template>
vue

In a form

Inside a FormField the label is linked to the row of stars through aria-labelledby, and the error message is rendered by the field; validation rules and submission belong to the Form. The value is 0 until a rating is given.

<script setup lang="ts">
  import { reactive, ref } from 'vue'
  import * as v from 'valibot'
  import { Button, Form, FormField, Rating, Text } from '@hina-ui/vue'

  const schema = v.object({
    score: v.pipe(v.number(), v.minValue(1, 'Give it a rating first')),
  })

  const values = reactive({ score: 0 })
  const saved = ref('')

  async function save(data: unknown) {
    await new Promise(resolve => setTimeout(resolve, 600))
    saved.value = JSON.stringify(data)
  }
</script>

<template>
  <Form v-slot="{ submitting }" :values="values" :rules="schema" class="w-80" @submit="save">
    <FormField name="score" label="Rating" required>
      <Rating v-model="values.score" />
    </FormField>
    <Button type="submit" :loading="submitting" class="self-start">Submit review</Button>
    <Text v-if="saved" tone="muted" size="sm">Submitted: {{ saved }}</Text>
  </Form>
</template>
vue

Behavior

  • Clicking a star picks that score, and clicking the same star again resets to zero; hovering previews the stars up to the pointer as filled and leaving restores them.
  • With focus on a star, the left and right arrow keys move focus and pick, as in a radio group.
  • Color changes of the stars are transitioned.

Accessibility

  • When interactive the group is role="radiogroup" and every star or half star is a role="radio" with a localized name.
  • When read only the group is role="img" named by the locale as “n out of m stars”. When the star count differs from the maximum score, radio options and read-only graphics use the actual score, such as “7 out of 10 points”.
  • Name the group with aria-label or aria-labelledby.

API

Props

Prop
Type
Default
Description
modelValue
number
0
The score
max
number
5
Positive maximum score; also determines the star count when stars is omitted
stars
number
max
Displayed star count, a positive integer
step
1 | 0.5
1
Step in stars; the score increment is max / stars * step
clearable
boolean
true
Whether clicking the picked star again resets
readonly
boolean
false
Whether the rating is display only
name
string
—
Form field name
size
'sm' | 'md' | 'lg'
'md'
Size
disabled
boolean
false
Whether the rating is disabled
class
string
—
Classes appended to the root element

Events

Event
Payload
Description
update:modelValue
value: number
The score changed