Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
56545bc3a3 | |||
a7d1cf28ba | |||
1517e81ef8 | |||
d78756f367 | |||
03f476f7a0 | |||
476203d81b | |||
6fdbb9079e |
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
services:
|
||||||
|
nodejs:
|
||||||
|
image: node:latest
|
||||||
|
container_name: node_app
|
||||||
|
working_dir: /app
|
||||||
|
volumes:
|
||||||
|
- ./:/app
|
||||||
|
ports:
|
||||||
|
- "80:5173"
|
||||||
|
command: >
|
||||||
|
sh -c "npm i -g npm@latest &&
|
||||||
|
npm i &&
|
||||||
|
npm run dev"
|
@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev --host",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
|
9
src/lib/components/About/Me.svelte
Normal file
9
src/lib/components/About/Me.svelte
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
import Header from "$lib/components/Common/Content/Heading.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-max h-1/2 m-auto flex flex-col">
|
||||||
|
<Header content="Backwards Development"/>
|
||||||
|
<p class="max-w-screen-lg">I'm Alexander Harding, I am the Founder of Backwards Development. I created Backwards Development as an umbrella for all of my professional works, this website was designed to allow for distribution for my software, tools and applications!</p>
|
||||||
|
<p class="max-w-screen-lg">Backwards Development is a group I founded to work on whatever enter's my plate, If you need anything done, feel free to <a href="/#contact" class="text-primary-500 underline">Contact Us</a> at any time!</p>
|
||||||
|
</div>
|
7
src/lib/components/About/Media.svelte
Normal file
7
src/lib/components/About/Media.svelte
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import Heading from "$lib/components/Common/Content/Heading.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Heading content="Backwards Media"/>
|
||||||
|
</div>
|
5
src/lib/components/Common/Content/Heading.svelte
Normal file
5
src/lib/components/Common/Content/Heading.svelte
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
export let content;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1 class="h1 text-center pt-4">{content}</h1>
|
75
src/lib/components/Common/Tracker.svelte
Normal file
75
src/lib/components/Common/Tracker.svelte
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<script>
|
||||||
|
import { sectionStore } from "$lib/stores/currentSection";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { fly, slide } from "svelte/transition";
|
||||||
|
|
||||||
|
export let page,
|
||||||
|
slides,
|
||||||
|
includeFirst = true;
|
||||||
|
|
||||||
|
let newSlides = includeFirst ? slides : slides.slice(1);
|
||||||
|
|
||||||
|
let pageSection = sectionStore[page];
|
||||||
|
|
||||||
|
let currentSection = $pageSection;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
pageSection.subscribe((cs) => {
|
||||||
|
currentSection = cs;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if includeFirst ? currentSection >= 0 : currentSection > 0}
|
||||||
|
<div
|
||||||
|
in:fly={{ x: 50, duration: 300 }}
|
||||||
|
out:fly={{ x: 50, duration: 300 }}
|
||||||
|
class="tracker"
|
||||||
|
>
|
||||||
|
{#each newSlides as _, i}
|
||||||
|
<div
|
||||||
|
class="tracker-dot {(includeFirst ? i : i + 1) ===
|
||||||
|
currentSection
|
||||||
|
? 'active'
|
||||||
|
: ''}"
|
||||||
|
></div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
.tracker-dot {
|
||||||
|
@apply bg-surface-300;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracker-dot.active {
|
||||||
|
@apply bg-primary-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -4,7 +4,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-screen h-screen flex justify-center items-center">
|
<div class="w-screen h-screen flex justify-center items-center">
|
||||||
<form action="?/contact" class="bg-surface-900 w-1/2 h-1/2 p-8 rounded-md">
|
<form action="?/contact" class="bg-surface-200 dark:bg-surface-900 w-1/2 h-max p-8 rounded-md">
|
||||||
<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" />
|
||||||
<p class="pt-4">Fullname</p>
|
<p class="pt-4">Fullname</p>
|
||||||
@ -34,4 +34,4 @@
|
|||||||
<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>
|
</div>
|
@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import Hero from "$lib/components/Hero.svelte";
|
import Hero from "$lib/components/Main/Hero.svelte";
|
||||||
import ArrowDown from "~icons/material-symbols/keyboard-double-arrow-down-rounded";
|
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";
|
6
src/lib/stores/currentSection.js
Normal file
6
src/lib/stores/currentSection.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export let sectionStore = {
|
||||||
|
about: writable(),
|
||||||
|
main: writable()
|
||||||
|
};
|
@ -1,92 +1,85 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Header from "$lib/components/Header.svelte";
|
import Header from "$lib/components/Main/Header.svelte";
|
||||||
import Downloads from "$lib/components/Downloads.svelte";
|
import Downloads from "$lib/components/Main/Downloads.svelte";
|
||||||
import { fly } from "svelte/transition";
|
import { fly, slide } from "svelte/transition";
|
||||||
import Media from "$lib/components/Media.svelte";
|
import Media from "$lib/components/Main/Media.svelte";
|
||||||
import Contact from "$lib/components/Contact.svelte";
|
import Contact from "$lib/components/Main/Contact.svelte";
|
||||||
import TechStack from "$lib/components/TechStack.svelte";
|
import TechStack from "$lib/components/Main/TechStack.svelte";
|
||||||
|
import Tracker from "$lib/components/Common/Tracker.svelte";
|
||||||
|
import { sectionStore } from "$lib/stores/currentSection";
|
||||||
|
|
||||||
/* IMPORTANT */
|
/* IMPORTANT */
|
||||||
// Anything added into the page directly will likely break the page's scrolling behaviour
|
// Anything added into the page directly will likely break the page's scrolling behaviour
|
||||||
// To properly add something to the main page, make it into a component and add it to the array.
|
// To properly add something to the main page, make it into a component and add it to the array.
|
||||||
// This array is in order of how they are to be displayed, modifying their positions will modify them in page.
|
// This array is in order of how they are to be displayed, modifying their positions will modify them in page.
|
||||||
|
|
||||||
let slides = [
|
let slides = [Header, Downloads, Media, TechStack, Contact];
|
||||||
Header,
|
|
||||||
Downloads,
|
|
||||||
Media,
|
|
||||||
TechStack,
|
|
||||||
Contact
|
|
||||||
];
|
|
||||||
|
|
||||||
|
let { main } = sectionStore;
|
||||||
|
|
||||||
let currentSection = 0;
|
if (!$main) main.set(0);
|
||||||
|
|
||||||
// Update the current section based on scroll position
|
let currentSection = $main;
|
||||||
const handleScroll = () => {
|
|
||||||
const sections = document.querySelectorAll(".section");
|
// Update the current section based on scroll position
|
||||||
const scrollTop = document.querySelector(".scroll-container").scrollTop;
|
const handleScroll = () => {
|
||||||
sections.forEach((section, index) => {
|
const sections = document.querySelectorAll(".section");
|
||||||
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
const scrollTop = document.querySelector(".scroll-container").scrollTop;
|
||||||
currentSection = index;
|
sections.forEach((section, index) => {
|
||||||
}
|
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
||||||
});
|
main.set(index);
|
||||||
};
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="main" class="scroll-container" on:scroll={handleScroll}>
|
<div id="main" class="scroll-container" on:scroll={handleScroll}>
|
||||||
{#each slides as content}
|
{#each slides as content}
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<svelte:component this={content} />
|
<svelte:component this={content} />
|
||||||
</section>
|
</section>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tracker -->
|
<!-- Tracker -->
|
||||||
{#if currentSection > 0}
|
<Tracker page="main" {slides} includeFirst={false} />
|
||||||
<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 {
|
.scroll-container {
|
||||||
scroll-snap-type: y mandatory;
|
scroll-snap-type: y mandatory;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
scroll-snap-align: start;
|
scroll-snap-align: start;
|
||||||
min-height: 100vh; /* Full viewport height */
|
min-height: 100vh; /* Full viewport height */
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tracker Styles */
|
/* Tracker Styles */
|
||||||
.tracker {
|
.tracker {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tracker-dot {
|
.tracker-dot {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
@apply bg-surface-600;
|
@apply bg-surface-600;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tracker-dot.active {
|
.tracker-dot.active {
|
||||||
@apply bg-primary-600;
|
@apply bg-primary-600;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
61
src/routes/about/+page.svelte
Normal file
61
src/routes/about/+page.svelte
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<script>
|
||||||
|
import Me from '$lib/components/About/Me.svelte';
|
||||||
|
import Media from '$lib/components/About/Media.svelte';
|
||||||
|
import Tracker from '$lib/components/Common/Tracker.svelte';
|
||||||
|
import { sectionStore } from '$lib/stores/currentSection';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
/* IMPORTANT */
|
||||||
|
// Anything added into the page directly will likely break the page's scrolling behaviour
|
||||||
|
// To properly add something to the main page, make it into a component and add it to the array.
|
||||||
|
// This array is in order of how they are to be displayed, modifying their positions will modify them in page.
|
||||||
|
|
||||||
|
let slides = [
|
||||||
|
Me,
|
||||||
|
Media
|
||||||
|
];
|
||||||
|
|
||||||
|
let { about } = sectionStore
|
||||||
|
|
||||||
|
if (!$about) about.set(0);
|
||||||
|
|
||||||
|
let currentSection = $about;
|
||||||
|
|
||||||
|
// Update the current section based on scroll position
|
||||||
|
const handleScroll = () => {
|
||||||
|
const sections = document.querySelectorAll('.section');
|
||||||
|
const scrollTop = document.querySelector('.scroll-container').scrollTop;
|
||||||
|
sections.forEach((section, index) => {
|
||||||
|
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
||||||
|
about.set(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="main" class="scroll-container" on:scroll={handleScroll}>
|
||||||
|
{#each slides as content}
|
||||||
|
<section class="section flex flex-row">
|
||||||
|
<svelte:component this={content} />
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tracker -->
|
||||||
|
<Tracker page="about" slides={slides} />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.scroll-container {
|
||||||
|
scroll-snap-type: y mandatory;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
scroll-snap-align: start;
|
||||||
|
min-height: 100vh; /* Full viewport height */
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user