Input Rating

GitHub
A component to display and collect ratings from users.

Usage

Use the v-model directive to control the rating value of the InputRating component.

<script setup lang="ts">
const value = ref(3)
</script>

<template>
  <UInputRating v-model="value" />
</template>

Use the default-value prop to set the initial value when you do not need to control its state.

<template>
  <UInputRating :default-value="3" />
</template>

Half Stars

Use the allow-half prop to enable half-star ratings. When enabled, clicking on the left half of a star will set a half-star value.

<script setup lang="ts">
const value = ref(3.5)
</script>

<template>
  <UInputRating allow-half v-model="value" />
</template>

Readonly

Use the readonly prop to display a rating without allowing user interaction. This is useful for displaying existing ratings.

<template>
  <UInputRating readonly v-model="value" />
</template>

Custom Icons

Use the icon prop to customize the icon used for stars. Defaults to i-lucide-star.

<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating icon="i-lucide-heart" v-model="value" />
</template>

Use the empty-icon prop to customize the icon used for empty stars. If not provided, uses the same icon as icon.

<script setup lang="ts">
const value = ref(3)
</script>

<template>
  <UInputRating icon="i-lucide-star" empty-icon="i-lucide-star-off" v-model="value" />
</template>
You can customize the default star icon globally in your app.config.ts under ui.icons.star key.
You can customize the default star icon globally in your vite.config.ts under ui.icons.star key.

Max Value

Use the max prop to set the maximum number of stars. Defaults to 5.

<script setup lang="ts">
const value = ref(7.5)
</script>

<template>
  <UInputRating :max="10" v-model="value" allow-half />
</template>

Color

Use the color prop to change the color of the filled stars.

<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating color="primary" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating color="success" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating color="warning" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating color="error" v-model="value" />
</template>

Size

Use the size prop to change the size of the stars.

<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating size="xs" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating size="sm" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating size="md" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating size="lg" v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4)
</script>

<template>
  <UInputRating size="xl" v-model="value" />
</template>

Disabled

Use the disabled prop to disable the InputRating component.

<script setup lang="ts">
const value = ref(3)
</script>

<template>
  <UInputRating disabled v-model="value" />
</template>

Examples

With Form Integration

The InputRating component integrates seamlessly with forms and supports form validation.

<script setup lang="ts">
const value = ref(0)
</script>

<template>
  <UInputRating name="rating" required v-model="value" />
</template>

Reading the Value

You can read the modelValue externally to use it in your application logic.

<script setup lang="ts">
const rating = ref(0)

watch(rating, (value) => {
  console.log('Rating changed:', value)
  // Save to database, update state, etc.
})
</script>

<template>
  <UInputRating v-model="rating" />
  <p>Current rating: {{ rating }}</p>
</template>

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

modelValue0 number

The rating value (0 to max).

defaultValue0 number

The default rating value.

max5 number

Maximum rating value.

allowHalffalseboolean

Allow half star ratings.

readonlyfalseboolean

Make the rating readonly (non-interactive).

disabledfalseboolean

Disable the rating.

iconappConfig.ui.icons.starany

The icon to use for stars.

emptyIconany

The icon to use for empty stars (outline version). If not provided, uses the same icon as icon but with outline style.

color'primary' "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"
size'md' "xs" | "sm" | "md" | "lg" | "xl"
name string

Form field name.

id string

Form field id.

requiredboolean

Form field required.

ui { root?: ClassNameValue; star?: ClassNameValue; starFilled?: ClassNameValue; starHalf?: ClassNameValue; }

Slots

Slot Type
star{ index: number; value: number; filled: boolean; half: boolean; }

Emits

