From 996d367a3fe0c49381dfca8dd5cf5431aedd1f19 Mon Sep 17 00:00:00 2001
From: Fuwn <contact@fuwn.me>
Date: Thu, 18 Apr 2024 00:19:07 -0700
Subject: feat(layout): semi-sticky header

---
 src/routes/+layout.svelte | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

(limited to 'src/routes/+layout.svelte')

diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 9bd00c72..0b1e81dc 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -2,7 +2,7 @@
 	import type { SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
 	import { env } from '$env/dynamic/public';
 	import { userIdentity as getUserIdentity } from '$lib/Data/AniList/identity';
-	import { onMount } from 'svelte';
+	import { onDestroy, onMount } from 'svelte';
 	import userIdentity from '$stores/identity';
 	import settings from '$stores/settings';
 	import { browser } from '$app/environment';
@@ -32,6 +32,9 @@
 
 	export let data;
 
+	let isHeaderVisible = true;
+	let previousScrollPosition = 0;
+
 	addMessages('en', english as unknown as LocaleDictionary);
 	addMessages('ja', japanese as unknown as LocaleDictionary);
 	init({ fallbackLocale: 'en', initialLocale: $settings.displayLanguage });
@@ -55,6 +58,14 @@
 		? 200
 		: -200;
 
+	const handleScroll = () => {
+		const currentScrollPosition = window.scrollY;
+
+		isHeaderVisible =
+			currentScrollPosition <= 100 || currentScrollPosition < previousScrollPosition;
+		previousScrollPosition = currentScrollPosition;
+	};
+
 	onMount(async () => {
 		if (browser) {
 			if (localStorage.getItem('redirect')) {
@@ -63,6 +74,8 @@
 				localStorage.removeItem('redirect');
 			}
 
+			window.addEventListener('scroll', handleScroll);
+
 			if (localStorage.getItem('commit') !== data.commit) {
 				localStorage.removeItem('identity');
 				localStorage.removeItem('anime');
@@ -94,6 +107,8 @@
 			});
 	});
 
+	onDestroy(() => window.removeEventListener('scroll', handleScroll));
+
 	$: {
 		if ((data.url === '/' || data.url === '/completed' || data.url === '/schedule') && !$subsPlease)
 			fetch(root(`/api/subsplease?tz=${Intl.DateTimeFormat().resolvedOptions().timeZone}`))
@@ -122,7 +137,7 @@
 <Announcement />
 
 <div class="container">
-	<div class="card card-centered header">
+	<div class="card card-centered header" class:header-hidden={!isHeaderVisible}>
 		<div>
 			<a href={root('/')} class="header-item">{$locale().navigation.home}</a><a
 				href={root('/completed')}
@@ -224,6 +239,13 @@
 		font-weight: 600;
 		padding: 0.8rem 0.4rem;
 		z-index: 4;
+		position: sticky;
+		top: 1.25rem;
+		transition: transform 0.3s ease;
+	}
+
+	.header-hidden {
+		transform: translateY(-150%);
 	}
 
 	:global(html.light-theme) {
-- 
cgit v1.2.3

