Files
site-profile/src/layouts/BaseLayout.astro
Alex Lebens 954112e30e
All checks were successful
test-build / guarddog (push) Successful in 21s
renovate / renovate (push) Successful in 58s
test-build / build (push) Successful in 1m51s
feat: add fallback to run animations on switch
2026-03-15 23:50:04 -05:00

212 lines
4.9 KiB
Plaintext

---
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}
/>
<!-- Set Theme -->
<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>
<!-- Preline -->
<script
src="/vendor/preline/collapse2.1.0.min.js"
is:inline
/>
<!-- 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-hidden">
<!-- Sliding backgrounds -->
<div class="bg"/>
<div class="bg bg2"/>
<div class="bg bg3"/>
<!-- Fixed header -->
<Header />
<!-- Main body -->
<div id="reset-scroll" class="mask-container w-screen h-screen overflow-y-auto overflow-x-hidden">
<main>
<!-- Content -->
<div class="grow w-full max-w-(--breakpoint-2xl) px-4 sm:px-6 lg:px-8 py-20 mx-auto">
<slot />
</div>
<!-- Footer -->
<Footer />
</main>
</div>
</body>
</html>
<script>
import { initPhotoSwipe } from '@/scripts/photoswipe';
import { animateContent } from '@/scripts/animations';
const resetScroll = () => {
const scrollContainer = document.getElementById('reset-scroll');
if (scrollContainer) scrollContainer.scrollTop = 0;
};
resetScroll();
initPhotoSwipe();
animateContent();
const observer = new MutationObserver((mutations) => {
const hasNewNodes = mutations.some(
(mutation) => mutation.type === 'childList' && mutation.addedNodes.length > 0
);
if (hasNewNodes) {
animateContent();
if (typeof (window as any).HSStaticMethods !== 'undefined') {
(window as any).HSStaticMethods.autoInit();
}
}
});
const targetNode = document.getElementById('reset-scroll');
if (targetNode) {
observer.observe(targetNode, { childList: true, subtree: true });
}
document.addEventListener('swup:page:view', () => {
resetScroll();
initPhotoSwipe();
animateContent();
if (typeof (window as any).HSStaticMethods !== 'undefined') {
(window as any).HSStaticMethods.autoInit();
}
if (typeof (window as any).rybbit === 'function') {
(window as any).rybbit('trackPageview');
}
});
</script>
<style>
/* Fade away content below header when scrolling */
.mask-container {
-webkit-mask-image: linear-gradient(
to bottom,
transparent 0px,
transparent 90px,
black 140px,
black 100%
);
mask-image: linear-gradient(
to bottom,
transparent 0px,
transparent 90px,
black 140px,
black 100%
);
-webkit-mask-size: 100vw 100vh;
-webkit-mask-repeat: no-repeat;
}
/* Background that creates the "glimmer" effect */
.bg {
animation: slide 25s ease-in-out infinite alternate;
will-change: transform;
background-image: linear-gradient(-55deg, var(--bg-primary) 33.3%, var(--bg-secondary) 33.3%, var(--bg-secondary) 66.6%, var(--bg-tertiary) 66.6%);
filter: blur(40px);
top: 0;
bottom: 0;
left: -70%;
right: -70%;
opacity: .5;
position: fixed;
z-index: -1;
--bg-primary: #e5e5e5;
--bg-secondary: #dce3eb;
--bg-tertiary: #f4f6f8;
}
:global(.dark) .bg {
--bg-primary: #3b3836;
--bg-secondary: #332f2e;
--bg-tertiary: #44403c;
}
.bg2 {
animation-direction: alternate-reverse;
animation-duration: 30s;
}
.bg3 {
animation-duration: 20s;
}
@keyframes slide {
0% {
transform: translateX(-30%);
}
100% {
transform: translateX(30%);
}
}
</style>