175 lines
4.0 KiB
Plaintext
175 lines
4.0 KiB
Plaintext
---
|
|
import { ClientRouter } from 'astro:transitions';
|
|
import { readSingleton } from '@directus/sdk';
|
|
|
|
import BaseHead from '@components/BaseHead.astro';
|
|
import Footer from '@components/Footer.astro';
|
|
import Header from '@components/Header.astro';
|
|
import directus from '@lib/directus';
|
|
|
|
import '@styles/global.css';
|
|
|
|
interface Props {
|
|
title?: string;
|
|
description?: string;
|
|
ogImage?: any;
|
|
lang?: string;
|
|
structuredData?: object;
|
|
}
|
|
|
|
const { title, description = 'Alex Lebens', ogImage, lang = 'en', structuredData } = Astro.props;
|
|
|
|
const global = await directus.request(readSingleton('site_global'));
|
|
|
|
const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|
---
|
|
|
|
<html lang={lang}>
|
|
<head>
|
|
<title>
|
|
{normalizeTitle}
|
|
</title>
|
|
|
|
<BaseHead
|
|
title={normalizeTitle}
|
|
description={description}
|
|
ogImage={ogImage}
|
|
ogTitle={title === '' ? global.name : title}
|
|
ogDescription={description}
|
|
structuredData={structuredData}
|
|
/>
|
|
|
|
<ClientRouter fallback="swap" />
|
|
|
|
<script is:inline>
|
|
const theme = (() => {
|
|
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
|
|
return localStorage.getItem('theme');
|
|
}
|
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
return 'dark';
|
|
}
|
|
return 'light';
|
|
})();
|
|
|
|
if (theme === 'light') {
|
|
document.documentElement.classList.remove('dark');
|
|
} else {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
window.localStorage.setItem('theme', theme);
|
|
</script>
|
|
|
|
<!-- Rybbit Tracking Snippet -->
|
|
<script
|
|
src="https://rybbit.alexlebens.dev/api/script.js"
|
|
data-site-id={global.rybbit_site_id}
|
|
defer
|
|
/>
|
|
</head>
|
|
|
|
<body class="bg-background selection:bg-yellow-400 m-0 p-0 overflow-x-hidden">
|
|
|
|
<!-- Sliding backgrounds -->
|
|
<div class="bg"/>
|
|
<div class="bg bg2"/>
|
|
<div class="bg bg3"/>
|
|
|
|
<!-- Layout -->
|
|
<div class="grow w-full max-w-(--breakpoint-2xl) px-4 sm:px-6 lg:px-8 py-20 mx-auto">
|
|
|
|
<Header />
|
|
|
|
<main class="has-js scroll-fade-container min-h-screen">
|
|
<slot />
|
|
</main>
|
|
|
|
</div>
|
|
|
|
<Footer />
|
|
|
|
</body>
|
|
</html>
|
|
|
|
<script>
|
|
document.addEventListener('astro:page-load', () => {
|
|
const onScroll = () => {
|
|
document.documentElement.style.setProperty('--scroll-offset', `${window.scrollY}px`);
|
|
document.documentElement.classList.add('has-js');
|
|
};
|
|
|
|
window.removeEventListener('scroll', onScroll);
|
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
|
|
onScroll();
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
/* Fade away content below header when scrolling */
|
|
.has-js .scroll-fade-container {
|
|
-webkit-mask-image: linear-gradient(
|
|
to bottom,
|
|
transparent 0px,
|
|
transparent 16px,
|
|
black 80px,
|
|
black 100%
|
|
);
|
|
|
|
mask-image: linear-gradient(
|
|
to bottom,
|
|
transparent 0px,
|
|
transparent 16px,
|
|
black 80px,
|
|
black 100%
|
|
);
|
|
|
|
-webkit-mask-size: 100vw 100vh;
|
|
-webkit-mask-repeat: no-repeat;
|
|
|
|
-webkit-mask-position-y: var(--scroll-offset);
|
|
mask-position-y: var(--scroll-offset);
|
|
}
|
|
|
|
/* Background that creates the "glimmer" effect */
|
|
.bg {
|
|
animation: slide 20s ease-in-out infinite alternate;
|
|
background-image: linear-gradient(-60deg, var(--bg-primary) 33.3%, var(--bg-secondary) 33.3%, var(--bg-secondary) 66.6%, var(--bg-tertiary) 66.6%);
|
|
filter: blur(80px);
|
|
top: 0;
|
|
bottom: 0;
|
|
left: -50%;
|
|
right: -50%;
|
|
opacity: .5;
|
|
position: fixed;
|
|
z-index: -1;
|
|
--bg-primary: #e5e5e5;
|
|
--bg-secondary: #d9d9d9;
|
|
--bg-tertiary: #ededed;
|
|
}
|
|
|
|
:global(.dark) .bg {
|
|
--bg-primary: #292524;
|
|
--bg-secondary: #44403c;
|
|
--bg-tertiary: #57534e;
|
|
}
|
|
|
|
.bg2 {
|
|
animation-direction: alternate-reverse;
|
|
animation-duration: 30s;
|
|
}
|
|
|
|
.bg3 {
|
|
animation-duration: 25s;
|
|
}
|
|
|
|
@keyframes slide {
|
|
0% {
|
|
transform:translateX(-25%);
|
|
}
|
|
100% {
|
|
transform:translateX(25%);
|
|
}
|
|
}
|
|
</style>
|