Skip to main content
View Zag.js on Github
Join the Discord server


Rating allows a user to add and remove rating to an item.



  • Syncs with disabled state of fieldset
  • Syncs with form reset events


To use the rating machine in your project, run the following command in your command line:

npm install @zag-js/rating-group @zag-js/react # or yarn add @zag-js/rating-group @zag-js/react

This command will install the framework agnostic rating logic and the reactive utilities for your framework of choice.


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.

On a high level, the rating consists of:

  • Root: The root container for the rating
  • Label: The label that gives the user information on the rating
  • Item: The element that visually represents the each rating item.
  • Item Group: The radiogroup wrapper for the rating items.
  • Input: The native html input that is visually hidden in the rating.


First, import the rating package into your project

import * as rating from "@zag-js/rating"

The rating package exports two key functions:

  • machine — The state machine logic for the rating widget.
  • connect — The function that translates the machine's state to JSX attributes and event handlers.

You'll also need to provide a unique id to the useMachine hook. This is used to ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the rating machine in your project 🔥

import * as rating from "@zag-js/rating-group" import { useMachine, normalizeProps } from "@zag-js/react" import { HalfStar, Star } from "./icons" function Rating() { const [state, send] = useMachine(rating.machine({ id: "1" })) const api = rating.connect(state, send, normalizeProps) return ( <div {...api.rootProps}> <label {...api.labelProps}>Rate:</label> <div {...api.controlProps}> { => { const state = api.getRatingState(index) return ( <span key={index} {...api.getRatingProps({ index })}> {state.isHalf ? <HalfStar /> : <Star />} </span> ) })} </div> <input {...api.hiddenInputProps} /> </div> ) }

Disabling the rating

To make rating disabled, set the context's disabled property to true

const [state, send] = useMachine( rating.machine({ disabled: true, }), )

Making the rating readonly

To make rating readonly, set the context's readOnly property to true

const [state, send] = useMachine( rating.machine({ readOnly: true, }), )

Setting the initial value

To set the rating's initial value, set the context's value property.

const [state, send] = useMachine( rating.machine({ value: 2.5, }), )

Listening for changes

When the rating value changes, the onChange callback is invoked.

const [state, send] = useMachine( rating.machine({ onChange({ value }) { console.log("rating value is:", value) // '1' | '2.5' | '4' }, }), )

Methods and Properties

The rating's api provides helpful properties and methods

isHoveringWhether the rating is being hovered
valueValue of the rating
hoveredValueHovered value of rating
sizeSize of the rating
getRatingStateGet info about a particular rating item by providing it's index
const api = connect(state, send) api.value // '1' | '2.5' | '4' api.isHovering // true | false api.getRatingState(0) /* { isEqual: true, isValueEmpty: false, isHighlighted: false, isHalf true, isChecked: true, } */

Usage within forms

To use rating within forms, use the exposed inputProps from the connect function and ensure you pass name value to the machine's context. It will render a hidden input and ensure the value changes get propagated to the form correctly.

const [state, send] = useMachine( rating.machine({ name: "rating", }), )

Styling guide

Earlier, we mentioned that each rating part has a data-part attribute added to them to select and style them in the DOM.

Disabled State

When the rating is disabled, the data-disabled attribute is added to the rating, control and label parts.

[data-part="rating"][data-disabled] { /* styles for rating disabled state */ } [data-part="label"][data-disabled] { /* styles for rating control disabled state */ } [data-part="input"][data-disabled] { /* styles for rating label disabled state */ }

Checked State

When the rating is checked, the data-checked attribute is added to the rating part.

[data-part="rating"][data-checked] { /* styles for rating checked state */ }

Readonly State

When the rating is readonly, the data-readonly attribute is added to the rating part.

[data-part="rating"][data-readonly] { /* styles for rating readonly state */ }


When a rating is highlighted, the data-highlighted attribute is added to the rating part.

[data-part="rating"][data-highlighted] { /* styles for highlighted rating */ }

Half rating

When a rating is half, the data-half attribute is added to the rating part.

[data-part="rating"][data-half] { /* styles for half rating */ }

Edit this page on GitHub

On this page