The name and tagline live in one place, shared/utils/site.ts, and feed the header, the footer, the home page and the title template.
95 lines
1.8 KiB
Vue
95 lines
1.8 KiB
Vue
<script setup lang="ts">
|
|
import type { Category } from '#shared/types/blog'
|
|
|
|
const { data: categories } = await useFetch<Category[]>('/api/categories', {
|
|
key: 'nav-categories',
|
|
default: () => [],
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="page">
|
|
<a class="skip-link" href="#main">Skip to content</a>
|
|
|
|
<header class="site-header">
|
|
<div class="container header-inner">
|
|
<NuxtLink to="/" class="brand">{{ SITE_NAME }}</NuxtLink>
|
|
<nav aria-label="Main navigation">
|
|
<ul>
|
|
<li><NuxtLink to="/blog">Articles</NuxtLink></li>
|
|
<li v-for="category in categories" :key="category.slug">
|
|
<NuxtLink :to="`/category/${category.slug}`">{{ category.name }}</NuxtLink>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="main" class="container site-main">
|
|
<slot />
|
|
</main>
|
|
|
|
<footer class="site-footer">
|
|
<div class="container">
|
|
<p class="muted">© {{ new Date().getFullYear() }} {{ SITE_NAME }}</p>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.site-header {
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.header-inner {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 1rem 2rem;
|
|
padding-block: 1rem;
|
|
}
|
|
|
|
.brand {
|
|
font-size: 1.25rem;
|
|
font-weight: 700;
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
nav ul {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 1rem;
|
|
padding: 0;
|
|
margin: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
nav a {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
nav a:hover,
|
|
nav a.router-link-active {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.site-main {
|
|
flex: 1;
|
|
padding-block: 2.5rem 4rem;
|
|
}
|
|
|
|
.site-footer {
|
|
padding-block: 1.5rem;
|
|
border-top: 1px solid var(--color-border);
|
|
}
|
|
</style>
|