114 lines
2.6 KiB
Vue
114 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import type { ButtonType } from '#layers/types/components/button'
|
|
|
|
interface props {
|
|
type?: ButtonType
|
|
buttonSize?: string
|
|
target?: '_self' | '_blank'
|
|
href?: string
|
|
rel?: string
|
|
backgroundColor?: string
|
|
textColor?: string
|
|
disabled?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<props>(), {
|
|
type: 'action',
|
|
buttonSize: 'size-small md:size-large',
|
|
target: '_blank',
|
|
backgroundColor: 'var(--primary)',
|
|
textColor: 'var(--alternative-02)',
|
|
disabled: false,
|
|
})
|
|
|
|
const componentTag = computed((): string => {
|
|
switch (props.type) {
|
|
case 'external':
|
|
case 'download':
|
|
case 'link':
|
|
return 'a'
|
|
case 'internal':
|
|
return 'AtomsLocaleLink'
|
|
default:
|
|
return 'button'
|
|
}
|
|
})
|
|
const componentProps = computed(() => {
|
|
const baseProps = { disabled: props.disabled }
|
|
|
|
if (
|
|
props.type === 'external' ||
|
|
props.type === 'download' ||
|
|
props.type === 'link'
|
|
) {
|
|
return {
|
|
...baseProps,
|
|
href: props.href,
|
|
target: props.target,
|
|
rel: props.rel,
|
|
}
|
|
}
|
|
|
|
if (props.type === 'internal') {
|
|
return {
|
|
...baseProps,
|
|
to: props.href,
|
|
}
|
|
}
|
|
|
|
return baseProps
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<component
|
|
:is="componentTag"
|
|
v-bind="{ ...componentProps }"
|
|
:class="['btn-base', props.buttonSize]"
|
|
:style="{
|
|
backgroundColor: props.backgroundColor,
|
|
color: props.textColor,
|
|
'--text-color': props.textColor,
|
|
}"
|
|
>
|
|
<span class="btn-content">
|
|
<slot />
|
|
<AtomsIconsLongArrowRightLine
|
|
v-if="props.type === 'internal'"
|
|
class="icon"
|
|
/>
|
|
<AtomsIconsWebLinkLine
|
|
v-if="props.type === 'external'"
|
|
color="#ebebeb"
|
|
class="icon"
|
|
/>
|
|
<AtomsIconsDownloadLine v-if="props.type === 'download'" class="icon" />
|
|
</span>
|
|
</component>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.btn-base {
|
|
@apply overflow-hidden relative inline-flex items-center justify-center font-medium cursor-pointer
|
|
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-white/10
|
|
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:transition-opacity after:duration-300 after:ease-in-out after:opacity-0;
|
|
}
|
|
.btn-base:hover {
|
|
@apply after:opacity-20;
|
|
}
|
|
.btn-base:disabled {
|
|
@apply cursor-default
|
|
after:bg-[var(--text-color)] after:opacity-20 after:z-[2];
|
|
}
|
|
|
|
.btn-base:disabled .btn-content {
|
|
@apply opacity-50;
|
|
}
|
|
.btn-base .btn-content {
|
|
@apply relative flex items-center gap-1 z-[1];
|
|
}
|
|
.btn-base.size-extra-small .btn-content {
|
|
@apply gap-0.5;
|
|
}
|
|
</style>
|