Files
RepoDructor/components/IconButton.client.vue
2025-08-10 00:58:31 -06:00

147 lines
2.7 KiB
Vue

<template>
<BaseButton
variant="icon"
:active="active"
:disabled="disabled"
:title="title"
@click="$emit('click', $event)"
:class="[
'icon-button',
{
'xsmall': size === 'xsmall',
'large': size === 'large',
'small': size === 'small'
}
]"
>
<component v-if="typeof icon === 'object' || typeof icon === 'function'" :is="icon" class="icon" :size="iconSize" />
<span v-else class="icon">{{ icon }}</span>
<div v-if="badge" class="badge">{{ badge }}</div>
</BaseButton>
</template>
<script setup>
import { computed } from 'vue'
import BaseButton from './BaseButton.client.vue'
const props = defineProps({
icon: {
type: [String, Object, Function],
required: true
},
active: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
size: {
type: String,
default: 'normal',
validator: (value) => ['xsmall', 'small', 'normal', 'large'].includes(value)
},
badge: {
type: [String, Number],
default: null
}
})
defineEmits(['click'])
const iconSize = computed(() => {
switch (props.size) {
case 'xsmall': return 16
case 'small': return 18
case 'large': return 28
default: return 20
}
})
</script>
<style scoped>
.icon-button {
position: relative;
}
.icon-button.xsmall {
width: 28px;
height: 28px;
font-size: 0.8rem;
}
.icon-button.small {
width: 36px;
height: 36px;
font-size: 0.9rem;
}
.icon-button.large {
width: 60px;
height: 60px;
font-size: 1.5rem;
}
.icon {
display: block;
transition: transform 0.2s ease;
}
.icon-button:hover .icon {
transform: scale(1.1);
}
.badge {
position: absolute;
top: -4px;
right: -4px;
background: var(--accent-primary);
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: 600;
z-index: 1;
}
/* Special animations for specific icons */
.icon-button[title*="Shuffle"]:hover .icon {
animation: shuffle 0.5s ease-in-out;
}
.icon-button[title*="Repeat"]:hover .icon {
animation: rotate 0.5s ease-in-out;
}
.icon-button[title*="Play"]:hover .icon,
.icon-button[title*="Pause"]:hover .icon {
animation: pulse-icon 0.3s ease-in-out;
}
@keyframes shuffle {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-2px); }
75% { transform: translateX(2px); }
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes pulse-icon {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
</style>