166 lines
3.5 KiB
Vue
166 lines
3.5 KiB
Vue
<template>
|
|
<component
|
|
:class="[`btn p-xs size-${size}`, { secondary, number, hover }]"
|
|
:is="component"
|
|
:href="href"
|
|
:field="linkField"
|
|
>
|
|
<span class="text" v-if="linkField">
|
|
<span>{{ linkField.text }}</span>
|
|
<span>{{ linkField.text }}</span>
|
|
</span>
|
|
<span class="text" v-else-if="slots.default">
|
|
<span><slot /></span>
|
|
<span><slot /></span>
|
|
</span>
|
|
|
|
<span v-if="loading" class="loading">
|
|
<svg-util-spinner />
|
|
</span>
|
|
</component>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { useSlots, computed, resolveComponent } from 'vue'
|
|
import SvgUtilSpinner from '@/components/svg/util/Spinner.vue'
|
|
|
|
const props = defineProps({
|
|
// Will render ADiv
|
|
href: [Object, String],
|
|
// Will render PrismicLink
|
|
linkField: Object,
|
|
tag: String,
|
|
size: {
|
|
type: String,
|
|
default: () => 'small',
|
|
},
|
|
icon: {
|
|
type: String,
|
|
default: () => '',
|
|
},
|
|
secondary: {
|
|
type: Boolean,
|
|
default: () => false,
|
|
},
|
|
number: {
|
|
type: Boolean,
|
|
default: () => false,
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: () => false,
|
|
},
|
|
hover: {
|
|
type: Boolean,
|
|
default: () => true,
|
|
},
|
|
})
|
|
|
|
const slots = useSlots()
|
|
|
|
const component = computed(() => {
|
|
if (props.tag) return props.tag
|
|
if (props.href) return 'a'
|
|
if (props.linkField) return resolveComponent('prismic-link')
|
|
return 'button'
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: desktop-vw(5px) desktop-vw(20px);
|
|
border: 1px solid var(--theme-fg);
|
|
background: var(--theme-fg);
|
|
color: var(--theme-bg);
|
|
position: relative;
|
|
cursor: pointer;
|
|
transition:
|
|
color var(--td) var(--te),
|
|
background var(--td) var(--te);
|
|
@include text-flip(var(--td), var(--te));
|
|
|
|
@include mobile {
|
|
padding: mobile-vw(5px) mobile-vw(20px);
|
|
}
|
|
|
|
.text span {
|
|
display: block;
|
|
}
|
|
|
|
.loading {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: inherit;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
svg {
|
|
width: 1em;
|
|
height: auto;
|
|
}
|
|
}
|
|
|
|
.icon {
|
|
margin-left: desktop-vw(6px);
|
|
width: desktop-vw(12px);
|
|
height: auto;
|
|
|
|
@include mobile {
|
|
margin-left: mobile-vw(6px);
|
|
width: mobile-vw(12px);
|
|
}
|
|
}
|
|
|
|
&.size-large {
|
|
font-size: desktop-vw(28px);
|
|
padding: desktop-vw(8.7px) desktop-vw(34.7px);
|
|
|
|
@include mobile {
|
|
font-size: mobile-vw(28px);
|
|
padding: mobile-vw(8.7px) mobile-vw(34.7px);
|
|
}
|
|
}
|
|
|
|
&.secondary {
|
|
background: var(--theme-bg);
|
|
color: var(--theme-fg);
|
|
}
|
|
|
|
&.number {
|
|
padding: desktop-vw(5px) desktop-vw(10px);
|
|
|
|
@include mobile {
|
|
padding: mobile-vw(5px) mobile-vw(10px);
|
|
}
|
|
}
|
|
|
|
&.hover {
|
|
&:hover,
|
|
&.active,
|
|
&.router-link-active,
|
|
&.router-link-exact-active {
|
|
color: var(--theme-fg);
|
|
background: var(--theme-bg);
|
|
|
|
&.secondary {
|
|
background: var(--theme-fg);
|
|
color: var(--theme-bg);
|
|
}
|
|
}
|
|
}
|
|
|
|
&:not(.hover) {
|
|
cursor: default;
|
|
}
|
|
|
|
&:disabled,
|
|
&.disabled {
|
|
opacity: 0.16;
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
</style>
|