feat(ui): implement link styles; use growing Spacers in Sidebar
This commit is contained in:
parent
302781d1fe
commit
1ca7f41ac2
|
@ -1,14 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { type RouterLinkProps, RouterLink } from 'vue-router'
|
||||
import { type ColorProps, propsToColor } from '~/composables/colors'
|
||||
import { type ColorProps, type VariantProps, propsToColor } from '~/composables/colors';
|
||||
|
||||
const { to, icon, inline, ...otherProps } = defineProps<RouterLinkProps
|
||||
& ColorProps
|
||||
const { to, icon, inline, round, ...otherProps } = defineProps<RouterLinkProps
|
||||
& {
|
||||
icon?: string;
|
||||
round?: boolean
|
||||
inline?: true
|
||||
}>()
|
||||
} & ColorProps & VariantProps>()
|
||||
|
||||
const isExternalLink = computed(() => {
|
||||
return typeof to === 'string' && to.startsWith('http')
|
||||
|
@ -17,8 +17,13 @@ const isExternalLink = computed(() => {
|
|||
|
||||
<template>
|
||||
<a v-if="isExternalLink"
|
||||
:v-bind="propsToColor(otherProps)"
|
||||
:class="[$style.link, $style.external, inline && $style.inline]"
|
||||
v-bind="propsToColor(otherProps)"
|
||||
:class="[
|
||||
'interactive',
|
||||
$style.link,
|
||||
$style.external,
|
||||
round && $style['is-round']
|
||||
]"
|
||||
:href="to?.toString()"
|
||||
target="_blank"
|
||||
>
|
||||
|
@ -27,8 +32,12 @@ const isExternalLink = computed(() => {
|
|||
</a>
|
||||
<RouterLink v-else
|
||||
:to="to"
|
||||
:v-bind="propsToColor(otherProps)"
|
||||
:class="[$style.link, inline && $style.inline]"
|
||||
v-bind="propsToColor(otherProps)"
|
||||
:class="[
|
||||
'interactive',
|
||||
$style.link,
|
||||
round && $style['is-round']
|
||||
]"
|
||||
>
|
||||
<i v-if="icon" :class="['bi', icon]" />
|
||||
<slot />
|
||||
|
@ -38,13 +47,8 @@ const isExternalLink = computed(() => {
|
|||
<style module lang="scss">
|
||||
.active { outline: 3px solid red; }
|
||||
.external { outline: 3px dotted blue; }
|
||||
.inline { display:inline-flex; }
|
||||
.button {
|
||||
background-color: var(--fw-bg-color);
|
||||
color: var(--fw-text-color);
|
||||
border: 1px solid var(--fw-bg-color);
|
||||
|
||||
display: flex;
|
||||
.link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
|
||||
|
@ -72,5 +76,9 @@ const isExternalLink = computed(() => {
|
|||
background-color:transparent;
|
||||
border-color:transparent;
|
||||
}
|
||||
|
||||
&.is-round {
|
||||
border-radius: 100vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
}
|
||||
|
||||
&:not(.is-raw) {
|
||||
color: var(--fw-link-color);
|
||||
color: var(--link-color);
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover,
|
||||
&.is-hovered {
|
||||
color: var(--fw-link-hover-color);
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,12 +118,12 @@
|
|||
background-color: var(--pressed-background-color, var(--active-background-color));
|
||||
border-color: var(--pressed-background-color, var(--active-background-color));
|
||||
}
|
||||
&:hover{
|
||||
&:hover {
|
||||
color:var(--hover-color);
|
||||
background-color:var(--hover-background-color);
|
||||
border-color: var(--hover-background-color);
|
||||
}
|
||||
&:active{
|
||||
&:is(:active, .active) {
|
||||
color:var(--active-color);
|
||||
background-color:var(--active-background-color);
|
||||
border-color: var(--active-background-color);
|
||||
|
@ -142,13 +142,13 @@
|
|||
border: 1px solid transparent;
|
||||
|
||||
&.interactive{
|
||||
&:hover{
|
||||
border: 1px solid var(--hover-background-color);
|
||||
&:hover {
|
||||
border-color: var(--hover-background-color);
|
||||
}
|
||||
&:active{
|
||||
border: 1px solid var(--active-background-color);
|
||||
&:is(:active, .active) {
|
||||
border-color: var(--active-background-color);
|
||||
&.router-link-exact-active {
|
||||
border: 1px solid var(--exact-active-background-color);
|
||||
border-color: var(--exact-active-background-color);
|
||||
}
|
||||
}
|
||||
&[disabled] {
|
||||
|
@ -164,12 +164,12 @@
|
|||
|
||||
&.interactive{
|
||||
&:hover{
|
||||
border: 1px solid var(--hover-background-color);
|
||||
border-color: var(--hover-background-color);
|
||||
}
|
||||
&:active{
|
||||
border: 1px solid var(--active-background-color);
|
||||
&:is(:active, .active) {
|
||||
border-color: var(--active-background-color);
|
||||
&.router-link-exact-active {
|
||||
background: 1px solid var(--exact-active-background-color);
|
||||
background-color: var(--exact-active-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +201,9 @@
|
|||
--background-color:var(--fw-beige-300);
|
||||
--border-color:var(--fw-beige-400);
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-400);
|
||||
--link-hover-color:var(--fw-blue-500);
|
||||
}
|
||||
|
||||
.secondary, button {
|
||||
|
@ -229,12 +232,18 @@
|
|||
--hover-background-color:var(--fw-gray-400);
|
||||
--active-background-color:var(--fw-gray-500);
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-600);
|
||||
--link-hover-color:var(--fw-blue-700);
|
||||
}
|
||||
|
||||
.primary {
|
||||
--color: var(--fw-blue-010);
|
||||
--background-color:var(--fw-blue-400);
|
||||
--border-color:var(--fw-blue-010);
|
||||
--border-color:var(--fw-blue-400);
|
||||
&> .primary {
|
||||
--border-color:var(--fw-blue-010);
|
||||
}
|
||||
|
||||
--hover-color: var(--fw-blue-010);
|
||||
--hover-background-color:var(--fw-blue-500);
|
||||
|
@ -254,6 +263,11 @@
|
|||
--hover-background-color:var(--fw-blue-600);
|
||||
--active-background-color:var(--fw-blue-700);
|
||||
}
|
||||
|
||||
&:not(:is(.ghost, .outline)) {
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
}
|
||||
|
||||
.destructive {
|
||||
|
@ -272,6 +286,11 @@
|
|||
--disabled-color:var(--fw-gray-500);
|
||||
--disabled-background-color:var(--fw-gray-100);
|
||||
--disabled-border-color:var(--fw-gray-100);
|
||||
|
||||
&:not(:is(.ghost, .outline)) {
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
}
|
||||
|
||||
.blue {
|
||||
|
@ -285,6 +304,9 @@
|
|||
--disabled-border-color: var(--fw-gray-400);
|
||||
--disabled-background-color: transparent;
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
|
||||
.red {
|
||||
|
@ -298,6 +320,9 @@
|
|||
--disabled-border-color: var(--fw-gray-400);
|
||||
--disabled-background-color: transparent;
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
|
||||
.purple {
|
||||
|
@ -311,6 +336,9 @@
|
|||
--disabled-border-color: var(--fw-gray-400);
|
||||
--disabled-background-color: transparent;
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
|
||||
.green {
|
||||
|
@ -324,6 +352,9 @@
|
|||
--disabled-border-color: var(--fw-gray-400);
|
||||
--disabled-background-color: transparent;
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
|
@ -337,6 +368,9 @@
|
|||
--disabled-border-color: var(--fw-gray-400);
|
||||
--disabled-background-color: transparent;
|
||||
}
|
||||
|
||||
--link-color:var(--fw-blue-010);
|
||||
--link-hover-color:white;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,6 +399,9 @@
|
|||
--background-color:var(--fw-gray-900);
|
||||
--border-color:var(--fw-gray-600);
|
||||
}
|
||||
|
||||
--link-color:var(--fw-gray-300);
|
||||
--link-hover-color:var(--fw-gray-400)
|
||||
}
|
||||
|
||||
.secondary, button {
|
||||
|
@ -396,6 +433,9 @@
|
|||
--active-color:var(--fw-gray-400);
|
||||
--active-background-color:var(--fw-gray-900);
|
||||
}
|
||||
|
||||
--link-color:var(--fw-gray-500);
|
||||
--link-hover-color:var(--fw-gray-600)
|
||||
}
|
||||
|
||||
.primary {
|
||||
|
|
|
@ -10,6 +10,8 @@ import Link from '~/components/ui/Link.vue'
|
|||
import ActorAvatar from '~/components/common/ActorAvatar.vue'
|
||||
import UserMenu from './UserMenu.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Layout from '~/components/ui/Layout.vue'
|
||||
import Spacer from '~/components/ui/layout/Spacer.vue'
|
||||
|
||||
const searchQuery = ref('')
|
||||
|
||||
|
@ -25,7 +27,7 @@ const uploads = useUploadsStore()
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<aside :class="[$style.sidebar, $style['sticky-content']]">
|
||||
<aside :class="[$style.sidebar, $style['sticky-content']]" v-bind="color('default solid raised')">
|
||||
<header :class="$style['header-wrapper']">
|
||||
<Link to="/" :class="$style['logo']">
|
||||
<img
|
||||
|
@ -64,16 +66,16 @@ const uploads = useUploadsStore()
|
|||
|
||||
</nav>
|
||||
</header>
|
||||
<div :class="$style.search">
|
||||
<Input
|
||||
v-model="searchQuery"
|
||||
type="search"
|
||||
icon="bi-search"
|
||||
:placeholder="t('components.audio.SearchBar.placeholder.search')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<nav :class="$style['button-list']">
|
||||
<Layout no-gap stack :class="$style['button-list']">
|
||||
<div :class="$style.search">
|
||||
<Input
|
||||
v-model="searchQuery"
|
||||
type="search"
|
||||
icon="bi-search"
|
||||
:placeholder="t('components.audio.SearchBar.placeholder.search')"
|
||||
/>
|
||||
</div>
|
||||
<nav style="display:contents;">
|
||||
<Link to="/library"
|
||||
ghost
|
||||
secondary
|
||||
|
@ -112,7 +114,7 @@ const uploads = useUploadsStore()
|
|||
>
|
||||
{{ t('components.Sidebar.link.radios') }}
|
||||
</Link>
|
||||
<Link to="/library/podcasts">
|
||||
<Link to="/library/podcasts"
|
||||
ghost
|
||||
secondary
|
||||
icon="bi-mic"
|
||||
|
@ -127,8 +129,10 @@ const uploads = useUploadsStore()
|
|||
{{ t('components.Sidebar.link.favorites') }}
|
||||
</Link>
|
||||
</nav>
|
||||
<Spacer grow />
|
||||
<h3>{{ t('components.Sidebar.link.channels') }}</h3>
|
||||
<nav :class="$style['button-list']">
|
||||
<Spacer grow />
|
||||
<nav>
|
||||
<Link inline to="/about">
|
||||
{{ t('components.Sidebar.link.about') }}
|
||||
</Link>
|
||||
|
@ -139,6 +143,7 @@ const uploads = useUploadsStore()
|
|||
Legal
|
||||
</Link>
|
||||
</nav>
|
||||
</Layout>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
|
@ -153,7 +158,6 @@ const uploads = useUploadsStore()
|
|||
height: 100%;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
background-color: var(--fw-gray-900);
|
||||
|
||||
&.sticky-content {
|
||||
position: sticky;
|
||||
|
@ -260,24 +264,11 @@ const uploads = useUploadsStore()
|
|||
> h3 {
|
||||
margin: 0;
|
||||
padding: 0 32px 8px;
|
||||
color: var(--fw-gray-700);
|
||||
@include light-theme {
|
||||
color: var(--fw-gray-700);
|
||||
}
|
||||
@include dark-theme {
|
||||
color: var(--fw-blue-100);
|
||||
}
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
nav.button-list {
|
||||
.button-list {
|
||||
padding: 0 16px 32px;
|
||||
|
||||
button {
|
||||
margin: 2px 0;
|
||||
justify-content: start;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import Link from '~/components/ui/Link.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
</script>
|
||||
|
||||
# Link
|
||||
|
@ -21,3 +22,57 @@ This component only adds some styles to a `<RouterLink>`.
|
|||
</Link>
|
||||
|
||||
Instead of a route, you can set the prop `to` to any web address starting with `http`.
|
||||
|
||||
## Colors and Variants
|
||||
|
||||
###### Solid:
|
||||
|
||||
<Link primary solid to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link secondary solid to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link destructive solid to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
###### Outline:
|
||||
|
||||
<Link primary outline to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link secondary outline to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link destructive outline to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
###### Ghost:
|
||||
|
||||
<Link primary ghost to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link secondary ghost to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Link destructive ghost to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
||||
<Button>
|
||||
I'm a button
|
||||
</Button>
|
||||
|
||||
## Shapes
|
||||
|
||||
<Link primary solid round to="/">
|
||||
Home
|
||||
</Link>
|
||||
|
|
Loading…
Reference in New Issue