Event Type
update:modelValue[value: number]
change[event: Event]

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    inputRating: {
      slots: {
        root: 'inline-flex items-center gap-0.5',
        star: 'relative inline-block cursor-pointer transition-colors select-none',
        starFilled: 'absolute inset-0 pointer-events-none',
        starHalf: 'absolute inset-0 pointer-events-none overflow-hidden'
      },
      variants: {
        size: {
          xs: {
            star: 'size-3'
          },
          sm: {
            star: 'size-4'
          },
          md: {
            star: 'size-5'
          },
          lg: {
            star: 'size-6'
          },
          xl: {
            star: 'size-7'
          }
        },
        color: {
          primary: {
            starFilled: 'text-primary-500 dark:text-primary-400',
            starHalf: 'text-primary-500 dark:text-primary-400'
          },
          secondary: {
            starFilled: 'text-secondary-500 dark:text-secondary-400',
            starHalf: 'text-secondary-500 dark:text-secondary-400'
          },
          success: {
            starFilled: 'text-success-500 dark:text-success-400',
            starHalf: 'text-success-500 dark:text-success-400'
          },
          info: {
            starFilled: 'text-info-500 dark:text-info-400',
            starHalf: 'text-info-500 dark:text-info-400'
          },
          warning: {
            starFilled: 'text-warning-500 dark:text-warning-400',
            starHalf: 'text-warning-500 dark:text-warning-400'
          },
          error: {
            starFilled: 'text-error-500 dark:text-error-400',
            starHalf: 'text-error-500 dark:text-error-400'
          },
          neutral: {
            starFilled: 'text-gray-500 dark:text-gray-400',
            starHalf: 'text-gray-500 dark:text-gray-400'
          }
        },
        readonly: {
          true: {
            root: 'cursor-default',
            star: 'cursor-default'
          },
          false: {
            star: 'hover:scale-110'
          }
        },
        disabled: {
          true: {
            root: 'opacity-75 cursor-not-allowed',
            star: 'cursor-not-allowed'
          }
        }
      },
      defaultVariants: {
        size: 'md',
        color: 'primary'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        inputRating: {
          slots: {
            root: 'inline-flex items-center gap-0.5',
            star: 'relative inline-block cursor-pointer transition-colors select-none',
            starFilled: 'absolute inset-0 pointer-events-none',
            starHalf: 'absolute inset-0 pointer-events-none overflow-hidden'
          },
          variants: {
            size: {
              xs: {
                star: 'size-3'
              },
              sm: {
                star: 'size-4'
              },
              md: {
                star: 'size-5'
              },
              lg: {
                star: 'size-6'
              },
              xl: {
                star: 'size-7'
              }
            },
            color: {
              primary: {
                starFilled: 'text-primary-500 dark:text-primary-400',
                starHalf: 'text-primary-500 dark:text-primary-400'
              },
              secondary: {
                starFilled: 'text-secondary-500 dark:text-secondary-400',
                starHalf: 'text-secondary-500 dark:text-secondary-400'
              },
              success: {
                starFilled: 'text-success-500 dark:text-success-400',
                starHalf: 'text-success-500 dark:text-success-400'
              },
              info: {
                starFilled: 'text-info-500 dark:text-info-400',
                starHalf: 'text-info-500 dark:text-info-400'
              },
              warning: {
                starFilled: 'text-warning-500 dark:text-warning-400',
                starHalf: 'text-warning-500 dark:text-warning-400'
              },
              error: {
                starFilled: 'text-error-500 dark:text-error-400',
                starHalf: 'text-error-500 dark:text-error-400'
              },
              neutral: {
                starFilled: 'text-gray-500 dark:text-gray-400',
                starHalf: 'text-gray-500 dark:text-gray-400'
              }
            },
            readonly: {
              true: {
                root: 'cursor-default',
                star: 'cursor-default'
              },
              false: {
                star: 'hover:scale-110'
              }
            },
            disabled: {
              true: {
                root: 'opacity-75 cursor-not-allowed',
                star: 'cursor-not-allowed'
              }
            }
          },
          defaultVariants: {
            size: 'md',
            color: 'primary'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes