vue-rating-kit
Lightweight, accessible, enterprise-grade star rating component for Vue 3. Built with the Composition API, fully typed with TypeScript, and styled with pure CSS.
- Lightweight with zero runtime dependencies
- Precision ratings with configurable step values
- Fractional visual rendering (half, quarter, and tenth stars)
- Native RTL support through the
dirattribute - Touch-friendly interactions with drag support
- Accessible with ARIA support and screen reader improvements
- Keyboard navigation support
- Custom icon slots for emoji, text, and SVG icons
- Size variants with named presets and numeric pixel values
- Color customization via props and CSS custom properties
- Readonly and disabled modes
- TypeScript support with exported types
- Comprehensive test coverage
- Built for Vue 3 Composition API
Documentation · Interactive Playground · NPM · GitHub
Installation
npm install vue-rating-kitNote: Vue is a peer dependency and must already exist in your project.
Import the stylesheet once in your application entry:
import 'vue-rating-kit/style.css'Basic Usage
<script setup lang="ts">
import { ref } from 'vue'
import { VRating } from 'vue-rating-kit'
import 'vue-rating-kit/style.css'
const rating = ref(3)
</script>
<template>
<VRating v-model="rating" />
</template>Precision Ratings
Control the granularity of selectable rating values using the step prop.
Supported values:
| Step | Example Values |
|---|---|
1 |
1, 2, 3, 4, 5 |
0.5 |
0.5, 1.5, 2.5, 3.5, 4.5 |
0.25 |
0.25, 0.5, 0.75, 1.25, 1.5 |
0.2 |
0.2, 0.4, 0.6, 0.8, 1.2 |
0.1 |
0.1, 0.2, 0.3, 0.4, 0.5 |
Example:
<script setup lang="ts">
import { ref } from 'vue'
import { VRating } from 'vue-rating-kit'
import 'vue-rating-kit/style.css'
const rating = ref(2.5)
</script>
<template>
<VRating
v-model="rating"
:step="0.5"
/>
</template>RTL Support
vue-rating-kit automatically respects the native HTML dir attribute. No additional props are required.
<div dir="rtl">
<VRating
v-model="rating"
:step="0.5"
/>
</div>Note: LTR remains the default behavior. RTL activates automatically when the component or one of its ancestors has
dir="rtl".
Touch Support
Touch interactions work automatically on touch-enabled devices.
Supported interactions include:
- Tap to select a rating
- Drag across stars to preview ratings
- Fractional precision during drag interactions
- RTL-aware touch behavior
No additional configuration is required.
<VRating
v-model="rating"
:step="0.5"
/>Readonly Example
<script setup lang="ts">
import { ref } from 'vue'
import { VRating } from 'vue-rating-kit'
import 'vue-rating-kit/style.css'
const rating = ref(4)
</script>
<template>
<VRating
v-model="rating"
readonly
/>
</template>Disabled Example
<script setup lang="ts">
import { ref } from 'vue'
import { VRating } from 'vue-rating-kit'
import 'vue-rating-kit/style.css'
const rating = ref(2.5)
</script>
<template>
<VRating
v-model="rating"
:step="0.5"
disabled
/>
</template>Note: Disabled ratings preserve the current rating value while preventing all user interaction.
Custom Maximum Stars
Increase or decrease the number of available stars using the max prop.
<VRating
v-model="rating"
:max="10"
:step="0.5"
/>Custom Icon Slots
Replace the default star character with any inline content using the #filled and #empty named slots.
<!-- Emoji icons -->
<VRating v-model="rating">
<template #filled>❤️</template>
<template #empty>🤍</template>
</VRating>Both slots receive a scoped star prop containing the 1-based index of the star being rendered:
<VRating v-model="rating">
<template #filled="{ star }">
<span :title="`${star} stars`">★</span>
</template>
<template #empty="{ star }">
<span :title="`${star} stars`">☆</span>
</template>
</VRating>Slots work with all existing features — precision ratings, RTL, touch, keyboard, readonly, and disabled modes are unaffected.
Note: Slot content must be inline-level (a single emoji, text character, or an
inline/inline-blockSVG). Block-level elements break precision clipping, which relies onoverflow: hiddenand a dynamic width on the fill container.
Size Variants
Control star size using the size prop. Pass a named preset or an exact number of pixels.
Named presets scale both star size and the gap between stars:
<VRating v-model="rating" size="sm" />
<VRating v-model="rating" size="md" />
<VRating v-model="rating" size="lg" />| Preset | Star size | Gap |
|---|---|---|
sm |
1.25rem |
0.125rem |
md |
2rem |
0.25rem |
lg |
3rem |
0.5rem |
Numeric values set the star size in pixels. The gap retains its default value and can be overridden separately via --vrk-star-gap if needed:
<VRating v-model="rating" :size="40" />For sizes defined in other CSS units (rem, em, clamp(...)), set --vrk-star-size directly via CSS:
.my-rating {
--vrk-star-size: clamp(1.5rem, 3vw, 3rem);
}Color Customization
Use the color, emptyColor, and hoverColor props to customize star colors without writing CSS.
<!-- Filled star color only -->
<VRating v-model="rating" color="#e63946" />
<!-- Filled and empty colors -->
<VRating v-model="rating" color="#e63946" emptyColor="#dee2e6" />
<!-- Filled and explicit hover color -->
<VRating v-model="rating" color="green" hoverColor="darkgreen" />
<!-- Combined with size -->
<VRating v-model="rating" size="lg" color="tomato" emptyColor="#ddd" />All three props accept any valid CSS color value: named colors, hex, rgb(), hsl(), or var(--my-token) for design token integration.
Hover color inheritance
When hoverColor is omitted, the hover state automatically inherits the color prop value:
<!-- Hover stars will also be green -->
<VRating v-model="rating" color="green" />When neither hoverColor nor color is set, the package default hover color (#f5c842) is used.
Note: CSS custom properties take precedence over color props. Setting
--vrk-color-hoveron the component or a parent element always overrides thehoverColorprop, regardless of prop value. This lets you keep CSS as the authoritative color source while using props as convenient defaults.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue |
number |
0 |
Current rating value (use with v-model) |
max |
number |
5 |
Total number of stars |
step |
number |
1 |
Granularity of rating values. Supports 1, 0.5, 0.25, 0.2, and 0.1. Invalid values fall back to 1. |
readonly |
boolean |
false |
Prevents value changes while preserving the current rating display |
disabled |
boolean |
false |
Prevents all interaction while preserving the current rating display using disabled styling |
ariaLabel |
string |
'Rating' |
Accessible label for the rating group |
size |
'sm' | 'md' | 'lg' | number |
— | Star size. Named presets scale size and gap together. A number sets the star size in pixels only. |
color |
string |
— | Filled and partial star color. Accepts any CSS color value. Sets --vrk-color-filled as an inline style. |
emptyColor |
string |
— | Empty (unselected) star track color. Sets --vrk-color-empty as an inline style. |
hoverColor |
string |
— | Hover state color. Inherits from color when omitted. CSS variable --vrk-color-hover always takes precedence. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue |
number |
Emitted when the rating value changes |
change |
number |
Emitted when the rating value is committed by user interaction |
hover |
number |
Emitted when hovering over stars (0 on mouse leave) |
focus |
— | Emitted when keyboard focus enters the component |
blur |
— | Emitted when keyboard focus leaves the component |
Keyboard Navigation
| Key | Action |
|---|---|
ArrowRight |
Increment rating by the configured step value (LTR) |
ArrowLeft |
Decrement rating by the configured step value (LTR) |
Home |
Set rating to 0 |
End |
Set rating to the maximum value |
Note: In RTL contexts,
ArrowLeftincrements the rating andArrowRightdecrements it.
Invalid Step Values
The step prop must be a positive divisor of 1.
Unsupported values such as:
0.3
0.7
0.33will trigger a development warning and automatically fall back to 1.
Accessibility
vue-rating-kit follows accessible rating patterns and includes:
radiogroupsemantics for the rating containerradiosemantics for individual stars- Accurate
aria-checkedsupport for both integer and fractional ratings aria-disabledsupportaria-readonlysupport- Keyboard navigation support
- Focus and blur boundary handling
- Screen reader improvements for precision ratings
- Customizable accessible labels through the
ariaLabelprop
TypeScript
All public types are exported for use in TypeScript projects.
import type {
RatingValue,
RatingProps,
RatingEmits,
RatingSlotProps,
RatingSlots,
RatingSize,
} from 'vue-rating-kit'Example with a typed ref:
import { ref } from 'vue'
import type { RatingValue } from 'vue-rating-kit'
const rating = ref<RatingValue>(0)Use RatingSlotProps when building a typed wrapper around custom slot content:
import type { RatingSlotProps } from 'vue-rating-kit'
function renderIcon(props: RatingSlotProps) {
return props.star <= activeRating ? '❤️' : '🤍'
}CSS Customization
Override CSS custom properties on the .vrk-rating element or a parent element.
.vrk-rating {
--vrk-color-filled: #f5a623;
--vrk-color-empty: #d3d3d3;
--vrk-color-hover: #f5c842;
--vrk-color-disabled: #a9a9a9;
--vrk-star-size: 2rem;
--vrk-star-gap: 0.25rem;
--vrk-focus-outline: 2px solid currentColor;
}| Variable | Description |
|---|---|
--vrk-color-filled |
Filled star color |
--vrk-color-empty |
Empty star color |
--vrk-color-hover |
Hover highlight color |
--vrk-color-disabled |
Disabled star color |
--vrk-star-size |
Star size |
--vrk-star-gap |
Space between stars |
--vrk-focus-outline |
Keyboard focus outline |
Note: CSS custom properties always take precedence over component props. A
--vrk-color-hoverrule set on the component or any ancestor will override thehoverColorprop. This makes the CSS variable system the authoritative customization layer, with props serving as convenient in-template defaults.
Development
npm install
npm run test:run
npm run buildSee CONTRIBUTING.md for full contribution guidelines.
Migration Guide
No migration guides are currently required.
vue-rating-kit 1.0.0 is the first stable release. No breaking changes have been introduced.
Future migration guides will be documented here when breaking changes occur.
License
MIT