add astro native SPA transition
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Theme transition script
|
// Theme transition script
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const themeToggle = document.querySelector('[data-theme-toggle]');
|
const themeToggle = document.querySelector('[data-theme-toggle]');
|
||||||
const overlay = document.getElementById('theme-transition-overlay');
|
const overlay = document.getElementById('theme-transition-overlay');
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ const socialLinks = [
|
|||||||
|
|
||||||
<footer
|
<footer
|
||||||
class="theme-transition-all relative mt-20 overflow-hidden border-t border-zinc-100 dark:border-zinc-800"
|
class="theme-transition-all relative mt-20 overflow-hidden border-t border-zinc-100 dark:border-zinc-800"
|
||||||
|
transition:animate="none"
|
||||||
>
|
>
|
||||||
<div class="pointer-events-none absolute inset-0 overflow-hidden">
|
<div class="pointer-events-none absolute inset-0 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
|
@@ -20,6 +20,7 @@ const currentPath = pathname.slice(1);
|
|||||||
|
|
||||||
<header
|
<header
|
||||||
class="fixed top-0 right-0 left-0 z-40 border-b border-zinc-100 bg-white py-4 dark:border-zinc-800 dark:bg-zinc-900"
|
class="fixed top-0 right-0 left-0 z-40 border-b border-zinc-100 bg-white py-4 dark:border-zinc-800 dark:bg-zinc-900"
|
||||||
|
transition:animate="none"
|
||||||
>
|
>
|
||||||
<div class="mx-auto flex max-w-3xl items-center justify-between px-4">
|
<div class="mx-auto flex max-w-3xl items-center justify-between px-4">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
@@ -121,7 +122,7 @@ const currentPath = pathname.slice(1);
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Mobile menu toggle with animations
|
// Mobile menu toggle with animations
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||||
const closeMenuButton = document.getElementById('close-menu-button');
|
const closeMenuButton = document.getElementById('close-menu-button');
|
||||||
const mobileMenu = document.getElementById('mobile-menu');
|
const mobileMenu = document.getElementById('mobile-menu');
|
||||||
|
@@ -47,6 +47,20 @@
|
|||||||
></span>
|
></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
// Use a function to persist theme when using SPA transitions
|
||||||
|
// https://docs.astro.build/en/guides/view-transitions/#script-re-execution
|
||||||
|
function applyTheme() {
|
||||||
|
localStorage.theme === 'dark'
|
||||||
|
? document.documentElement.classList.add('dark')
|
||||||
|
: document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('astro:after-swap', applyTheme);
|
||||||
|
|
||||||
|
applyTheme();
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Use a function to handle theme toggle to ensure it can be called from anywhere
|
// Use a function to handle theme toggle to ensure it can be called from anywhere
|
||||||
function setupThemeToggle() {
|
function setupThemeToggle() {
|
||||||
@@ -171,7 +185,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run setup on load
|
// Run setup on load
|
||||||
document.addEventListener('DOMContentLoaded', setupThemeToggle);
|
document.addEventListener('astro:page-load', setupThemeToggle);
|
||||||
|
|
||||||
// Also run on page visibility change to ensure theme is consistent
|
// Also run on page visibility change to ensure theme is consistent
|
||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import { ClientRouter } from 'astro:transitions';
|
||||||
|
|
||||||
import Navigation from '../components/Navigation.astro';
|
import Navigation from '../components/Navigation.astro';
|
||||||
import Footer from '../components/Footer.astro';
|
import Footer from '../components/Footer.astro';
|
||||||
import Background from '../components/Background.astro';
|
import Background from '../components/Background.astro';
|
||||||
@@ -47,11 +49,11 @@ const { title, description } = Astro.props;
|
|||||||
}
|
}
|
||||||
window.localStorage.setItem('theme', theme);
|
window.localStorage.setItem('theme', theme);
|
||||||
</script>
|
</script>
|
||||||
|
<ClientRouter />
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
class="flex min-h-screen flex-col bg-white text-zinc-900 dark:bg-zinc-900 dark:text-zinc-100"
|
class="flex min-h-screen flex-col bg-white text-zinc-900 dark:bg-zinc-900 dark:text-zinc-100"
|
||||||
>
|
>
|
||||||
|
|
||||||
<Background />
|
<Background />
|
||||||
|
|
||||||
<div class="mx-auto w-full max-w-3xl grow px-4 sm:px-6">
|
<div class="mx-auto w-full max-w-3xl grow px-4 sm:px-6">
|
||||||
|
@@ -5,6 +5,7 @@ import Layout from '../layouts/Layout.astro';
|
|||||||
<Layout title="404 - Page Not Found">
|
<Layout title="404 - Page Not Found">
|
||||||
<div
|
<div
|
||||||
class="relative flex min-h-[80vh] flex-col items-center justify-center overflow-hidden px-4 py-20 text-center"
|
class="relative flex min-h-[80vh] flex-col items-center justify-center overflow-hidden px-4 py-20 text-center"
|
||||||
|
transition:animate="slide"
|
||||||
>
|
>
|
||||||
<!-- Animated background elements -->
|
<!-- Animated background elements -->
|
||||||
<div class="absolute inset-0 overflow-hidden">
|
<div class="absolute inset-0 overflow-hidden">
|
||||||
|
@@ -16,7 +16,10 @@ const skills = await directus.request(
|
|||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="About Me" description={global.description}>
|
<BaseLayout title="About Me" description={global.description}>
|
||||||
<div class="theme-transition-all mx-auto max-w-6xl px-4 py-8 sm:px-6 sm:py-12 md:py-16">
|
<div
|
||||||
|
class="theme-transition-all mx-auto max-w-6xl px-4 py-8 sm:px-6 sm:py-12 md:py-16"
|
||||||
|
transition:animate="slide"
|
||||||
|
>
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<div class="relative mb-12 sm:mb-16 md:mb-20">
|
<div class="relative mb-12 sm:mb-16 md:mb-20">
|
||||||
<!-- Decorative elements -->
|
<!-- Decorative elements -->
|
||||||
@@ -366,7 +369,7 @@ const skills = await directus.request(
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const sliderTrack = document.querySelector('.slider-track');
|
const sliderTrack = document.querySelector('.slider-track');
|
||||||
|
|
||||||
// Create seamless infinite scrolling effect
|
// Create seamless infinite scrolling effect
|
||||||
|
@@ -196,9 +196,6 @@ const { post, nextPost, prevPost } = Astro.props;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize on first load
|
|
||||||
document.addEventListener('DOMContentLoaded', initializeBlogPost);
|
|
||||||
|
|
||||||
// Re-initialize when content changes via Astro's view transitions
|
// Re-initialize when content changes via Astro's view transitions
|
||||||
document.addEventListener('astro:page-load', initializeBlogPost);
|
document.addEventListener('astro:page-load', initializeBlogPost);
|
||||||
</script>
|
</script>
|
||||||
|
@@ -25,7 +25,7 @@ const years = Object.keys(postsByYear).sort((a, b) => b - a);
|
|||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Blog">
|
<BaseLayout title="Blog">
|
||||||
<div class="mx-auto w-full max-w-6xl px-4 py-10 sm:px-6 sm:py-16">
|
<div class="mx-auto w-full max-w-6xl px-4 py-10 sm:px-6 sm:py-16" transition:animate="slide">
|
||||||
<div class="relative mb-12 sm:mb-20">
|
<div class="relative mb-12 sm:mb-20">
|
||||||
<div
|
<div
|
||||||
class="animate-blob absolute -top-10 -left-10 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl sm:-top-20 sm:-left-20 sm:h-72 sm:w-72 dark:bg-zinc-800/30"
|
class="animate-blob absolute -top-10 -left-10 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl sm:-top-20 sm:-left-20 sm:h-72 sm:w-72 dark:bg-zinc-800/30"
|
||||||
@@ -307,7 +307,7 @@ const years = Object.keys(postsByYear).sort((a, b) => b - a);
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const backToTopButton = document.getElementById('back-to-top');
|
const backToTopButton = document.getElementById('back-to-top');
|
||||||
|
|
||||||
if (backToTopButton) {
|
if (backToTopButton) {
|
||||||
|
@@ -23,7 +23,10 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
|
|||||||
|
|
||||||
<Layout title=`Home | ${global.name}`>
|
<Layout title=`Home | ${global.name}`>
|
||||||
<!-- Hero Section with mobile responsiveness -->
|
<!-- Hero Section with mobile responsiveness -->
|
||||||
<section class="theme-transition-all px-4 py-10 sm:px-6 sm:py-16 md:py-20">
|
<section
|
||||||
|
class="theme-transition-all px-4 py-10 sm:px-6 sm:py-16 md:py-20"
|
||||||
|
transition:animate="slide"
|
||||||
|
>
|
||||||
<div class="relative mx-auto max-w-2xl">
|
<div class="relative mx-auto max-w-2xl">
|
||||||
<!-- Adjusted blob positions and sizes for mobile appearance -->
|
<!-- Adjusted blob positions and sizes for mobile appearance -->
|
||||||
<div
|
<div
|
||||||
@@ -278,7 +281,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Add hover effect for cards on touch devices
|
// Add hover effect for cards on touch devices
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
||||||
|
|
||||||
if (isTouchDevice) {
|
if (isTouchDevice) {
|
||||||
|
@@ -30,7 +30,10 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
|
|||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Explore Tags">
|
<BaseLayout title="Explore Tags">
|
||||||
<div class="theme-transition-all mx-auto w-full px-3 py-6 sm:px-6 sm:py-12 md:py-16">
|
<div
|
||||||
|
class="theme-transition-all mx-auto w-full px-3 py-6 sm:px-6 sm:py-12 md:py-16"
|
||||||
|
transition:animate="slide"
|
||||||
|
>
|
||||||
<div class="theme-transition-element relative mb-8 text-center sm:mb-12 md:mb-16">
|
<div class="theme-transition-element relative mb-8 text-center sm:mb-12 md:mb-16">
|
||||||
<div
|
<div
|
||||||
class="animate-blob theme-transition-bg absolute -top-16 -left-16 h-36 w-36 rounded-full bg-zinc-100 opacity-50 blur-3xl sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/50"
|
class="animate-blob theme-transition-bg absolute -top-16 -left-16 h-36 w-36 rounded-full bg-zinc-100 opacity-50 blur-3xl sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/50"
|
||||||
@@ -145,7 +148,7 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
|
|||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
const fixViewportWidth = () => {
|
const fixViewportWidth = () => {
|
||||||
// Force the viewport to be exactly the width of the device
|
// Force the viewport to be exactly the width of the device
|
||||||
const viewport = document.querySelector('meta[name="viewport"]');
|
const viewport = document.querySelector('meta[name="viewport"]');
|
||||||
|
Reference in New Issue
Block a user