Components
Rating group

Rating Group

Allows users to rate items using a set of icons.

Star IconStar IconStar IconStar IconStar Icon

Anatomy

To set up the rating correctly, you'll need to understand its anatomy and how we name its parts.

Each part includes a data-part attribute to help identify them in the DOM.

Examples

Learn how to use the RatingGroup component in your project. Let's take a look at the most basic example:

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root :count="5" :model-value="3">
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Using half ratings

Allow 0.5 value steps by setting the allowHalf prop to true. Ensure to render the correct icon if the isHalf value is set in the Rating components render callback.

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarHalfIcon, StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root :count="5" :model-value="3" allowHalf>
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted, half }">
            <StarHalfIcon v-if="half" />
            <StarIcon v-else-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Using a default value

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root :count="5" :model-value="2" readOnly>
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Controlled

When using the RatingGroup component, you can use the value and onValueChange props to control the state.

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { ref } from 'vue'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'

const value = ref(0)
</script>

<template>
  <RatingGroup.Root :count="5" v-model="value" allowHalf>
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Disabling the rating group

To make the rating group disabled, set the disabled prop to true.

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root :count="5" :model-value="3" disabled>
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Readonly rating group

To make the rating group readonly, set the readOnly prop to true.

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root :count="5" :model-value="3" readOnly>
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Usage within forms

To use the rating group within forms, pass the prop name. It will render a hidden input and ensure the value changes get propagated to the form correctly.

<script setup lang="ts">
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <RatingGroup.Root name="my-rating" :count="5" :model-value="3">
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.Root>
</template>

Using the Field Component

The Field component helps manage form-related state and accessibility attributes of a rating group. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.

<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import { RatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'
</script>

<template>
  <Field.Root>
    <RatingGroup.Root :count="5" :model-value="3">
      <RatingGroup.Label>Label</RatingGroup.Label>
      <RatingGroup.Control>
        <RatingGroup.Context v-slot="{ items }">
          <RatingGroup.Item v-for="item in items" :key="item" :index="item">
            <RatingGroup.ItemContext v-slot="{ highlighted }">
              <StarIcon v-if="highlighted" />
              <StarOutlineIcon v-else />
            </RatingGroup.ItemContext>
          </RatingGroup.Item>
        </RatingGroup.Context>
        <RatingGroup.HiddenInput />
      </RatingGroup.Control>
    </RatingGroup.Root>
    <Field.HelperText>Additional Info</Field.HelperText>
    <Field.ErrorText>Error Info</Field.ErrorText>
  </Field.Root>
</template>

Using the Root Provider

The RootProvider component provides a context for the rating-group. It accepts the value of the useRating-group hook. You can leverage it to access the component state and methods from outside the rating-group.

<script setup lang="ts">
import { RatingGroup, useRatingGroup } from '@ark-ui/vue/rating-group'
import { StarIcon, StarOutlineIcon } from 'lucide-vue-next'

const ratingGroup = useRatingGroup({ count: 5, modelValue: 3 })
</script>

<template>
  <button @click="ratingGroup.clearValue()">Clear</button>

  <RatingGroup.RootProvider :value="ratingGroup">
    <RatingGroup.Label>Label</RatingGroup.Label>
    <RatingGroup.Control>
      <RatingGroup.Context v-slot="{ items }">
        <RatingGroup.Item v-for="item in items" :key="item" :index="item">
          <RatingGroup.ItemContext v-slot="{ highlighted }">
            <StarIcon v-if="highlighted" />
            <StarOutlineIcon v-else />
          </RatingGroup.ItemContext>
        </RatingGroup.Item>
      </RatingGroup.Context>
      <RatingGroup.HiddenInput />
    </RatingGroup.Control>
  </RatingGroup.RootProvider>
</template>

If you're using the RootProvider component, you don't need to use the Root component.

API Reference

Root

PropDefaultType
allowHalf
boolean

Whether to allow half stars.

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
autoFocus
boolean

Whether to autofocus the rating.

count5
number

The total number of ratings.

defaultValue
number

The initial value of the rating group when it is first rendered. Use when you do not need to control the state of the rating group.

disabled
boolean

Whether the rating is disabled.

form
string

The associate form of the underlying input element.

id
string

The unique identifier of the machine.

ids
Partial<{ root: string label: string hiddenInput: string control: string item(id: string): string }>

The ids of the elements in the rating. Useful for composition.

modelValue
number

name
string

The name attribute of the rating element (used in forms).

readOnly
boolean

Whether the rating is readonly.

required
boolean

Whether the rating is required.

translations
IntlTranslations

Specifies the localized strings that identifies the accessibility elements and their states

EmitEvent
hoverChange
[details: HoverChangeDetails]

Function to be called when the rating value is hovered.

update:modelValue
[value: number]

The callback fired when the model value changes.

valueChange
[details: ValueChangeDetails]

Function to be called when the rating value changes.

Control

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]rating-group
[data-part]control
[data-readonly]Present when read-only
[data-disabled]Present when disabled

HiddenInput

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Item

PropDefaultType
index
number

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]rating-group
[data-part]item
[data-disabled]Present when disabled
[data-readonly]Present when read-only
[data-checked]Present when checked
[data-highlighted]Present when highlighted
[data-half]

Label

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]rating-group
[data-part]label
[data-disabled]Present when disabled

RootProvider

PropDefaultType
value
MachineApi<PropTypes>

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Accessibility

Keyboard Support

KeyDescription
ArrowRight
Moves focus to the next star, increasing the rating value based on the `allowHalf` property.
ArrowLeft
Moves focus to the previous star, decreasing the rating value based on the `allowHalf` property.
Enter
Selects the focused star in the rating group.