76 lines
1.8 KiB
Vue
76 lines
1.8 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { type RouterLinkProps, RouterLink } from 'vue-router';
|
|
import { type ColorProps, propsToColor } from '~/composables/colors';
|
|
const { to, icon, inline, ...otherProps } = defineProps<RouterLinkProps
|
|
& ColorProps
|
|
& {
|
|
icon?: string;
|
|
inline?: true
|
|
}>()
|
|
|
|
const isExternalLink = computed(() => {
|
|
return typeof to === 'string' && to.startsWith('http')
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<a v-if="isExternalLink"
|
|
:v-bind="propsToColor(otherProps)"
|
|
:class="[$style.link, $style.external, inline && $style.inline]"
|
|
:href="to?.toString()"
|
|
target="_blank"
|
|
>
|
|
<i v-if="icon" :class="['bi', icon]" />
|
|
<slot />
|
|
</a>
|
|
<RouterLink v-else
|
|
:to="to"
|
|
:v-bind="propsToColor(otherProps)"
|
|
:class="[$style.link, inline && $style.inline]"
|
|
>
|
|
<i v-if="icon" :class="['bi', icon]" />
|
|
<slot />
|
|
</RouterLink>
|
|
</template>
|
|
|
|
<style module lang="scss">
|
|
.active { outline: 3px solid red; }
|
|
.external { outline: 3px dotted blue; }
|
|
.inline { display:inline-flex; }
|
|
.link {
|
|
background-color: var(--fw-bg-color);
|
|
color: var(--fw-text-color);
|
|
border: 1px solid var(--fw-bg-color);
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
white-space: nowrap;
|
|
|
|
font-family: $font-main;
|
|
font-weight: 900;
|
|
font-size: 0.875em;
|
|
|
|
line-height: 1em;
|
|
|
|
padding: 0.642857142857em;
|
|
|
|
border-radius: var(--fw-border-radius);
|
|
margin: 0 0.5ch;
|
|
|
|
transform: translateX(var(--fw-translate-x)) translateY(var(--fw-translate-y)) scale(var(--fw-scale));
|
|
transition:background-color .3s, border-color .2s;
|
|
|
|
i {
|
|
margin-right:1ch;
|
|
font-size:1.4em;
|
|
}
|
|
|
|
&:not(:hover):not(:global(.active)) {
|
|
text-decoration:none;
|
|
background-color:transparent;
|
|
border-color:transparent;
|
|
}
|
|
}
|
|
</style>
|