alt-website-test #5
8
package-lock.json
generated
8
package-lock.json
generated
@ -22,7 +22,7 @@
|
|||||||
"@skeletonlabs/skeleton": "^2.10.4",
|
"@skeletonlabs/skeleton": "^2.10.4",
|
||||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.11",
|
"@sveltejs/adapter-node": "^5.2.12",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
@ -1374,9 +1374,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sveltejs/adapter-node": {
|
"node_modules/@sveltejs/adapter-node": {
|
||||||
"version": "5.2.11",
|
"version": "5.2.12",
|
||||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.12.tgz",
|
||||||
"integrity": "sha512-lR7/dfUaKFf3aI408KRDy/BVDYoqUws7zNOJz2Hl4JoshlTnMgdha3brXBRFXB+cWtYvJjjPhvmq3xqpbioi4w==",
|
"integrity": "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"@skeletonlabs/skeleton": "^2.10.4",
|
"@skeletonlabs/skeleton": "^2.10.4",
|
||||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.11",
|
"@sveltejs/adapter-node": "^5.2.12",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
|
23
src/app.css
23
src/app.css
@ -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;
|
|
||||||
} */
|
|
@ -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>
|
@ -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>
|
|
@ -6,12 +6,18 @@
|
|||||||
import MdiDiscord from '~icons/mdi/discord';
|
import MdiDiscord from '~icons/mdi/discord';
|
||||||
import MdiLinkedin from '~icons/mdi/linkedin';
|
import MdiLinkedin from '~icons/mdi/linkedin';
|
||||||
import CibGitea from '~icons/cib/gitea';
|
import CibGitea from '~icons/cib/gitea';
|
||||||
|
let personal = true;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="text-center h-max self-center" id="hero">
|
<div class="text-center h-max self-center" id="hero">
|
||||||
<h1 class="h1 overflow-hidden">Backwards Development</h1>
|
{#if personal}
|
||||||
<h4 class="h4">A Software Development and Distribution Company</h4>
|
<h1 class="h1 overflow-hidden">Alexander Harding</h1>
|
||||||
|
<h3 class="h3">Software and Application Developer</h3>
|
||||||
|
{:else}
|
||||||
|
<h1 class="h1 overflow-hidden">Backwards Development</h1>
|
||||||
|
<h4 class="h4">A Software Development and Distribution Company</h4>
|
||||||
|
{/if}
|
||||||
<div class="flex justify-evenly pt-4">
|
<div class="flex justify-evenly pt-4">
|
||||||
<a href="https://github.com/BackwardsUser/" class="btn variant-filled-surface text-2xl p-3 rounded-md spin">
|
<a href="https://github.com/BackwardsUser/" class="btn variant-filled-surface text-2xl p-3 rounded-md spin">
|
||||||
<span class="block spinner duration-500"><MdiGithub /></span>
|
<span class="block spinner duration-500"><MdiGithub /></span>
|
||||||
|
@ -1,25 +1,32 @@
|
|||||||
<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>
|
||||||
<h2 class="h2 font-bold">Backwards Media</h2>
|
<div class="flex flex-col justify-center items-center">
|
||||||
<h3 class="h3">Upload and Share Media with your Friends</h3>
|
<h2 class="h2 font-bold">Backwards Media</h2>
|
||||||
<div class="flex flex-row controls pt-4 gap-12">
|
<h3 class="h3">Upload and Share Media with your Friends</h3>
|
||||||
<a href={mediaPageOnline ? "https://media.backwards.dev/" : ""} class="btn variant-filled-primary cool-hover opacity-50 cursor-not-allowed">
|
<div class="flex flex-row controls pt-4 gap-12">
|
||||||
<span>Try it out</span>
|
<a href={mediaPageOnline ? "https://media.backwards.dev/" : ""} class="btn variant-filled-primary cool-hover opacity-50 cursor-not-allowed">
|
||||||
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsArrowForwardRounded /></span>
|
<span>Try it out</span>
|
||||||
</a>
|
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsArrowForwardRounded /></span>
|
||||||
<a href="/about#media" class="btn variant-ghost-surface cool-hover">
|
</a>
|
||||||
<span>Learn more</span>
|
<a href="/about#media" class="btn variant-ghost-surface cool-hover">
|
||||||
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsLabProfileOutline /></span>
|
<span>Learn more</span>
|
||||||
</a>
|
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsLabProfileOutline /></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper">
|
||||||
|
<Down {scrollInDirection} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* dumb ass name :(, cool ass animation :) */
|
/* dumb ass name :(, cool ass animation :) */
|
||||||
|
@ -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,38 +15,41 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="min-h-screen">
|
<div id="projects" class="min-h-screen">
|
||||||
<h2 class="h2 text-center w-screen pt-4 overflow-hidden">Projects</h2>
|
<div class="wrapper">
|
||||||
<div class="flex flex-wrap gap-4 p-4 w-max max-w-full m-auto">
|
<Up {scrollInDirection} />
|
||||||
{#each projects as project}
|
<h2 class="h2 text-center w-screen pt-4 overflow-hidden">Projects</h2>
|
||||||
<a href={project.url} class="card w-min variant-glass-surface card-hover overflow-hidden flex flex-col">
|
<div class="flex flex-wrap gap-4 p-4 w-max max-w-full m-auto">
|
||||||
<header>
|
{#each projects as project}
|
||||||
<img
|
<a href={project.url} class="card w-min variant-glass-surface card-hover overflow-hidden flex flex-col">
|
||||||
src={project.thumbnail || fallbackThumbnail}
|
<header>
|
||||||
class="bg-black/50 aspect=[21/9] object-cover flex justify-center items-center"
|
<img
|
||||||
alt={project.name}
|
src={project.thumbnail || fallbackThumbnail}
|
||||||
loading="lazy"
|
class="bg-black/50 aspect=[21/9] object-cover flex justify-center items-center"
|
||||||
on:error={handleImageError}>
|
alt={project.name}
|
||||||
</header>
|
loading="lazy"
|
||||||
<div class="p-4 space-y-4 flex-auto">
|
on:error={handleImageError}>
|
||||||
<h3 class="h3" data-toc-ignore>{project.name}</h3>
|
</header>
|
||||||
<article>
|
<div class="p-4 space-y-4 flex-auto">
|
||||||
<p>
|
<h3 class="h3" data-toc-ignore>{project.name}</h3>
|
||||||
{project.description}
|
<article>
|
||||||
</p>
|
<p>
|
||||||
</article>
|
{project.description}
|
||||||
</div>
|
</p>
|
||||||
<hr class="opacity-50" />
|
</article>
|
||||||
<footer class="p-4 flex text-nowrap justify-start items-center space-x-4">
|
|
||||||
<Avatar src={project.author.icon || fallbackAvatar} width="w-8" />
|
|
||||||
<div class="flex-auto gap-6 flex justify-between items-center">
|
|
||||||
<h6 class="font-bold" data-toc-ignore>
|
|
||||||
By {project.author.username}
|
|
||||||
</h6>
|
|
||||||
<small>Updated {project.date}</small>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
<hr class="opacity-50" />
|
||||||
</a>
|
<footer class="p-4 flex text-nowrap justify-start items-center space-x-4">
|
||||||
{/each}
|
<Avatar src={project.author.icon || fallbackAvatar} width="w-8" />
|
||||||
|
<div class="flex-auto gap-6 flex justify-between items-center">
|
||||||
|
<h6 class="font-bold" data-toc-ignore>
|
||||||
|
By {project.author.username}
|
||||||
|
</h6>
|
||||||
|
<small>Updated {project.date}</small>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
<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 id="techstack" class="w-screen h-max min-h-screen flex flex-row justify-between items-center">
|
||||||
<div class="wrapper h-max overflow-visible">
|
<div>
|
||||||
<h2 class="h2 font-bold pb-0 w-full overflow-hidden">My Current Tech Stack</h2>
|
<Left {scrollInDirection} />
|
||||||
<span class="text-sm pt-0 text-surface-700 dark:text-surface-200">Subject to change</span>
|
</div>
|
||||||
<div class="pt-4 m-auto w-max max-w-full h-max flex flex-wrap gap-4 justify-center">
|
<div class="max-w-2/3 flex flex-col justify-center items-center">
|
||||||
|
<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>
|
||||||
|
<span class="text-sm pt-0 text-surface-700 dark:text-surface-200">Subject to Change</span>
|
||||||
|
</div>
|
||||||
|
<div class="pt-4 w-max max-w-full h-max flex flex-wrap gap-4 justify-center overflow-visible">
|
||||||
{#each Techs as tech}
|
{#each Techs as tech}
|
||||||
<a href="{tech.url}" class="min-w-72 flex flex-row justify-between items-center card card-hover p-4 hover:bg-surface-700 rounded-lg">
|
<a href="{tech.url}" class="min-w-72 flex flex-row justify-between items-center card card-hover p-4 dark:hover:bg-surface-700 hover:bg-surface-200 rounded-lg">
|
||||||
<Avatar class="p-2" src={tech.logo} alt={`Logo of ${tech.name}`} />
|
<Avatar class="p-2" src={tech.logo} alt={`Logo of ${tech.name}`} />
|
||||||
<span class="text-xl">{tech.name}</span>
|
<span class="text-xl">{tech.name}</span>
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
@ -17,20 +25,11 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
<div class="spacer"></div>
|
||||||
|
|
||||||
<div class="w-screen h-max min-h-screen flex flex-col justify-center items-center py-32">
|
|
||||||
<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>
|
|
||||||
<span class="text-sm pt-0 text-surface-700 dark:text-surface-200">Subject to Change</span>
|
|
||||||
</div>
|
|
||||||
<div class="pt-4 w-max max-w-full h-max flex flex-wrap gap-4 justify-center overflow-visible">
|
|
||||||
{#each Techs as tech}
|
|
||||||
<a href="{tech.url}" class="min-w-72 flex flex-row justify-between items-center card card-hover p-4 dark:hover:bg-surface-700 hover:bg-surface-200 rounded-lg">
|
|
||||||
<Avatar class="p-2" src={tech.logo} alt={`Logo of ${tech.name}`} />
|
|
||||||
<span class="text-xl">{tech.name}</span>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
</a>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.max-w-2\/3 {
|
||||||
|
max-width: 66.6%;
|
||||||
|
}
|
||||||
|
</style>
|
13
src/lib/components/navigation-items/Down.svelte
Normal file
13
src/lib/components/navigation-items/Down.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<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 class="relative" on:click={() => { scrollInDirection([1, 0]) }}>
|
||||||
|
<ArrowDown />
|
||||||
|
<div class="absolute -z-10 -top-0.5 left-0 text-surface-400">
|
||||||
|
<ArrowDown />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
14
src/lib/components/navigation-items/Left.svelte
Normal file
14
src/lib/components/navigation-items/Left.svelte
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<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 class="relative" on:click={() => { scrollInDirection([0, -1]) }}>
|
||||||
|
<ArrowLeft />
|
||||||
|
<div class="absolute -z-10 top-0 left-0.5 text-surface-400">
|
||||||
|
<ArrowLeft />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
13
src/lib/components/navigation-items/Right.svelte
Normal file
13
src/lib/components/navigation-items/Right.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<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 class="relative" on:click={() => { scrollInDirection([0, 1]) }}>
|
||||||
|
<ArrowRight />
|
||||||
|
<div class="absolute -z-10 top-0 -left-0.5 text-surface-400">
|
||||||
|
<ArrowRight />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
13
src/lib/components/navigation-items/Up.svelte
Normal file
13
src/lib/components/navigation-items/Up.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<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 class="relative" on:click={() => { scrollInDirection([-1, 0]) }}>
|
||||||
|
<ArrowUp />
|
||||||
|
<div class="absolute -z-10 top-0.5 left-0 text-surface-400">
|
||||||
|
<ArrowUp />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
@ -6,93 +6,138 @@
|
|||||||
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) => {
|
return null;
|
||||||
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
}
|
||||||
currentSection = index;
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const itemAtCoords = layout[newCoords[0]][newCoords[1]];
|
||||||
|
if (itemAtCoords == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const sectionId = layout[newCoords[0]][newCoords[1]];
|
||||||
|
selectedId = sectionId;
|
||||||
|
scrollToSection(document.getElementById(sectionId), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = {
|
||||||
|
"up": [
|
||||||
|
"ArrowUp",
|
||||||
|
"w"
|
||||||
|
],
|
||||||
|
"down": [
|
||||||
|
"ArrowDown",
|
||||||
|
"s"
|
||||||
|
],
|
||||||
|
"left": [
|
||||||
|
"ArrowLeft",
|
||||||
|
"a"
|
||||||
|
],
|
||||||
|
"right": [
|
||||||
|
"ArrowRight",
|
||||||
|
"d"
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
scrollToSection(document.getElementById("header"));
|
||||||
|
|
||||||
|
window.addEventListener("resize", e => {
|
||||||
|
console.log(selectedId)
|
||||||
|
scrollToSection(document.getElementById(selectedId));
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", e => {
|
||||||
|
const directionArr = Object.entries(keys).filter(([_, values]) => values.some(v => v == e.key));
|
||||||
|
if (!directionArr || directionArr.length == 0)
|
||||||
|
return;
|
||||||
|
const direction = directionArr[0][0];
|
||||||
|
switch (direction) {
|
||||||
|
case "up":
|
||||||
|
scrollInDirection([-1, 0]);
|
||||||
|
break;
|
||||||
|
case "down":
|
||||||
|
scrollInDirection([1, 0]);
|
||||||
|
break;
|
||||||
|
case "left":
|
||||||
|
scrollInDirection([0, -1]);
|
||||||
|
break;
|
||||||
|
case "right":
|
||||||
|
scrollInDirection([0, 1]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
</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) {
|
scroll-snap-align: center;
|
||||||
.section {
|
|
||||||
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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user