wf4/components/Header.vue
2024-06-21 09:30:11 +02:00

112 lines
4.3 KiB
Vue

<template>
<div ref="stickyWatch" />
<header ref="header" class="Header">
<div ref="headerWrapper" class="wrapper z-0">
<strong>
<svg aria-label="Logo" class="logo" height="40" viewBox="0 0 2500 2500" width="40">
<g id="Logo">
<g transform="matrix(2.00744,0,-5.91646e-31,2.00744,-1223.85,-1050.52)">
<path class="fussel"
d="M1232.34,1444.88L1356.88,1532.06C1356.88,1532.06 1405.5,1504.81 1444.06,1395.07C1464.03,1338.21 1476.18,1339.49 1506.32,1320.35C1579.8,1273.69 1638.29,1212.62 1630.86,1195.81C1560.6,1178.12 1512.77,1137.84 1506.32,1102.15L1618.41,946.736C1618.41,946.736 1514.23,877.412 1406.69,896.922C1407.7,845.817 1413.57,804.009 1481.42,759.931C1417.36,736.758 1260.23,740.351 1182.53,834.653C1115.13,783.067 1068.98,763.931 1008.18,759.931L1045.54,872.014C999.993,865.527 914.886,866.941 858.733,902.888C912.917,941.197 943.173,985.627 958.362,1033.91C883.905,1079.32 844.648,1134.09 808.918,1195.81C875.598,1205.68 938.224,1226.42 970.816,1282.99C1016.82,1362.83 1028.77,1456.11 1107.81,1532.06L1232.34,1444.88"/>
</g>
<g transform="matrix(1,0,0,1,-422.589,697.589)">
<path class="glasses" d="M1747.59,277.411C1695.36,294.131 1645.34,294.246 1597.59,277.411"/>
</g>
<path class="glasses"
d="M1175,975C1189.02,1037.51 1161.76,1216.53 1125,1300C1027.14,1307.22 909.088,1298.04 825,1275C798.072,1183.9 789.715,1050.66 825,950C935.158,934.697 1076.23,935.423 1175,975Z"/>
<g transform="matrix(-1,0,0,1,2500,2.20268e-13)">
<path class="glasses"
d="M1175,975C1189.02,1037.51 1161.76,1216.53 1125,1300C1027.14,1307.22 909.088,1298.04 825,1275C798.072,1183.9 789.715,1050.66 825,950C935.158,934.697 1076.23,935.423 1175,975Z"/>
</g>
</g>
</svg>
webfussel
</strong>
<input id="navToggle" v-model="isBurgerOpen" type="checkbox">
<label :aria-label="burgerLabel" for="navToggle">
<span/><span/><span/><span/>
</label>
<nav>
<ul class="main-nav">
<li v-for="({label, ...rest}) in nav" :key="label" @click="isBurgerOpen = false">
<NuxtLink v-bind="rest">{{ label }}</NuxtLink>
</li>
</ul>
<ul class="socials">
<li v-for="({icon, ...rest}) in socials" :key="rest.href" @click="isBurgerOpen = false">
<a v-bind="rest" target="_blank">
<img class="icon" :src="icon" :alt="rest['aria-label']" />
</a>
</li>
</ul>
</nav>
</div>
</header>
</template>
<script lang="ts" setup>
import KofiIcon from '/img/icons/kofi.svg'
import LinkedInIcon from 'iconoir/icons/regular/linkedin.svg'
import MastodonIcon from 'iconoir/icons/regular/mastodon.svg'
let observer: IntersectionObserver
const header = ref<HTMLElement | null>(null)
const headerWrapper = ref<HTMLElement | null>(null)
const stickyWatch = ref<HTMLElement | null>(null)
const isBurgerOpen = ref<boolean>(false)
const burgerOpenLabel = 'Burgermenü öffnen'
const burgerCloseLabel = 'Burgermenü schließen'
const burgerLabel = computed(() => isBurgerOpen.value ? burgerCloseLabel : burgerOpenLabel)
const nav = [
{
to: `/#intro`,
label: 'Über mich',
'aria-label': 'Link dieser Seite: Über mich'
}, {
to: `/#customers`,
label: 'Kunden',
'aria-label': 'Link dieser Seite: Kunden'
}, {
to: `/#services`,
label: 'Services',
'aria-label': 'Link dieser Seite: Services'
}
]
const socials = [
{
href: 'https://www.linkedin.com/in/webfussel/',
icon: LinkedInIcon,
'aria-label': 'Externer Link: LinkedIn Profil'
},
{
href: 'https://mastodontech.de/@webfussel',
icon: MastodonIcon,
rel: 'me',
'aria-label': 'Externer Link: Mastodon Profil'
},
{
href: 'https://ko-fi.com/webfussel',
icon: KofiIcon,
'aria-label': 'Externer Link: KoFi Profil'
},
]
onMounted(() => {
observer = new IntersectionObserver(([entry]) => {
const {isIntersecting} = entry
header.value?.classList.toggle('sticks', !isIntersecting)
headerWrapper.value?.classList.toggle('z-4', !isIntersecting)
headerWrapper.value?.classList.toggle('z-0', isIntersecting)
}, {
rootMargin: '3% 0px 0px 0px'
})
observer.observe(stickyWatch.value!)
})
onUnmounted(() => {
observer.disconnect()
})
</script>