FEAT: Started fleshing out content on the webpage
This commit is contained in:
42
src/app.html
42
src/app.html
@ -1,19 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="Luke Else - Software Developer at Thales UK. I specialise in developing distributed systems in C++ using highly scalable internal frameworks. I also develop backend and system applications in my spare time using both Svelte, Rust and C++. Feel free to check my work out at https://git.luke-else.co.uk." />
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Luke Else - Software Developer at Thales UK. I specialise in developing distributed systems in C++ using highly scalable internal frameworks. I also develop backend and system applications in my spare time using both Svelte, Rust and C++. Feel free to check my work out at https://git.luke-else.co.uk."
|
||||
/>
|
||||
<meta name="author" content="Luke Else (mail@luke-else.co.uk)" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.15.1/devicon.min.css">
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<script async src="https://tracking.luke-else.co.uk/tracker.js" data-ackee-server="https://tracking.luke-else.co.uk" data-ackee-domain-id="6c59ab88-dc6d-4d53-9831-0d6bff919dcd" data-ackee-opts='{ "detailed": true }'></script>
|
||||
%sveltekit.head%
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.15.1/devicon.min.css"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<script
|
||||
async
|
||||
src="https://tracking.luke-else.co.uk/tracker.js"
|
||||
data-ackee-server="https://tracking.luke-else.co.uk"
|
||||
data-ackee-domain-id="6c59ab88-dc6d-4d53-9831-0d6bff919dcd"
|
||||
data-ackee-opts='{ "detailed": true }'
|
||||
></script>
|
||||
%sveltekit.head%
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
<style></style>
|
||||
</head>
|
||||
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,24 +3,29 @@
|
||||
export let headerRight: string = "";
|
||||
export let headerColour: string = "text-red-500";
|
||||
export let footer: string = "";
|
||||
|
||||
// Allows additional styling to be applied to the Card component's outer wrapping
|
||||
export let containerStyle: string = "";
|
||||
</script>
|
||||
|
||||
<div class="bg-slate-100/10 dark:bg-slate-100/10 rounded-2xl shadow-2xl p-6 flex flex-col h-full w-full">
|
||||
<div class="{headerColour} flex flex-row justify-between items-center mb-4">
|
||||
<p class="text-2xl md:text-3xl font-bold truncate">{headerLeft}</p>
|
||||
|
||||
{#if headerRight}
|
||||
<p class="max-md:hidden text-xl md:text-2xl truncate">{@html headerRight}</p>
|
||||
<div class={containerStyle}>
|
||||
<div class="bg-slate-100/10 dark:bg-slate-100/10 rounded-2xl shadow-2xl p-6 flex flex-col h-full w-full">
|
||||
<div class="{headerColour} flex flex-row justify-between items-center mb-4">
|
||||
<p class="text-2xl md:text-3xl font-bold truncate">{headerLeft}</p>
|
||||
|
||||
{#if headerRight}
|
||||
<p class="max-md:hidden text-xl md:text-2xl truncate">{@html headerRight}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<hr class="mb-4 border-1" />
|
||||
<div class="flex-1 flex flex-col justify-center p-5">
|
||||
<slot />
|
||||
</div>
|
||||
{#if footer}
|
||||
<hr class="my-4 border-1" />
|
||||
<div class="mt-2 text-base opacity-90">
|
||||
{@html footer}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<hr class="mb-4 border-1" />
|
||||
<div class="flex-1 flex flex-col justify-center p-5">
|
||||
<slot />
|
||||
</div>
|
||||
{#if footer}
|
||||
<hr class="my-4 border-1" />
|
||||
<div class="mt-2 text-base opacity-90">
|
||||
{@html footer}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
7
src/lib/components/FlexGallery.svelte
Normal file
7
src/lib/components/FlexGallery.svelte
Normal file
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
<!-- FlexGallery.svelte -->
|
||||
<div class="flex flex-wrap gap-10 w-full">
|
||||
<slot />
|
||||
</div>
|
@ -1,39 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let showModal: boolean;
|
||||
|
||||
let dialog: HTMLDialogElement;
|
||||
|
||||
$: if (dialog && showModal) dialog.showModal();
|
||||
|
||||
import CloseIcon from "./Toasts/CloseIcon.svelte";
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
||||
<dialog
|
||||
bind:this={dialog}
|
||||
on:close={() => (showModal = false)}
|
||||
on:click|self={() => dialog.close()}
|
||||
class="max-w-[70vw] rounded-md border-0 p-0 shadow-lg bg-bg text-fg relative animate-[zoom_0.5s_cubic-bezier(0.34,1.56,0.64,1)]"
|
||||
style="box-shadow: 0.5em 0.5em 0.5em var(--header);"
|
||||
>
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div on:click|stopPropagation class="p-4">
|
||||
<slot name="header" />
|
||||
<hr class="my-2 border-accent" />
|
||||
<slot />
|
||||
<hr class="my-2 border-accent" />
|
||||
</div>
|
||||
<button
|
||||
class="close absolute top-4 right-6 text-fg bg-transparent border-0 p-0 m-0 leading-none text-[1.2em] hover:text-accent"
|
||||
on:click={() => dialog.close()}
|
||||
>
|
||||
<CloseIcon width="0.8em" />
|
||||
</button>
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
@keyframes zoom {
|
||||
from { transform: scale(0.95); }
|
||||
to { transform: scale(1); }
|
||||
}
|
||||
</style>
|
@ -2,7 +2,7 @@
|
||||
export let label: string = "";
|
||||
</script>
|
||||
|
||||
<div class="relative flex flex-row w-full min-h-[300px] mt-5 mb-5">
|
||||
<div id={label} class="relative flex flex-row w-full min-h-[300px] mt-5 mb-25">
|
||||
<!-- Sticky/Sliding Label -->
|
||||
<div class="hidden md:flex flex-col items-center mr-6">
|
||||
<div class="sticky top-24 left-0 z-10">
|
||||
|
15
src/lib/components/SkillProgress.svelte
Normal file
15
src/lib/components/SkillProgress.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
export let value: number = 0; // 0 to 100
|
||||
</script>
|
||||
|
||||
<div class="w-full mt-3">
|
||||
<div class="flex justify-between mb-1">
|
||||
<span class="text-sm font-medium text-gray-400">{value}%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-800 rounded-full h-5">
|
||||
<div
|
||||
class="bg-orange-400 h-5 rounded-full transition-all duration-500"
|
||||
style="width: {value}%"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,9 @@
|
||||
import Loading from '$lib/components/Loading.svelte';
|
||||
import Section from '$lib/components/Section.svelte';
|
||||
import Card from '$lib/components/Cards/Card.svelte';
|
||||
import FlexGallery from "$lib/components/FlexGallery.svelte";
|
||||
import SkillProgress from "$lib/components/SkillProgress.svelte";
|
||||
import Timeline from './timeline.svelte';
|
||||
</script>
|
||||
|
||||
{#await getJson('/json/me.json')}
|
||||
@ -33,6 +36,23 @@
|
||||
</div>
|
||||
</Card>
|
||||
</Section>
|
||||
|
||||
<!-- SKills -->
|
||||
<Section label="Skills">
|
||||
<FlexGallery>
|
||||
{#each info.skills as skill}
|
||||
<Card headerLeft={skill.name} footer={skill.link} containerStyle="flex-1 min-w-[250px] max-w-full md:min-w-[33%] opacity-100 hover:opacity-100 hover:scale-[105%] md:opacity-70 transition-all duration-300">
|
||||
{skill.about}
|
||||
|
||||
<SkillProgress value={skill.competency} />
|
||||
</Card>
|
||||
{/each}
|
||||
</FlexGallery>
|
||||
</Section>
|
||||
|
||||
<Section label="Experience">
|
||||
<Timeline timelineData={info.experience} />
|
||||
</Section>
|
||||
{:catch}
|
||||
<div style="display: none;">
|
||||
{toasts.add({
|
||||
|
@ -1,63 +1,67 @@
|
||||
<script lang="ts">
|
||||
export let timelineData: any;
|
||||
|
||||
import Timeline from '$lib/components/timeline/Timeline.svelte';
|
||||
import TimelineItem from '$lib/components/timeline/TimelineItem.svelte';
|
||||
import TimelineSeparator from '$lib/components/timeline/TimelineSeparator.svelte';
|
||||
import TimelineDot from '$lib/components/timeline/TimelineDot.svelte';
|
||||
import TimelineConnector from '$lib/components/timeline/TimelineConnector.svelte';
|
||||
import TimelineContent from '$lib/components/timeline/TimelineContent.svelte';
|
||||
import TimelineOppositeContent from '$lib/components/timeline/TimelineOppositeContent.svelte';
|
||||
import Timeline from '$lib/components/timeline/Timeline.svelte';
|
||||
import TimelineItem from '$lib/components/timeline/TimelineItem.svelte';
|
||||
import TimelineSeparator from '$lib/components/timeline/TimelineSeparator.svelte';
|
||||
import TimelineDot from '$lib/components/timeline/TimelineDot.svelte';
|
||||
import TimelineConnector from '$lib/components/timeline/TimelineConnector.svelte';
|
||||
import TimelineContent from '$lib/components/timeline/TimelineContent.svelte';
|
||||
import TimelineOppositeContent from '$lib/components/timeline/TimelineOppositeContent.svelte';
|
||||
</script>
|
||||
|
||||
<Timeline
|
||||
position="alternate"
|
||||
style={`
|
||||
position="alternate"
|
||||
style={`
|
||||
border-radius: 3%;
|
||||
padding: 1rem;
|
||||
`}
|
||||
>
|
||||
{#each timelineData as item}
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent slot="opposite-content">
|
||||
<p class="oposite-content-title">{item.duration}</p>
|
||||
</TimelineOppositeContent>
|
||||
{#each timelineData as item}
|
||||
<TimelineItem>
|
||||
<TimelineOppositeContent slot="opposite-content">
|
||||
<p class="oposite-content-title">{item.duration}</p>
|
||||
</TimelineOppositeContent>
|
||||
|
||||
<TimelineSeparator>
|
||||
{#if item.duration.includes('Present') || !item.duration.includes('-')}
|
||||
<div class="elementToFadeInAndOut">
|
||||
<TimelineDot style={`background-color: var(--link); border-color: var(--accent);`} />
|
||||
</div>
|
||||
{:else}
|
||||
<TimelineDot style={`background-color: var(--link); border-color: var(--accent);`} />
|
||||
{/if}
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>
|
||||
<h3 class="content-title">{item.title}</h3>
|
||||
<p class="content-description">{@html item.description}</p>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
{/each}
|
||||
<TimelineSeparator>
|
||||
{#if item.duration.includes('Present') || !item.duration.includes('-')}
|
||||
<div class="elementToFadeInAndOut">
|
||||
<TimelineDot
|
||||
style={`background-color: var(--link); border-color: var(--accent);`}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<TimelineDot
|
||||
style={`background-color: var(--link); border-color: var(--accent);`}
|
||||
/>
|
||||
{/if}
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>
|
||||
<h3 class="content-title">{item.title}</h3>
|
||||
<p class="content-description">{@html item.description}</p>
|
||||
</TimelineContent>
|
||||
</TimelineItem>
|
||||
{/each}
|
||||
</Timeline>
|
||||
|
||||
<style>
|
||||
.oposite-content-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--accent);
|
||||
}
|
||||
.content-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.oposite-content-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--accent);
|
||||
}
|
||||
.content-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content-description {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
color: var(--fg);
|
||||
font-weight: lighter;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
</style>
|
||||
.content-description {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
color: var(--fg);
|
||||
font-weight: lighter;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user