The rendering of the tabs would not include the spacer in Firefox for if the width was not set for some reason.
90 lines
1.6 KiB
Vue
90 lines
1.6 KiB
Vue
<!--
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
-->
|
|
<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;
|
|
}
|
|
.tab.active {
|
|
padding-block-start: 1px;
|
|
}
|
|
.tab:last-child {
|
|
flex-grow: 1;
|
|
}
|
|
.tab .spacer {
|
|
flex: 1 0 0.75rem;
|
|
width: 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>
|