2025-06-30 18:58:24 +02:00
|
|
|
<!--
|
|
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-->
|
2025-06-18 00:23:43 +02:00
|
|
|
<template>
|
|
|
|
<section class="tabs">
|
|
|
|
<nav>
|
|
|
|
<div
|
|
|
|
v-for="tab in tabs"
|
|
|
|
class="tab"
|
|
|
|
:class="{ active: tab.id === activeTab }"
|
|
|
|
>
|
|
|
|
<div class="flap">
|
|
|
|
<h2>
|
|
|
|
<NuxtLink
|
|
|
|
:to="{ ...route, query: { ...route.query, tab: tab.id }}"
|
|
|
|
>
|
|
|
|
{{ tab.title }}
|
|
|
|
</NuxtLink>
|
|
|
|
</h2>
|
|
|
|
</div>
|
|
|
|
<div class="spacer"></div>
|
|
|
|
</div>
|
|
|
|
</nav>
|
|
|
|
<slot :name="activeTab">No content for {{ activeTab }}</slot>
|
|
|
|
</section>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
const props = defineProps<{
|
|
|
|
tabs: { id: string, title: string }[],
|
|
|
|
default: string,
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
const activeTab = computed({
|
|
|
|
get: () => queryToString(route.query.tab ?? props.default),
|
|
|
|
set: (value: string | undefined) => navigateTo({
|
|
|
|
path: route.path,
|
|
|
|
query: {
|
|
|
|
...route.query,
|
|
|
|
tab: value,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
|
|
nav {
|
|
|
|
margin-block: 1rem 0.5rem;
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
row-gap: 0.5rem;
|
|
|
|
}
|
|
|
|
.tab {
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
}
|
|
|
|
.tab.active {
|
|
|
|
padding-block-start: 1px;
|
|
|
|
}
|
|
|
|
.tab:last-child {
|
|
|
|
flex-grow: 1;
|
|
|
|
}
|
|
|
|
.tab .spacer {
|
|
|
|
flex: 1 0 0.75rem;
|
|
|
|
}
|
|
|
|
.tab .flap,
|
|
|
|
.tab .spacer {
|
|
|
|
border-block-end: 1px solid color-mix(in srgb, CanvasText, Canvas 20%);
|
|
|
|
}
|
|
|
|
.tab.active .flap {
|
|
|
|
border-block-end: none;
|
|
|
|
}
|
|
|
|
.tab:not(.active) .flap h2 {
|
|
|
|
opacity: 0.7;
|
|
|
|
}
|
|
|
|
|
|
|
|
h2 {
|
|
|
|
border: 1px solid color-mix(in srgb, CanvasText, Canvas 20%);
|
|
|
|
border-start-start-radius: 0.4rem;
|
|
|
|
border-start-end-radius: 0.4rem;
|
|
|
|
border-block-end: none;
|
|
|
|
padding-inline: 0.5rem;
|
|
|
|
margin-block: 0;
|
|
|
|
font-size: 1.2rem;
|
|
|
|
padding-block: 0.3rem 0.1rem;
|
|
|
|
}
|
|
|
|
</style>
|