feat(ui): [WIP] new `Link` component, use for sidebar links
This commit is contained in:
parent
8ea49dd251
commit
ad9e3dd4b0
|
@ -0,0 +1,182 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { type RouterLinkProps, RouterLink } from 'vue-router';
|
||||
const { to, icon } = defineProps<RouterLinkProps & {
|
||||
icon?: string;
|
||||
variant?: 'solid' | 'outline' | 'ghost'
|
||||
}>()
|
||||
|
||||
const isExternalLink = computed(() => {
|
||||
return typeof to === 'string' && to.startsWith('http')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a v-if="isExternalLink" :class="$style.external" :href="to?.toString()" target="_blank">
|
||||
<slot />
|
||||
</a>
|
||||
<RouterLink v-if="to && !isExternalLink" :to="to" v-slot="{ isActive, href, navigate }">
|
||||
<a :href="href" @click="navigate" :class="{ [$style.active]: isActive }">
|
||||
<slot />
|
||||
<i v-if="icon" :class="['bi', icon]" />
|
||||
</a>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<style module lang="scss">
|
||||
.active { background:red; }
|
||||
.external { outline: 3px dotted blue; }
|
||||
a {
|
||||
background-color: var(--fw-bg-color);
|
||||
color: var(--fw-text-color);
|
||||
border: 1px solid var(--fw-bg-color);
|
||||
|
||||
position: relative;
|
||||
display: inline-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: all .2s ease;
|
||||
|
||||
@include light-theme {
|
||||
&.is-secondary.is-outline {
|
||||
--fw-bg-color: var(--fw-gray-600);
|
||||
--fw-text-color: var(--fw-gray-700);
|
||||
|
||||
&[disabled] {
|
||||
--fw-bg-color: var(--fw-gray-600) !important;
|
||||
--fw-text-color: var(--fw-gray-600) !important;
|
||||
}
|
||||
|
||||
&.is-hovered,
|
||||
&:hover {
|
||||
--fw-bg-color: var(--fw-gray-700) !important;
|
||||
--fw-text-color: var(--fw-gray-800) !important;
|
||||
}
|
||||
|
||||
&.is-active,
|
||||
&:active {
|
||||
--fw-text-color: var(--fw-red-010) !important;
|
||||
border: 1px solid var(--fw-gray-600) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-outline {
|
||||
&:not(:active):not(.is-active) {
|
||||
background-color: transparent !important;
|
||||
--fw-text-color:--fw-gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-ghost {
|
||||
&:not(:active):not(.is-active):not(:hover):not(.is-hovered) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent !important;
|
||||
--fw-text-color:--fw-gray-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include dark-theme {
|
||||
&.is-secondary.is-outline {
|
||||
--fw-bg-color: var(--fw-gray-500);
|
||||
--fw-text-color: var(--fw-gray-400);
|
||||
|
||||
&[disabled] {
|
||||
--fw-bg-color: var(--fw-gray-600) !important;
|
||||
--fw-text-color: var(--fw-gray-700) !important;
|
||||
}
|
||||
|
||||
&.is-hovered,
|
||||
&:hover {
|
||||
--fw-bg-color: var(--fw-gray-600) !important;
|
||||
--fw-text-color: var(--fw-gray-500) !important;
|
||||
}
|
||||
|
||||
&.is-active,
|
||||
&:active {
|
||||
--fw-text-color: var(--fw-red-010) !important;
|
||||
--fw-bg-color: var(--fw-gray-700) !important;
|
||||
border: 1px solid var(--fw-gray-600) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-outline {
|
||||
&:not(:active):not(.is-active) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-ghost {
|
||||
&:not(:active):not(.is-active):not(:hover):not(.is-hovered) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.is-aligned-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.is-aligned-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
&.is-aligned-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
&.is-shadow {
|
||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
&:not(.icon-only):not(.is-auto) {
|
||||
min-width: 8.5rem;
|
||||
}
|
||||
|
||||
&.is-full {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.is-round {
|
||||
border-radius: 100vh;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
font-weight: normal;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.is-loading {
|
||||
@extend .is-active;
|
||||
|
||||
> span {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
i.bi {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
i.bi + span:not(:empty) {
|
||||
margin-left: 1ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -7,6 +7,7 @@ import { useStore } from '~/store'
|
|||
import Button from '~/components/ui/Button.vue'
|
||||
import Input from '~/components/ui/Input.vue'
|
||||
import Pill from '~/components/ui/Pill.vue'
|
||||
import Link from '~/components/ui/Link.vue'
|
||||
|
||||
const searchQuery = ref('')
|
||||
|
||||
|
@ -99,13 +100,13 @@ const uploads = useUploadsStore()
|
|||
|
||||
<h3>Explore</h3>
|
||||
<nav class="button-list">
|
||||
<Button
|
||||
<Link to="/content"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
icon="bi-compass"
|
||||
>
|
||||
All Funkwhale
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
|
|
|
@ -39,6 +39,9 @@ export default defineConfig({
|
|||
{ text: 'Tabs', link: '/components/ui/tabs' },
|
||||
],
|
||||
},
|
||||
{ text: 'Link',
|
||||
link: 'components/ui/link'
|
||||
},
|
||||
{
|
||||
text: 'Form',
|
||||
items: [
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import Link from '~/components/ui/Link.vue'
|
||||
</script>
|
||||
|
||||
# Link
|
||||
|
||||
Will render an `<a href...>` element.
|
||||
|
||||
This component only adds some styles to a `<RouterLink>`.
|
||||
|
||||
```vue-html
|
||||
|
||||
<Link to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
```
|
||||
|
||||
<Link to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
Instead of a route, you can set the prop `to` to any web address starting with `http`.
|
Loading…
Reference in New Issue