close
Skip to content

pooyagolchian/vue-star-rate

Repository files navigation

⭐ vue-js-star-rating

Zero-dependency Vue 3.5+ star rating — WCAG 2.2 accessible, TypeScript-first, half-star precision, Lucide / FontAwesome / custom icons

npm version npm downloads license GitHub stars

📖 View Documentation →


✨ Features

Feature Description
🎯 Half-star ratings Precise 0.5-step ratings with visual half-fill support
📐 Size presets Five built-in sizes — xs · sm · md · lg · xl
🎨 Custom colors Per-state color tokens: empty, filled, hover, half
🔌 Icon providers Lucide, FontAwesome, or bring your own via scoped slot/render fn
⌨️ Keyboard navigation Arrow keys, Home, End, 0–9 — fully operable without mouse
🔒 Read-only mode Display-only ratings for reviews and dashboards
WCAG 2.2 accessible role="group", aria-pressed per star, aria-live counter
🔷 TypeScript-first Full generics, MaybeRefOrGetter<T> reactive options
Zero dependencies No runtime deps — only Vue 3.5+ as a peer
🌐 RTL support Right-to-left layout via :rtl="true"
🔁 Clearable / reset Built-in clear button and allow-reset-on-reclick behaviour
🧩 Slots API Override icon, counter, and clear button with your own markup

📦 Installation

# pnpm (recommended)
pnpm add vue-js-star-rating

# npm
npm install vue-js-star-rating

# yarn
yarn add vue-js-star-rating

Requires Vue 3.5+. This package uses defineModel, useTemplateRef, and MaybeRefOrGetter — all stable in Vue 3.5. It has zero runtime dependencies.


🚀 Quick Start

<script setup lang="ts">
import { ref } from 'vue';
import { VueStarRate } from 'vue-js-star-rating';
import 'vue-js-star-rating/dist/style.css';

const rating = ref(0);
</script>

<template>
  <VueStarRate v-model="rating" />
</template>

Global Plugin Registration

// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import VueStarRatePlugin from 'vue-js-star-rating';
import 'vue-js-star-rating/dist/style.css';

createApp(App).use(VueStarRatePlugin).mount('#app');

📖 Examples

Half-Star Ratings

<VueStarRate v-model="rating" :allow-half="true" :show-counter="true" />

Size Presets

<!-- Size Presets: xs(16px), sm(20px), md(24px), lg(32px), xl(40px) -->
<VueStarRate v-model="rating" size="xs" />
<VueStarRate v-model="rating" size="sm" />
<VueStarRate v-model="rating" size="md" />
<VueStarRate v-model="rating" size="lg" />
<VueStarRate v-model="rating" size="xl" />

<!-- Custom pixel size -->
<VueStarRate v-model="rating" :icon-size="28" />

Custom Colors

<VueStarRate
  v-model="rating"
  :colors="{
    empty: '#e5e7eb',
    filled: '#fbbf24',
    hover: '#fcd34d',
    half: '#fbbf24',
  }"
/>

Read-only Display

<VueStarRate v-model="rating" :readonly="true" :show-counter="true" />

Clearable Rating

<VueStarRate v-model="rating" :clearable="true" />

RTL Layout

<VueStarRate v-model="rating" :rtl="true" />

Icon Providers

<!-- Lucide icons (requires lucide-vue-next) -->
<VueStarRate v-model="rating" icon-provider="lucide" />

<!-- FontAwesome (requires @fortawesome/fontawesome-free CSS) -->
<VueStarRate v-model="rating" icon-provider="fontawesome" />

<!-- Custom slot icon -->
<VueStarRate v-model="rating" icon-provider="custom">
  <template #icon="{ filled, size, color }">
    <svg :width="size.width" :height="size.height" viewBox="0 0 24 24">
      <polygon points="12,2 15,9 22,9 17,14 19,21 12,17 5,21 7,14 2,9 9,9"
               :fill="filled ? color : 'none'" :stroke="color" stroke-width="2" />
    </svg>
  </template>
</VueStarRate>

Custom Star Count

<VueStarRate v-model="rating" :max-stars="10" />

Counter & Tooltips

<!-- Show counter -->
<VueStarRate v-model="rating" :show-counter="true" />

<!-- Custom counter template -->
<VueStarRate v-model="rating" :show-counter="true" counter-template="{value} / {max} stars" />

<!-- Tooltips on hover -->
<VueStarRate v-model="rating" :show-tooltip="true" />

<!-- Custom tooltip labels -->
<VueStarRate
  v-model="rating"
  :show-tooltip="true"
  :tooltip-labels="['Terrible', 'Bad', 'OK', 'Good', 'Excellent']"
