(POC) Changed Snap Scroll system to button navigation system

This commit is contained in:
Harding 2025-02-26 17:43:58 -05:00
parent e46137d2df
commit 55baf1b3e3
11 changed files with 229 additions and 177 deletions

View File

@ -3,7 +3,7 @@
@import 'tailwindcss/utilities'; @import 'tailwindcss/utilities';
* { * {
overflow-x: hidden; overflow: hidden !important;
} }
*:not(a), *:not(a),
@ -11,24 +11,3 @@
*:not(input) { *:not(input) {
user-select: none; user-select: none;
} }
/* @font-face {
font-family: 'Nunita';
src: url('$lib/assets/fonts/Nunito-VariableFont_wght.ttf');
}
@font-face {
font-family: 'Roboto';
src: url('$lib/assets/fonts/Roboto-VariableFont_wdth,wght.ttf');
}
:root {
--theme-font-family-base: 'Roboto', serif;
--theme-font-family-heading: 'Roboto', serif;
}
:root body[data-theme='modern'],
:root body[data-theme='gold-nouveau'] {
--theme-font-family-base: 'Nunita', serif;
--theme-font-family-heading: 'Nunita', serif;
} */

View File

@ -1,9 +1,13 @@
<script> <script>
import MaterialSymbolsPerson from '~icons/material-symbols/person'; import MaterialSymbolsPerson from '~icons/material-symbols/person';
import MaterialSymbolsMail from '~icons/material-symbols/mail'; import MaterialSymbolsMail from '~icons/material-symbols/mail';
import Right from './navigation-items/Right.svelte';
export let scrollInDirection;
</script> </script>
<div class="w-screen h-screen flex justify-center items-center"> <div id="contact" class="w-screen h-screen flex justify-between items-center">
<div class="spacer"></div>
<form action="?/contact" class="w-full min-h-full dark:bg-surface-900 bg-surface-200 lg:w-1/2 lg:min-h-max p-8 rounded-md pr-12 lg:pr-8"> <form action="?/contact" class="w-full min-h-full dark:bg-surface-900 bg-surface-200 lg:w-1/2 lg:min-h-max p-8 rounded-md pr-12 lg:pr-8">
<h1 class="h1 font-bold ps-4 pb-4">Contact Us</h1> <h1 class="h1 font-bold ps-4 pb-4">Contact Us</h1>
<hr class="opacity-25" /> <hr class="opacity-25" />
@ -34,4 +38,7 @@
<button type="submit" class="btn variant-filled-primary">Submit</button> <button type="submit" class="btn variant-filled-primary">Submit</button>
</div> </div>
</form> </form>
<div>
<Right {scrollInDirection} />
</div>
</div> </div>

View File

