Reka UI logoReka
backdrop
Components

Rating

A star-rating input where the user selects a score, with support for fractional values.

Features

  • Can be controlled or uncontrolled.
  • Supports fractional ratings (half, quarter, etc.) via the step prop.
  • Previews the value under the pointer on hover.
  • Can be cleared by clicking the active value again.
  • Built on top of Radio Group — full keyboard navigation and form support.
  • Supports Right to Left direction.
  • Exposes CSS variables for rendering partial steps.

Installation

Install the component from your command line.

sh
$ npm add reka-ui

Anatomy

Import all parts and piece them together. RatingRoot exposes the list of items, and each RatingItem exposes the steps it is made of, so you render an indicator per step.

vue
<script setup>
import { RatingItem, RatingItemIndicator, RatingRoot } from 'reka-ui'
</script>

<template>
  <RatingRoot v-slot="{ items }">
    <RatingItem
      v-for="item in items"
      :key="item"
      v-slot="{ steps }"
      :item="item"
    >
      <RatingItemIndicator
        v-for="step in steps"
        :key="step"
        :step="step"
      />
    </RatingItem>
  </RatingRoot>
</template>

API Reference

Root

Contains all the parts of a rating and provides the rating state. Renders a Radio Group under the hood, so it supports form submission and keyboard navigation.

Data AttributeValue
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Item

Wraps a single rating value (e.g. a single star). It computes the list of steps that compose this item based on the root's step prop, exposed via the default slot. Renders a label by default.

ItemIndicator

The interactive indicator rendered for each step of an item. It reflects whether the step is active based on the current (or hovered) value.

Data AttributeValue
[data-state]"active"
[data-disabled]Present when disabled

To render partial steps (for step values below 1), RatingItemIndicator exposes the following CSS variables:

CSS VariableDescription
--reka-rating-item-step-widthThe width this step should occupy within the item, e.g. 50% for a half step.
--reka-rating-item-step-opacity1 when the step should be visible, 0 otherwise (used to stack overlapping steps).
--reka-rating-item-step-z-indexThe stacking order of the step so smaller steps render above larger ones.

A typical fractional indicator clips its width and stacks steps using these variables:

vue
<RatingItemIndicator
  :step="step"
  class="absolute overflow-hidden w-[var(--reka-rating-item-step-width)] opacity-[var(--reka-rating-item-step-opacity)] z-[var(--reka-rating-item-step-z-index)]"
/>

Examples

Fractional rating

Use the step prop to allow values smaller than 1. Each RatingItem is then split into multiple steps, and each step renders its own indicator clipped with the exposed CSS variables.

vue
<script setup>
import { RatingItem, RatingItemIndicator, RatingRoot } from 'reka-ui'
import { ref } from 'vue'

const rating = ref(2.5)
</script>

<template>
  <RatingRoot
    v-slot="{ items }"
    v-model="rating"
    :step="0.5"
  >
    <RatingItem
      v-for="item in items"
      :key="item"
      v-slot="{ steps }"
      :item="item"
      class="relative"
    >
      <RatingItemIndicator
        v-for="step in steps"
        :key="step"
        :step="step"
        class="absolute overflow-hidden w-[var(--reka-rating-item-step-width)] opacity-[var(--reka-rating-item-step-opacity)] z-[var(--reka-rating-item-step-z-index)]"
      />
    </RatingItem>
  </RatingRoot>
</template>

Clearable

Use the clearable prop to let users reset the rating to 0 by clicking the currently selected value again.

vue
<template>
  <RatingRoot
    v-model="rating"
    clearable
  >
    <!-- ... -->
  </RatingRoot>
</template>

Hover preview

Use the hoverable prop to preview the value under the pointer before committing to it. The RatingItemIndicator exposes data-state="active" for every step at or below the hovered value.

vue
<template>
  <RatingRoot
    v-model="rating"
    hoverable
  >
    <!-- ... -->
  </RatingRoot>
</template>

Custom length

Use the length prop to change how many items are rendered. It defaults to 5.

vue
<template>
  <RatingRoot
    v-model="rating"
    :length="10"
  >
    <!-- ... -->
  </RatingRoot>
</template>

Read-only / disabled

Use the disabled prop to prevent interaction, for example when displaying an average rating.

vue
<template>
  <RatingRoot
    :default-value="4"
    disabled
  >
    <!-- ... -->
  </RatingRoot>
</template>

Accessibility

Built on top of the Radio Group primitive and adheres to the Radio Group WAI-ARIA design pattern. Provide an accessible label for each step via aria-label so screen reader users understand the value each indicator represents.

Keyboard Interactions

KeyDescription
Tab
Moves focus to either the checked item or the first item in the rating.
Space
When focus is on an unchecked item, selects that value.
ArrowDown
Moves focus and selection to the next item.
ArrowRight
Moves focus and selection to the next item.
ArrowUp
Moves focus and selection to the previous item.
ArrowLeft
Moves focus and selection to the previous item.