Rating

ARIAGitHubnpm
A star-rating input where the user selects a score, with support for fractional values.
<script setup lang="ts">
import { RatingItem, RatingItemIndicator, RatingRoot } from 'akar';
import { ref } from 'vue';
import './styles.css';

const rating = ref(3);
</script>

<template>
  <div class="akar-demo akar-demo-Rating">
    <RatingRoot
      v-slot="{ items }"
      v-model="rating"
      class="RatingRoot"
    >
      <RatingItem
        v-for="item in items"
        :key="item"
        v-slot="{ steps }"
        :item="item"
        class="RatingItem"
      >
        <RatingItemIndicator
          v-for="step in steps"
          :key="step"
          :step="step"
          :aria-label="`Rate ${step}`"
          class="RatingItemIndicator"
        >
          <PIcon
            name="i-lucide-star"
            class="RatingStar"
          />
        </RatingItemIndicator>
      </RatingItem>
    </RatingRoot>
  </div>
</template>

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.

pnpm add akar

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.

<script setup>
import { RatingItem, RatingItemIndicator, RatingRoot } from 'akar';
</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.

PropDefaultType
as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

clearable
boolean

When true, clicking the currently selected rating resets the value to 0.

defaultValue
number

The rating value when initially rendered. Use when you do not need to control the state of the rating.

dir
"ltr" | "rtl"

The reading direction of the combobox when applicable.

If omitted, inherits globally from ConfigProvider or assumes LTR (left-to-right) reading mode.

disabled
boolean

When true, prevents the user from interacting with radio items.

hoverable
boolean

When true, the rating previews the value under the pointer on hover.

length
5
number

The number of rating items to render.

loop
boolean

When true, keyboard navigation will loop from last item to first, and vice versa.

modelValue
number

The controlled rating value. Can be bound with v-model.

name
string

The name of the field. Submitted with its owning form as part of a name/value pair.

orientation
"horizontal"
"vertical" | "horizontal"

The orientation of the component.

required
boolean

When true, indicates that the user must set the value before the owning form can be submitted.

step
1
1 | 0.5 | 0.25 | 0.1

The granularity each rating item is divided into.

EventPayload
update:modelValue
payload: number

Event handler called when the value changes

Slot (default)Payload
modelValue
number
items
number[]

RatingRoot.vue source

Data attribute Value
[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.

PropDefaultType
as
"label"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

item*
number

The 1-based index of this item within the rating (e.g. the 3rd star).

Slot (default)Payload
steps
number[]

RatingItem.vue source

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.

PropDefaultType
as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

step*
number

The step value this indicator represents.

RatingItemIndicator.vue source

Data attribute Value
[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
--akar-rating-item-step-widthThe width this step should occupy within the item, e.g. 50% for a half step.
--akar-rating-item-step-opacity1 when the step should be visible, 0 otherwise (used to stack overlapping steps).
--akar-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:

<RatingItemIndicator
  :step="step"
  class="absolute overflow-hidden w-[var(--akar-rating-item-step-width)] opacity-[var(--akar-rating-item-step-opacity)] z-[var(--akar-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.

<script setup>
import { RatingItem, RatingItemIndicator, RatingRoot } from 'akar'
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(--akar-rating-item-step-width)] opacity-[var(--akar-rating-item-step-opacity)] z-[var(--akar-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.

<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.

<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.

<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.

<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

Key Description
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.