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>
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>
Use the readonly prop to display a rating without allowing user interaction. This is useful for displaying existing ratings. The component maintains its normal appearance but prevents user interaction.
<template>
<UInputRating readonly v-model="value" />
</template>
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>
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>
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>
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>
Use the disabled prop to disable the InputRating component. When disabled, the component has reduced opacity (75%) and shows a not-allowed cursor to indicate it's not interactive.
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<UInputRating disabled v-model="value" />
</template>
Both readonly and disabled prevent user interaction, but they have different visual appearances:
readonly: Maintains normal appearance (full opacity, default cursor). Use when you want to display a rating that cannot be changed but should look normal.disabled: Shows reduced opacity (75%) and a not-allowed cursor. Use when you want to clearly indicate that the rating is temporarily unavailable or inactive.<script setup lang="ts">
const value = ref(4.5)
</script>
<template>
<UInputRating readonly v-model="value" />
</template>
<script setup lang="ts">
const value = ref(4.5)
</script>
<template>
<UInputRating disabled v-model="value" />
</template>
The InputRating component displays a focus ring by default for accessibility purposes, helping keyboard users identify the focused element. If you need to remove the focus ring for design reasons, you can override it using the ui prop:
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<UInputRating v-model="value" :ui="{
star: 'focus-within:ring-0 focus-within:ring-offset-0'
}" />
</template>
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>
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>
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
modelValue | 0 | numberThe rating value (0 to max). |
defaultValue | 0 | numberThe default rating value. |
max | 5 | numberMaximum rating value. |
allowHalf | false | boolean Allow half star ratings. |
readonly | false | boolean Make the rating readonly (non-interactive). |
disabled | false | boolean Disable the rating. |
icon | appConfig.ui.icons.star | anyThe icon to use for stars. |
emptyIcon | anyThe icon to use for empty stars (outline version).
If not provided, uses the same icon as | |
color | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
size | 'md' | "xs" | "sm" | "md" | "lg" | "xl" |
name | stringForm field name. | |
id | stringForm field id. | |
required | boolean Form field required. | |
ui | { root?: ClassNameValue; star?: ClassNameValue; starFilled?: ClassNameValue; starHalf?: ClassNameValue; } |
| Slot | Type |
|---|---|
star | { index: number; value: number; filled: boolean; half: boolean; } |
| Event | Type |
|---|---|
update:modelValue | [value: number] |
change | [event: Event] |
export default defineAppConfig({
ui: {
inputRating: {
slots: {
root: 'inline-flex items-center gap-0.5',
star: 'relative inline-block cursor-pointer transition-colors select-none focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-white dark:focus-within:ring-offset-gray-900 rounded-sm',
starFilled: 'absolute inset-0 pointer-events-none',
starHalf: 'absolute inset-0 pointer-events-none overflow-hidden [clip-path:polygon(0_0,50%_0,50%_100%,0_100%)] [-webkit-clip-path:polygon(0_0,50%_0,50%_100%,0_100%)]'
},
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',
star: 'focus-within:ring-primary-500 dark:focus-within:ring-primary-400'
},
secondary: {
starFilled: 'text-secondary-500 dark:text-secondary-400',
starHalf: 'text-secondary-500 dark:text-secondary-400',
star: 'focus-within:ring-secondary-500 dark:focus-within:ring-secondary-400'
},
success: {
starFilled: 'text-success-500 dark:text-success-400',
starHalf: 'text-success-500 dark:text-success-400',
star: 'focus-within:ring-success-500 dark:focus-within:ring-success-400'
},
info: {
starFilled: 'text-info-500 dark:text-info-400',
starHalf: 'text-info-500 dark:text-info-400',
star: 'focus-within:ring-info-500 dark:focus-within:ring-info-400'
},
warning: {
starFilled: 'text-warning-500 dark:text-warning-400',
starHalf: 'text-warning-500 dark:text-warning-400',
star: 'focus-within:ring-warning-500 dark:focus-within:ring-warning-400'
},
error: {
starFilled: 'text-error-500 dark:text-error-400',
starHalf: 'text-error-500 dark:text-error-400',
star: 'focus-within:ring-error-500 dark:focus-within:ring-error-400'
},
neutral: {
starFilled: 'text-gray-500 dark:text-gray-400',
starHalf: 'text-gray-500 dark:text-gray-400',
star: 'focus-within:ring-gray-500 dark:focus-within:ring-gray-400'
}
},
readonly: {
true: {
root: 'cursor-default',
star: 'cursor-default'
},
false: {}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed',
star: 'cursor-not-allowed pointer-events-none'
},
false: {
star: 'hover:scale-110'
}
}
},
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})
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 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-white dark:focus-within:ring-offset-gray-900 rounded-sm',
starFilled: 'absolute inset-0 pointer-events-none',
starHalf: 'absolute inset-0 pointer-events-none overflow-hidden [clip-path:polygon(0_0,50%_0,50%_100%,0_100%)] [-webkit-clip-path:polygon(0_0,50%_0,50%_100%,0_100%)]'
},
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',
star: 'focus-within:ring-primary-500 dark:focus-within:ring-primary-400'
},
secondary: {
starFilled: 'text-secondary-500 dark:text-secondary-400',
starHalf: 'text-secondary-500 dark:text-secondary-400',
star: 'focus-within:ring-secondary-500 dark:focus-within:ring-secondary-400'
},
success: {
starFilled: 'text-success-500 dark:text-success-400',
starHalf: 'text-success-500 dark:text-success-400',
star: 'focus-within:ring-success-500 dark:focus-within:ring-success-400'
},
info: {
starFilled: 'text-info-500 dark:text-info-400',
starHalf: 'text-info-500 dark:text-info-400',
star: 'focus-within:ring-info-500 dark:focus-within:ring-info-400'
},
warning: {
starFilled: 'text-warning-500 dark:text-warning-400',
starHalf: 'text-warning-500 dark:text-warning-400',
star: 'focus-within:ring-warning-500 dark:focus-within:ring-warning-400'
},
error: {
starFilled: 'text-error-500 dark:text-error-400',
starHalf: 'text-error-500 dark:text-error-400',
star: 'focus-within:ring-error-500 dark:focus-within:ring-error-400'
},
neutral: {
starFilled: 'text-gray-500 dark:text-gray-400',
starHalf: 'text-gray-500 dark:text-gray-400',
star: 'focus-within:ring-gray-500 dark:focus-within:ring-gray-400'
}
},
readonly: {
true: {
root: 'cursor-default',
star: 'cursor-default'
},
false: {}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed',
star: 'cursor-not-allowed pointer-events-none'
},
false: {
star: 'hover:scale-110'
}
}
},
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})
]
})