106 lines
2.0 KiB
Vue
106 lines
2.0 KiB
Vue
<template>
|
|
<div class="star-rating" :class="[`size-${size}`, { readonly }]">
|
|
<button
|
|
v-for="star in 5"
|
|
:key="star"
|
|
type="button"
|
|
class="star-btn"
|
|
:class="{ filled: star <= displayRating, hovered: star <= hoverRating }"
|
|
@click="!readonly && selectRating(star)"
|
|
@mouseenter="!readonly && (hoverRating = star)"
|
|
@mouseleave="hoverRating = 0"
|
|
:disabled="readonly"
|
|
>
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path
|
|
d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
|
|
:fill="star <= displayRating || star <= hoverRating ? 'currentColor' : 'none'"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, defineProps, defineEmits } from 'vue'
|
|
|
|
const props = defineProps({
|
|
rating: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
readonly: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
size: {
|
|
type: String,
|
|
default: 'medium',
|
|
validator: (v) => ['small', 'medium', 'large'].includes(v)
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['update:rating', 'rate'])
|
|
|
|
const hoverRating = ref(0)
|
|
|
|
const displayRating = computed(() => Math.round(props.rating))
|
|
|
|
function selectRating(star) {
|
|
emit('update:rating', star)
|
|
emit('rate', star)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.star-rating {
|
|
display: inline-flex;
|
|
gap: 2px;
|
|
}
|
|
|
|
.star-btn {
|
|
background: none;
|
|
border: none;
|
|
padding: 0;
|
|
cursor: pointer;
|
|
color: var(--color-border);
|
|
transition: all var(--transition-base);
|
|
}
|
|
|
|
.star-btn:disabled {
|
|
cursor: default;
|
|
}
|
|
|
|
.star-btn.filled,
|
|
.star-btn.hovered {
|
|
color: #f5a623;
|
|
}
|
|
|
|
.star-btn:not(:disabled):hover {
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
.readonly .star-btn {
|
|
cursor: default;
|
|
}
|
|
|
|
.size-small .star-btn svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
.size-medium .star-btn svg {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
|
|
.size-large .star-btn svg {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
</style>
|