75 lines
1.7 KiB
Vue
75 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|
interface props {
|
|
type?: 'button' | 'link'
|
|
to?: string
|
|
target?: '_self' | '_blank'
|
|
backgroundColor?: string
|
|
srOnly?: string
|
|
}
|
|
|
|
const props = withDefaults(defineProps<props>(), {
|
|
type: 'button',
|
|
to: '',
|
|
target: '_self',
|
|
backgroundColor: '',
|
|
srOnly: '',
|
|
})
|
|
|
|
const componentTag = computed((): string => {
|
|
switch (props.type) {
|
|
case 'link':
|
|
return 'AtomsLocaleLink'
|
|
default:
|
|
return 'button'
|
|
}
|
|
})
|
|
const componentProps = computed(() => {
|
|
switch (props.type) {
|
|
case 'link':
|
|
return { to: props.to, target: props.target }
|
|
default:
|
|
return {}
|
|
}
|
|
})
|
|
|
|
const buttonStyle = computed(() => {
|
|
const style: Record<string, string> = {}
|
|
if (props.backgroundColor) {
|
|
style.backgroundColor = props.backgroundColor
|
|
}
|
|
return style
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<component
|
|
:is="componentTag"
|
|
v-bind="componentProps"
|
|
class="btn-circle"
|
|
:style="buttonStyle"
|
|
>
|
|
<span class="icon">
|
|
<slot />
|
|
</span>
|
|
<span class="sr-only">{{ props.srOnly }}</span>
|
|
</component>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.btn-circle {
|
|
@apply relative flex items-center justify-center rounded-full
|
|
w-[40px] h-[40px] md:w-[48px] md:h-[48px]
|
|
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.06)] before:rounded-full
|
|
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-full after:opacity-0 after:transition-all after:duration-300 after:ease-in-out
|
|
hover:after:opacity-10;
|
|
}
|
|
|
|
.btn-circle:deep(svg) {
|
|
@apply w-[20px] h-[20px] md:w-[24px] md:h-[24px];
|
|
}
|
|
|
|
.icon {
|
|
@apply transition-transform duration-300 ease-spring;
|
|
}
|
|
</style>
|