79 lines
2.0 KiB
Vue
79 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import type { GameDataKeyCodeCodes } from '#layers/types/api/gameData'
|
|
|
|
interface ButtonProps {
|
|
backgroundColor?: string
|
|
textColor?: string
|
|
icon?: string
|
|
disabled?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<ButtonProps>(), {
|
|
backgroundColor: 'var(--primary)',
|
|
textColor: 'var(--alternative-02)',
|
|
icon: '',
|
|
disabled: false,
|
|
})
|
|
|
|
// 색상 코드 키 목록 key_code_codes
|
|
const PARSED_KEY_CODE_CODES_KEYS: (keyof GameDataKeyCodeCodes)[] = [
|
|
'primary',
|
|
'text-primary',
|
|
'text-secondary',
|
|
'alternative-01',
|
|
'alternative-02',
|
|
]
|
|
|
|
// 색상 값을 CSS 변수로 변환하는 헬퍼 함수
|
|
const getColorValue = (color: string) =>
|
|
PARSED_KEY_CODE_CODES_KEYS.includes(color as keyof GameDataKeyCodeCodes)
|
|
? `var(--${color})`
|
|
: color
|
|
|
|
const buttonClasses = computed(() => [
|
|
'btn-base group relative inline-flex items-center justify-center font-medium border border-gray-600/30 overflow-hidden',
|
|
props.disabled ? 'cursor-default' : 'cursor-pointer',
|
|
])
|
|
|
|
const buttonStyles = computed(() => ({
|
|
backgroundColor: getColorValue(props.backgroundColor),
|
|
color: getColorValue(props.textColor),
|
|
}))
|
|
|
|
const overlayClasses = computed(() => [
|
|
'absolute inset-0 -m-px transition-opacity duration-200',
|
|
props.disabled
|
|
? 'opacity-20 z-10'
|
|
: 'bg-white opacity-0 group-hover:opacity-20',
|
|
])
|
|
|
|
const overlayDisabledStyles = computed(
|
|
() =>
|
|
props.disabled && {
|
|
backgroundColor: props.textColor,
|
|
}
|
|
)
|
|
|
|
const contentDisabledStyles = computed(() => props.disabled && { opacity: 0.2 })
|
|
</script>
|
|
|
|
<template>
|
|
<button
|
|
:class="buttonClasses"
|
|
:style="buttonStyles"
|
|
:disabled="props.disabled"
|
|
>
|
|
<!-- 호버 효과 / Disabled 오버레이 -->
|
|
<span :class="overlayClasses" :style="overlayDisabledStyles" />
|
|
|
|
<!-- 버튼 내용 -->
|
|
<span
|
|
class="relative flex items-center gap-2"
|
|
:style="contentDisabledStyles"
|
|
>
|
|
<slot />
|
|
<span v-if="props.icon" class="flex-shrink-0" v-html="props.icon" />
|
|
</span>
|
|
</button>
|
|
</template>
|