import { RatingGroup } from "@chakra-ui/react"
const Demo = () => {
return (
<RatingGroup.Root count={5} defaultValue={3} size="sm">
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Usage
import { RatingGroup } from "@chakra-ui/react"
<RatingGroup.Root>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
<RatingGroup.Item>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
</RatingGroup.Control>
</RatingGroup.Root>
Examples
Sizes
Use the size
prop to change the size of the rating component.
import { For, RatingGroup, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack>
<For each={["xs", "sm", "md", "lg"]}>
{(size) => (
<RatingGroup.Root key={size} count={5} defaultValue={3} size={size}>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)}
</For>
</Stack>
)
}
Controlled
Use the value
and onValueChange
prop to control the rating value.
"use client"
import { RatingGroup } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState(3)
return (
<RatingGroup.Root
count={5}
value={value}
onValueChange={(e) => setValue(e.value)}
>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Store
An alternative way to control the rating is to use the RootProvider
component
and the useRatingGroup
store hook.
This way you can access the rating state and methods from outside the component.
"use client"
import { RatingGroup, useRatingGroup } from "@chakra-ui/react"
const Demo = () => {
const store = useRatingGroup({ count: 5, defaultValue: 3 })
return (
<RatingGroup.RootProvider value={store} size="sm">
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{store.items.map((index) => (
<RatingGroup.Item key={index} index={index}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.RootProvider>
)
}
ReadOnly
Use the readOnly
prop to make the rating component read-only.
import { RatingGroup } from "@chakra-ui/react"
const Demo = () => {
return (
<RatingGroup.Root readOnly count={5} defaultValue={3} size="sm">
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Hook Form
Here's an example of how to use rating with react-hook-form
.
"use client"
import { Button, Field, RatingGroup, Stack } from "@chakra-ui/react"
import { zodResolver } from "@hookform/resolvers/zod"
import { Controller, useForm } from "react-hook-form"
import { z } from "zod"
const formSchema = z.object({
rating: z.number({ required_error: "Rating is required" }).min(1).max(5),
})
type FormValues = z.infer<typeof formSchema>
const Demo = () => {
const {
handleSubmit,
formState: { errors },
control,
} = useForm<FormValues>({
resolver: zodResolver(formSchema),
})
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}>
<Stack gap="4" align="flex-start">
<Field.Root invalid={!!errors.rating}>
<Field.Label>Rating</Field.Label>
<Controller
control={control}
name="rating"
render={({ field }) => (
<RatingGroup.Root
count={5}
name={field.name}
value={field.value}
onValueChange={({ value }) => field.onChange(value)}
>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)}
/>
<Field.ErrorText>{errors.rating?.message}</Field.ErrorText>
</Field.Root>
<Button size="sm" type="submit">
Submit
</Button>
</Stack>
</form>
)
}
Custom Icon
Use the icon
prop to pass a custom icon to the rating component. This will
override the default star icon.
import { RatingGroup } from "@chakra-ui/react"
import { IoHeart } from "react-icons/io5"
const Demo = () => {
return (
<RatingGroup.Root count={5} defaultValue={4} colorPalette="red">
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator icon={<IoHeart />} />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Half Star
Use the allowHalf
prop to allow half-star ratings.
import { RatingGroup } from "@chakra-ui/react"
const Demo = () => {
return (
<RatingGroup.Root allowHalf count={5} defaultValue={3.5} size="sm">
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Emoji
Compose the rating component with emojis.
import { RatingGroup } from "@chakra-ui/react"
const emojiMap: Record<string, string> = {
1: "😡",
2: "😠",
3: "😐",
4: "😊",
5: "😍",
}
const Demo = () => {
return (
<RatingGroup.Root count={5} defaultValue={3}>
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item
key={index}
index={index + 1}
minW="9"
filter={{ base: "grayscale(1)", _checked: "revert" }}
transition="scale 0.1s"
_hover={{ scale: "1.1" }}
>
{emojiMap[index + 1]}
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
}
Colors
Use the colorPalette
prop to change the color of the rating
gray
red
green
blue
teal
pink
purple
cyan
orange
yellow
import { RatingGroup, Stack, Text } from "@chakra-ui/react"
import { colorPalettes } from "compositions/lib/color-palettes"
const Demo = () => {
return (
<Stack gap="2" align="flex-start">
{colorPalettes.map((colorPalette) => (
<Stack
align="center"
key={colorPalette}
direction="row"
gap="10"
px="4"
>
<Text minW="8ch">{colorPalette}</Text>
<RatingGroup.Root
count={5}
defaultValue={3}
size="sm"
colorPalette={colorPalette}
>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
</Stack>
))}
</Stack>
)
}
Testimonial
Use the rating component to show testimonials.
Sage is a great software engineer. He is very professional and knowledgeable.

Matthew Jones
CTO, Company
import { Avatar, HStack, RatingGroup, Stack, Text } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack maxW="320px" gap="4">
<RatingGroup.Root
colorPalette="orange"
readOnly
count={5}
defaultValue={5}
size="xs"
>
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: 5 }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
<Text>
Sage is a great software engineer. He is very professional and
knowledgeable.
</Text>
<HStack gap="4">
<Avatar.Root>
<Avatar.Fallback name="Matthew Jones" />
<Avatar.Image src="https://randomuser.me/api/portraits/men/70.jpg" />
</Avatar.Root>
<Stack textStyle="sm" gap="0">
<Text fontWeight="medium">Matthew Jones</Text>
<Text color="fg.muted">CTO, Company</Text>
</Stack>
</HStack>
</Stack>
)
}
Closed Component
Here's how to setup the Rating for a closed component composition.
import { RatingGroup } from "@chakra-ui/react"
import * as React from "react"
export interface RatingProps extends RatingGroup.RootProps {
icon?: React.ReactElement
count?: number
label?: React.ReactNode
}
export const Rating = React.forwardRef<HTMLDivElement, RatingProps>(
function Rating(props, ref) {
const { icon, count = 5, label, ...rest } = props
return (
<RatingGroup.Root ref={ref} count={count} {...rest}>
{label && <RatingGroup.Label>{label}</RatingGroup.Label>}
<RatingGroup.HiddenInput />
<RatingGroup.Control>
{Array.from({ length: count }).map((_, index) => (
<RatingGroup.Item key={index} index={index + 1}>
<RatingGroup.ItemIndicator icon={icon} />
</RatingGroup.Item>
))}
</RatingGroup.Control>
</RatingGroup.Root>
)
},
)
Usage
<Rating defaultValue={3} size="sm" />
Props
Root
Prop | Default | Type |
---|---|---|
count | '5' | number The total number of ratings. |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' | 'accent' The color palette of the component |
size | 'md' | 'xs' | 'sm' | 'md' | 'lg' The size of the component |
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. | |
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. | |
name | string The name attribute of the rating element (used in forms). | |
onHoverChange | (details: HoverChangeDetails) => void Function to be called when the rating value is hovered. | |
onValueChange | (details: ValueChangeDetails) => void Function to be called when the rating value changes. | |
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 | |
value | number The current rating value. | |
as | React.ElementType The underlying element to render. | |
unstyled | boolean Whether to remove the component's style. |
Item
Prop | Default | Type |
---|---|---|
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. |