@ -1,8 +1,13 @@
<script> <script>
import Hero from "$lib/components/Hero.svelte"; import Hero from "$lib/components/Hero.svelte";
import ArrowDown from "~icons/material-symbols/keyboard-double-arrow-down-rounded";
import { crossfade, fade, fly } from "svelte/transition"; import { crossfade, fade, fly } from "svelte/transition";
import { onMount } from "svelte"; import { onMount } from "svelte";
import Up from "$lib/components/navigation-items/Up.svelte";
import Left from "$lib/components/navigation-items/Left.svelte";
import Right from "$lib/components/navigation-items/Right.svelte";
import Down from "$lib/components/navigation-items/Down.svelte";
export let scrollInDirection;
let isAtTop = true; let isAtTop = true;
@ -15,30 +20,26 @@
}); });
</script> </script>
<!-- Add these classes to your root container (likely in app.html or layout.svelte) --> <header id="header" class="h-screen grid p-4 hero">
<div class="spacer"></div>
<Up {scrollInDirection} />
<div class="spacer"></div>
<Left {scrollInDirection} />
<Hero></Hero>
<Right {scrollInDirection} />
<div class="spacer"></div>
<Down {scrollInDirection} />
</header>
<style> <style>
:global(html) { :global(html) {
scroll-snap-type: y mandatory; scroll-snap-type: y mandatory;
scroll-behavior: smooth; scroll-behavior: smooth;
} }
</style>
<!-- Add scroll-snap-align to your sections --> #header {
<header class="fancy-background align-center flex h-screen flex-col justify-between p-4 hero scroll-snap-start"> grid-template-areas: '. . .'
<div class=""></div> '. . .'
<Hero></Hero> '. . .';
<div }
class="transition-all duration-300 text-xl self-center ease-in-out relative slide h-6" </style>
class:opacity-0={!isAtTop}
>
{#if isAtTop}
<div
class="animate-bounce"
in:fly={{ x: 200, duration: 300 }}
out:fly={{ x: -200, duration: 300 }}
>
<ArrowDown></ArrowDown>
</div>
{/if}
</div>
</header>

View File

@ -1,12 +1,15 @@
<script> <script>
import MaterialSymbolsArrowForwardRounded from "~icons/material-symbols/arrow-forward-rounded"; import MaterialSymbolsArrowForwardRounded from "~icons/material-symbols/arrow-forward-rounded";
import MaterialSymbolsLabProfileOutline from '~icons/material-symbols/lab-profile-outline'; import MaterialSymbolsLabProfileOutline from '~icons/material-symbols/lab-profile-outline';
import Down from "./navigation-items/Down.svelte";
export let scrollInDirection;
let mediaPageOnline = false; let mediaPageOnline = false;
</script> </script>
<div id="media" class="w-screen h-screen flex flex-col justify-between items-center">
<div class="w-screen h-screen flex flex-col justify-center items-center"> <div class="spacer"></div>
<div class="flex flex-col justify-center items-center">
<h2 class="h2 font-bold">Backwards Media</h2> <h2 class="h2 font-bold">Backwards Media</h2>
<h3 class="h3">Upload and Share Media with your Friends</h3> <h3 class="h3">Upload and Share Media with your Friends</h3>
<div class="flex flex-row controls pt-4 gap-12"> <div class="flex flex-row controls pt-4 gap-12">
@ -20,6 +23,10 @@
</a> </a>
</div> </div>
</div> </div>
<div class="wrapper">
<Down {scrollInDirection} />
</div>
</div>
<style> <style>
/* dumb ass name :(, cool ass animation :) */ /* dumb ass name :(, cool ass animation :) */

View File

@ -2,7 +2,9 @@
import { Avatar } from "@skeletonlabs/skeleton"; import { Avatar } from "@skeletonlabs/skeleton";
import projects from "$lib/data/projects.json"; import projects from "$lib/data/projects.json";
import { onMount } from "svelte"; import { onMount } from "svelte";
import Up from "./navigation-items/Up.svelte";
export let scrollInDirection;
const fallbackThumbnail = "/Image_not_available.png"; // Set a valid default image path const fallbackThumbnail = "/Image_not_available.png"; // Set a valid default image path
function handleImageError(event, type) { function handleImageError(event, type) {
@ -13,7 +15,9 @@
</script> </script>
<div class="min-h-screen"> <div id="projects" class="min-h-screen">
<div class="wrapper">
<Up {scrollInDirection} />
<h2 class="h2 text-center w-screen pt-4 overflow-hidden">Projects</h2> <h2 class="h2 text-center w-screen pt-4 overflow-hidden">Projects</h2>
<div class="flex flex-wrap gap-4 p-4 w-max max-w-full m-auto"> <div class="flex flex-wrap gap-4 p-4 w-max max-w-full m-auto">
{#each projects as project} {#each projects as project}
@ -48,3 +52,4 @@
{/each} {/each}
</div> </div>
</div> </div>
</div>

View File

@ -1,6 +1,9 @@
<script> <script>
import Techs from '$lib/data/techstack.json'; import Techs from '$lib/data/techstack.json';
import { Avatar } from '@skeletonlabs/skeleton'; import { Avatar } from '@skeletonlabs/skeleton';
import Left from './navigation-items/Left.svelte';
export let scrollInDirection;
</script> </script>
<!-- <div class="w-screen h-screen text-center pb-32 flex justify-center items-center px-8"> <!-- <div class="w-screen h-screen text-center pb-32 flex justify-center items-center px-8">
@ -19,7 +22,11 @@
</div> </div>
</div> --> </div> -->
<div class="w-screen h-max min-h-screen flex flex-col justify-center items-center py-32"> <div class="w-screen h-max min-h-screen flex flex-row justify-between items-center">
<div>
<Left {scrollInDirection} />
</div>
<div id="techstack" class="max-w-2/3 flex flex-col justify-center items-center">
<div class="header-wrapper text-center overflow-visible"> <div class="header-wrapper text-center overflow-visible">
<h2 class="flex-shrink-0 flex-grow-1 h2 font-bold pb-0 w-full overflow-hidden">My Current Tech Stack</h2> <h2 class="flex-shrink-0 flex-grow-1 h2 font-bold pb-0 w-full overflow-hidden">My Current Tech Stack</h2>
<span class="text-sm pt-0 text-surface-700 dark:text-surface-200">Subject to Change</span> <span class="text-sm pt-0 text-surface-700 dark:text-surface-200">Subject to Change</span>
@ -34,3 +41,11 @@
{/each} {/each}
</div> </div>
</div> </div>
<div class="spacer"></div>
</div>
<style>
.max-w-2\/3 {
max-width: 66.6%;
}
</style>

View File

@ -0,0 +1,10 @@
<script>
import ArrowDown from "~icons/material-symbols/keyboard-double-arrow-down-rounded";
export let scrollInDirection;
</script>
<div class="w-full h-full flex justify-center items-end text-3xl">
<button on:click={() => { scrollInDirection([1, 0]) }}>
<ArrowDown />
</button>
</div>

View File

@ -0,0 +1,10 @@
<script>
import ArrowLeft from "~icons/material-symbols/keyboard-double-arrow-left-rounded";
export let scrollInDirection;
</script>
<div class="w-full h-full flex justify-start items-center text-3xl">
<button on:click={() => { scrollInDirection([0, -1]) }}>
<ArrowLeft />
</button>
</div>

View File

@ -0,0 +1,10 @@
<script>
import ArrowRight from "~icons/material-symbols/keyboard-double-arrow-right-rounded";
export let scrollInDirection;
</script>
<div class="w-full h-full flex justify-end items-center text-3xl">
<button on:click={() => { scrollInDirection([0, 1]) }}>
<ArrowRight />
</button>
</div>

View File

@ -0,0 +1,10 @@
<script>
import ArrowUp from "~icons/material-symbols/keyboard-double-arrow-up-rounded";
export let scrollInDirection;
</script>
<div class="w-full h-full flex justify-center items-start text-3xl">
<button on:click={() => { scrollInDirection([-1, 0]) }}>
<ArrowUp />
</button>
</div>

View File

@ -6,93 +6,91 @@
import Contact from "$lib/components/Contact.svelte"; import Contact from "$lib/components/Contact.svelte";
import TechStack from "$lib/components/TechStack.svelte"; import TechStack from "$lib/components/TechStack.svelte";
import Projects from "$lib/components/Projects.svelte"; import Projects from "$lib/components/Projects.svelte";
import { tableMapperValues } from "@skeletonlabs/skeleton";
/* IMPORTANT */ function scrollToSection(section, smooth) {
// Anything added into the page directly will likely break the page's scrolling behaviour section.scrollIntoView({
// To properly add something to the main page, make it into a component and add it to the array. behavior: smooth ? "smooth" : "instant",
// This array is in order of how they are to be displayed, modifying their positions will modify them in page. block: "center",
});
}
let slides = [ // by ID
Header, let layout = [
Projects, [null, "media", null],
TechStack, ["contact", "header", "techstack"],
Contact, [null, "projects", null],
// Media,
]; ];
let selectedId = "header";
let currentSection = 0; function getIndexPathOfSelected() {
for (let rowIndex = 0; rowIndex < layout.length; rowIndex++) {
const colIndex = layout[rowIndex].indexOf(selectedId);
// Update the current section based on scroll position if (colIndex !== -1) {
const handleScroll = () => { return [rowIndex, colIndex];
const sections = document.querySelectorAll(".section");
const scrollTop = document.querySelector(".scroll-container").scrollTop;
sections.forEach((section, index) => {
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
currentSection = index;
} }
}
return null;
}
function evaluateArrays(input, equationArr) {
let output = [];
if (input.length !== equationArr.length)
return null;
for (let index = 0; index < input.length; index++) {
output.push(input[index] + equationArr[index]);
}
return output;
}
function scrollInDirection(direction) {
const currentCoords = getIndexPathOfSelected();
const newCoords = evaluateArrays(currentCoords, direction);
console.log(currentCoords)
console.log(newCoords)
const sectionId = layout[newCoords[0]][newCoords[1]];
console.log(sectionId);
selectedId = sectionId;
scrollToSection(document.getElementById(sectionId), true);
}
onMount(() => {
scrollToSection(document.getElementById("header"));
}); });
};
</script> </script>
<div id="main" class="scroll-container" on:scroll={handleScroll}> <main class="grid">
{#each slides as content} <div class="page-card spacer"></div>
<section class="section"> <Media {scrollInDirection}></Media>
<svelte:component this={content} /> <div class="page-card spacer"></div>
</section> <Contact {scrollInDirection}></Contact>
{/each} <Header {scrollInDirection}></Header>
</div> <TechStack {scrollInDirection}></TechStack>
<div class="page-card spacer"></div>
<!-- Tracker --> <Projects {scrollInDirection}></Projects>
{#if currentSection > 0} </main>
<div in:fly={{ x: 50, duration: 300 }} out:fly={{ x: 50, duration: 300 }} class="tracker">
{#each slides.slice(1) as _, i}
<div class="tracker-dot {i + 1 === currentSection ? 'active' : ''}"></div>
{/each}
</div>
{/if}
<style> <style>
.scroll-container { .page-card {
scroll-snap-type: y mandatory; width: 100vw;
overflow-y: auto;
height: 100vh; height: 100vh;
width: 100vw; /* scroll-snap-align: center; */
scroll-behavior: smooth;
} }
.section { main {
min-height: 100vh; /* Full viewport height */ grid-template-areas:
width: 100vw; ". 1 ."
"2 3 4"
". 5 .";
height: 100vh;
/* overflow-y: scroll;
scroll-snap-type: y mandatory;
scroll-behavior: smooth; */
} }
/* Scroll Snapping works well with a mouse, but without it feels forced, weird and wrong. */ main > * {
@media (width >= 64rem) {
.section {
scroll-snap-align: center; scroll-snap-align: center;
} }
}
/* Tracker Styles */
.tracker {
position: fixed;
top: 50%;
right: 20px;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10px;
}
.tracker-dot {
width: 10px;
height: 10px;
@apply bg-surface-600;
border-radius: 50%;
transition: background-color 0.3s ease;
}
.tracker-dot.active {
@apply bg-primary-600;
}
</style> </style>