/>

Full Configuration

<VueStarRate
  v-model="rating"
  :max-stars="5"
  :allow-half="true"
  :readonly="false"
  :show-counter="true"
  :show-tooltip="true"
  size="lg"
  :colors="{
    empty: '#27272a',
    filled: '#fbbf24',
    hover: '#fcd34d',
    half: '#fbbf24',
  }"
  :animation="{
    enabled: true,
    duration: 200,
    type: 'scale',
  }"
  @change="(val, old) => console.log(val, old)"
  @hover="(val) => console.log('hover:', val)"
/>

📋 Props API

Prop Type Default Description
v-model number 0 Rating value
maxStars number 5 Maximum number of stars
allowHalf boolean false Enable half-star ratings
size 'xs' | 'sm' | 'md' | 'lg' | 'xl' 'md' Size preset
iconSize number | { width, height } auto Custom pixel size
iconProvider 'custom' | 'lucide' | 'fontawesome' 'custom' Icon renderer
colors Partial<StarColors> see below Color configuration
animation Partial<AnimationConfig> see below Animation configuration
readonly boolean false Disable user interaction
disabled boolean false Disable + grey out component
clearable boolean false Show a clear button when rating > 0
allowReset boolean true Click active star again to reset
showCounter boolean false Show rating counter
counterTemplate string '{value} / {max}' Counter format template
showTooltip boolean false Show tooltips on star hover
tooltipLabels string[] Custom tooltip labels per star
minRating number 0 Minimum selectable value
step number 1 Increment step (overridden by allowHalf)
rtl boolean false Right-to-left layout
inline boolean false Inline layout mode
gap number 4 Gap between stars in pixels
ariaLabel string 'Star rating' Accessible group label
className string Extra CSS class on root element
faIcons { empty?, filled?, half? } FontAwesome class overrides
customIcon CustomIconRenderer Programmatic icon render function

StarColors type

interface StarColors {
  empty:   string  // default '#d1d5db' — unfilled star
  filled:  string  // default '#fbbf24' — filled star
  hover:   string  // default '#f59e0b' — hovered star
  half?:   string  // default = filled  — half-filled star
}

AnimationConfig type

interface AnimationConfig {
  enabled:  boolean                               // default true
  duration: number                                // default 200 ms
  type:     'scale' | 'bounce' | 'pulse' | 'none' // default 'scale'
}

🎰 Slots

Slot Scoped props Description
icon { filled, half, size, color, index } Custom icon per star
counter { value, max } Custom counter content
clear Custom clear button content

📡 Events

Event Payload Description
change (value, oldValue) Rating changed by user interaction
hover number | null Hover enters / leaves a star
focus Component received keyboard focus
blur Component lost focus

update:modelValue is handled automatically by v-model / defineModel.


⌨️ Keyboard Navigation

Key Action
Increase rating
Decrease rating
Home Set to minimum
End Set to maximum
1-9 Jump to specific value
0 Reset to minimum

🖥️ Exposed Methods

const ratingRef = ref<InstanceType<typeof VueStarRate>>();

ratingRef.value?.reset();          // Reset to initial value
ratingRef.value?.setRating(3.5);   // Set programmatically
ratingRef.value?.getRating();      // Get current value
ratingRef.value?.focus();          // Focus the component
ratingRef.value?.blur();           // Blur the component

🔄 Migrating from v2 to v3

Breaking Changes

v2.x v3.x
modelValue prop Managed by defineModel — template syntax unchanged
lucideIcons prop Removed — use icon-provider="lucide" instead
role="slider" on container role="group" — WCAG 2.2 compliant
animation: { scale: 1.15 } animation: { type: 'scale' } — no numeric scale key
peerDependencies: vue ^3.3.0 peerDependencies: vue ^3.5.0
Options API data()/methods Composition API + <script setup> / defineModel

Animation Migration

<!-- v2 — scale was never a valid AnimationConfig key -->
:animation="{ enabled: true, duration: 200, scale: 1.15 }"

<!-- v3 — use type instead -->
:animation="{ enabled: true, duration: 200, type: 'scale' }"

🛠️ Development

# Clone the repository
git clone https://github.com/pooyagolchian/vue-star-rate.git
cd vue-star-rate

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Run tests
pnpm test

# Build for production
pnpm build

# Documentation development
pnpm docs:dev

# Build documentation
pnpm docs:build

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.


📄 License

MIT © Pooya Golchian


Built with ❤️ for the Vue.js community

Packages

 
 
 

Contributors