Rating
Overview
A star-rating component built on a multi-slot Aria core: RatingRoot provides the slider context, state, and keyboard handling, while each RatingItem renders a single star. Supports controlled and uncontrolled modes, half-star precision, clear-on-repeat-click, read-only and disabled states, horizontal/vertical orientation, RTL direction, and native form integration through a visually hidden input. Use it whenever users need to express a graded preference—product reviews, feedback surveys, or skill self-assessment.
Usage
Features
- 🎚
modelValue/defaultValue— controlled and uncontrolled modes backed byuseControllableState - ⭐
max(default 5) drives the star count; eachRatingItemis generated from context - ½
allowHalfenables half-star precision; pointer position and arrow-key steps resolve to 0.5 increments - ♻️
allowClearresets the value to 0 when the current item is clicked again - ⌨️ Keyboard operable — ArrowUp/Right increments, ArrowDown/Left decrements, Home resets to 0, End sets to max
- ♿
role="slider"with fullaria-valuenow/min/max/valuetext/orientation/readonly/disabled/labelreflection - 🧭
orientation(horizontal/vertical) anddir(ltr/rtl) drive layout and ARIA orientation - 🎨
ratingVariants(6 sizes) +ratingItemVariants(8 colors × 2 variants × 6 sizes); default colorwarning, default variantfilled - 🧩
iconslot exposes{ index, value, state }(stateis'full' | 'half' | 'empty') for custom star rendering - 📝 Form integration via
VisuallyHiddenInputwhennameis provided - 🌐 Localized ARIA —
rating.ariaLabel,rating.starN({count} of {max} stars),rating.empty - 🚫
readonly+disabledstates with guarded pointer and keyboard handling
Demos
Basic
CustomIcon
API
Aria Layer
3Rating
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
color | ThemeColor | — | Theme color of the component. |
size | ThemeSize | — | Visual size of the component. |
variant | RatingVariant | — | Visual variant of the component. |
modelValue | number | — | The controlled value of the rating. Can be bound as `v-model`. |
defaultValue | number | — | The initial value of the rating when uncontrolled. |
max | number | — | The maximum rating value (number of items). |
allowHalf | boolean | — | Whether half-star precision is allowed. |
allowClear | boolean | — | Whether clicking the current value clears the rating to 0. |
readonly | boolean | — | Whether the rating is read-only (focusable but not interactive). |
disabled | boolean | — | Whether the rating is disabled (inert). |
orientation | DataOrientation | — | The orientation of the rating. |
dir | Direction | — | The reading direction of the rating. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | number | Event handler called when the rating value changes. |
hoverChange | number | null | Event handler called when the hover preview value changes. `null` when the pointer leaves. |
valueCommit | number | Event handler called when a rating interaction is committed (click or keyboard). |
RatingItem
Props
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | — | The zero-based index of the item within the rating. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
RatingRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | number | — | The controlled value of the rating. Can be bound as `v-model`. |
defaultValue | number | — | The initial value of the rating when uncontrolled. |
max | number | — | The maximum rating value (number of items). |
allowHalf | boolean | — | Whether half-star precision is allowed. |
allowClear | boolean | — | Whether clicking the current value clears the rating to 0. |
readonly | boolean | — | Whether the rating is read-only (focusable but not interactive). |
disabled | boolean | — | Whether the rating is disabled (inert). |
orientation | DataOrientation | — | The orientation of the rating. |
dir | Direction | — | The reading direction of the rating. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | number | Event handler called when the rating value changes. |
hoverChange | number | null | Event handler called when the hover preview value changes. `null` when the pointer leaves. |
valueCommit | number | Event handler called when a rating interaction is committed (click or keyboard). |
Notes
Architecture and benchmark differences
VeanUI splits the rating into Aria RatingRoot (slider context, useControllableState, keyboard navigation, ARIA reflection, half-step pointer resolution, VisuallyHiddenInput form binding) and Aria RatingItem (renders each star from context, exposes state for slot-driven icons). The UI wrapper SRating injects ratingVariants and ratingItemVariants classes via the standard multi-slot provide*Ui / useUiContext pattern; state and visuals stay decoupled through data-[state=...] selectors. Compared with AntD Rate, Element Plus el-rate, Mantine Rating, and Naive UI n-rate, VeanUI is the only benchmarked library with an Aria/styled split, RTL support, vertical orientation, and native form integration; shadcn ships no rating component.
| Capability | VeanUI | Ant Design | Element Plus | Mantine | Naive UI | shadcn |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — | — | — |
| Controlled/uncontrolled | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Half-star precision | ✅ | ✅ | ✅ | ✅ (fractions) | ✅ | — |
| Allow clear | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Read-only mode | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Custom icon (slot) | ✅ | ✅ (character) | ✅ (iconClass) | ✅ | ✅ | — |
| Keyboard navigation | ✅ | — | — | ✅ | — | — |
| RTL support | ✅ | — | — | — | — | — |
| Vertical orientation | ✅ | — | — | ✅ | — | — |
| Form integration | ✅ | — | — | ✅ | — | — |
| Color/size variants | ✅ | size | size | size | size/color | — |
Cautions
- The root element carries
role="slider"; do not addrole="img"or any other conflicting role to child items. - Half-star precision depends on the pointer position within a single item; on touch devices, consider increasing the hit area so users can reliably target the half region.
allowClearonly fires when the clicked item matches the current value—clicking any other item changes the value normally.- The
iconslot receivesstate('full'/'half'/'empty'); style custom icons withdata-[state=...]selectors or conditional rendering.
FAQ
Controlled or uncontrolled?
Pass modelValue with v-model for a controlled value, or defaultValue to let the rating own its state internally. Both are supported via useControllableState.
How do I use half-star precision?
Set allowHalf to true. Arrow keys then step by 0.5, and pointer position within an item determines whether the step resolves to a half or a full star.
How do I customize the icon?
Use the icon slot and read the state prop: <template #icon="{ state }">...</template>. The slot also receives index and value if you need position-aware rendering.
How do I clear the rating?
Set allowClear to true. Clicking the item that matches the current value resets the rating to 0; clicking any other item behaves normally.