This commit is contained in:
Xeovalyte 2023-02-09 20:21:20 +01:00
parent 248868b1bd
commit 372984e55b
12 changed files with 2580 additions and 2601 deletions

1
.prettierigonore Normal file
View File

@ -0,0 +1 @@
.nuxt

1
.prettierrc.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -7,7 +7,7 @@ pipeline:
username: xeovalyte username: xeovalyte
password: password:
from_secret: docker_password from_secret: docker_password
repo: gitea.xeovalyte.dev/xeovalyte/portfolio repo: gitea.xeovalyte.dev/xeovalyte/website
tags: tags:
- latest - latest
registry: gitea.xeovalyte.dev registry: gitea.xeovalyte.dev

44
assets/css/tailwind.css Normal file
View File

@ -0,0 +1,44 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-4xl;
}
h2 {
@apply text-3xl;
}
h3 {
@apply text-2xl;
}
h4 {
@apply text-xl;
}
}
@layer utilities {
.perspective {
perspective: 100px;
}
.preserve-3d {
transform-style: preserve-3d;
}
.distance-1 {
transform: translateZ(-50px) scale(1.5);
}
.distance-2 {
transform: translateZ(-100px) scale(2);
}
.distance-3 {
transform: translateZ(-150px) scale(2.5);
}
.-distance-1 {
transform: translateZ(50px) scale(0.5);
}
}

41
components/About.vue Normal file
View File

@ -0,0 +1,41 @@
<template>
<section class="flex h-screen snap-center items-center justify-center">
<div
class="my-40 flex w-full max-w-xl flex-wrap items-center justify-center gap-5 whitespace-pre-wrap text-lg text-primary-500"
>
<h2
v-animate="{ preset: 'slide-right', duration: 500 }"
class="mb-10 text-center text-3xl font-bold"
>
{{ t("title") }}
</h2>
<div v-animate="{ preset: 'slide-right', delay: 400, duration: 500 }">
{{ t("message") }}
</div>
</div>
</section>
</template>
<script setup>
const { t } = useI18n({ useScope: "local" });
</script>
<i18n lang="yaml">
en:
message: |
Hi,
My name is Timo Boomers (16) also known as Xeovalyte. I live in the Netherlands and I have always found electronics and computers interesting.
When I was 12 I started programming. I now program Websites, Discord bots and Arduino.
title: "About"
nl:
message: |
Hallo,
Mijn naam is Timo Boomers (16) ook wel bekend als Xeovalyte. Ik heb electronica en computers altijd interresant gevonden en ben toen gaan programmeren.
Toen ik 12 was begon ik met programmeren. Ondertussen programmeer ik Websites, Discord bots en Arduino.
title: "Over mij"
</i18n>

40
components/Heading.vue Normal file
View File

@ -0,0 +1,40 @@
<template>
<section
class="relative flex h-screen snap-center items-center justify-center"
>
<div
class="flex flex-wrap items-center justify-center gap-5 text-center text-primary-500"
>
<img
v-animate="{ preset: 'slide-left', delay: 300 }"
src="../assets/icons/logo.svg"
alt="Logo Xeovalyte"
width="150"
/>
<div class="space-y-2">
<h1
v-animate="{ preset: 'slide-up', delay: 450 }"
class="text-7xl font-bold"
>
Xeovalyte
</h1>
<div
v-animate="{ preset: 'slide-right', delay: 600 }"
class="h-1 w-full rounded-full bg-primary-500"
/>
<h3
v-animate="{ preset: 'slide-down', delay: 750 }"
class="text-4xl font-bold"
>
Timo Boomers
</h3>
</div>
<Icon
size="2em"
name="ph:arrow-fat-line-down"
class="absolute bottom-20 basis-full animate-bounce hover:cursor-pointer"
/>
</div>
</section>
</template>

85
components/Skills.vue Normal file
View File

@ -0,0 +1,85 @@
<template>
<section class="flex h-screen snap-center items-center justify-center">
<div
class="my-40 mx-5 flex w-full max-w-3xl flex-col text-primary-500"
v-animate="{ stagger: true, preset: 'slide-left', duration: 500 }"
>
<h2 class="mb-10 text-center text-3xl font-bold">
{{ t("skills.skills") }}
</h2>
<h2 class="text-lg font-bold">Arduino</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-3/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
<h2 class="text-lg font-bold">Docker</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-4/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.advanced") }}
</h2>
</div>
<h2 class="text-lg font-bold">Javascript</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-2/3 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
<h2 class="text-lg font-bold">Linux</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-4/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.advanced") }}
</h2>
</div>
<h2 class="text-lg font-bold">Nuxt</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-3/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
</div>
</section>
</template>
<script setup>
const { t } = useI18n({ useScope: "local" });
</script>
<i18n lang="yaml">
en:
skills:
skills: "Skills"
intermediate: "Intermediate"
advanced: "Advanced"
nl:
skills:
skills: "Vaardigheden"
intermediate: "Gemiddeld"
advanced: "Geavanceerd"
</i18n>

View File

@ -7,27 +7,7 @@ export default defineNuxtConfig({
"nuxt-icons", "nuxt-icons",
"@nuxtjs/robots", "@nuxtjs/robots",
"@nuxtjs/i18n", "@nuxtjs/i18n",
"@nuxtjs/plausible",
], ],
plausible: {
domain: 'xeovalyte.com',
apiHost: 'https://plausible.xeovalyte.dev'
},
app: {
head: {
title: 'Xeovalyte | Timo Boomers Portfolio',
link: [
{
"rel": "icon",
"href": "/favicon.ico",
"type": "image/png"
}
],
meta: [
{ name: 'description', content: 'This is the official portfolio of Xeovalyte or Timo Boomers'}
]
}
},
i18n: { i18n: {
baseUrl: 'https://xeovalyte.com', baseUrl: 'https://xeovalyte.com',
locales: [ locales: [

4833
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,11 +8,10 @@
"postinstall": "nuxt prepare" "postinstall": "nuxt prepare"
}, },
"devDependencies": { "devDependencies": {
"@nuxtjs/plausible": "^0.2.0",
"@nuxtjs/tailwindcss": "^6.2.0", "@nuxtjs/tailwindcss": "^6.2.0",
"@vueuse/core": "^9.8.2", "@vueuse/core": "^9.8.2",
"@vueuse/nuxt": "^9.8.2", "@vueuse/nuxt": "^9.8.2",
"nuxt": "3.1.2", "nuxt": "3.0.0",
"nuxt-icon": "^0.1.8", "nuxt-icon": "^0.1.8",
"prettier": "^2.8.3", "prettier": "^2.8.3",
"prettier-plugin-tailwindcss": "^0.2.2" "prettier-plugin-tailwindcss": "^0.2.2"
@ -21,6 +20,7 @@
"@nuxtjs/i18n": "^8.0.0-beta.9", "@nuxtjs/i18n": "^8.0.0-beta.9",
"@nuxtjs/robots": "^3.0.0", "@nuxtjs/robots": "^3.0.0",
"locomotive-scroll": "^4.1.4", "locomotive-scroll": "^4.1.4",
"motion": "^10.15.5",
"nuxt-icons": "^3.1.0" "nuxt-icons": "^3.1.0"
} }
} }

9
pages/index.vue Normal file
View File

@ -0,0 +1,9 @@
<template>
<div class="h-screen snap-y snap-mandatory overflow-y-auto bg-dark-200">
<Heading />
<About />
<Skills />
</div>
</template>
<script setup></script>

101
plugins/motion.js Normal file
View File

@ -0,0 +1,101 @@
export default defineNuxtPlugin((NuxtApp) => {
NuxtApp.vueApp.directive('animate', (el, binding) => {
el.classList.add('animate')
el.setAttribute('data-animate-duration', binding.value.duration || 250 )
el.setAttribute('data-animate-delay', binding.value.delay || 200 )
el.setAttribute('data-animate-preset', binding.value.preset || 'fade' )
el.setAttribute('data-animate-stagger', binding.value.stagger || false )
el.setAttribute('data-animate-stagger-delay', binding.value.staggerDelay || 100 )
})
NuxtApp.hook('page:finish', () => {
const applyClasses = (el, type) => {
const initialClasses = JSON.parse(el.getAttribute('data-animate-initial'))
const animateClasses = JSON.parse(el.getAttribute('data-animate-animate'))
if (type === 'initial') {
Object.keys(initialClasses).forEach(x => {
el.style[x] = initialClasses[x]
})
el.style['transition-property'] = 'none'
}
if (type === 'animate') {
Object.keys(animateClasses).forEach(x => {
el.style[x] = animateClasses[x]
})
el.style['transition-property'] = 'all'
}
}
const callback = (entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
applyClasses(entry.target, 'animate')
} else {
applyClasses(entry.target, 'initial')
}
})
}
// Configure staggering animations
let targets = document.querySelectorAll('.animate')
targets.forEach((target) => {
if (target.getAttribute('data-animate-stagger') === 'true') {
target.classList.remove('animate')
const collection = target.children
Object.values(collection).forEach((child, index) => {
child.setAttribute('data-animate-preset', target.getAttribute('data-animate-preset') )
child.setAttribute('data-animate-duration', target.getAttribute('data-animate-duration') )
child.style.transitionDelay = Number(target.getAttribute('data-animate-delay')) + index * Number(target.getAttribute('data-animate-stagger-delay')) + 'ms'
child.classList.add('animate')
})
} else {
target.style.transitionDelay = target.getAttribute('data-animate-delay') + 'ms'
}
})
// Configure presets
const observer = new IntersectionObserver(callback)
targets = document.querySelectorAll('.animate')
targets.forEach(target => {
const preset = target.getAttribute('data-animate-preset')
if (preset === 'fade') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0 }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100 }))
} else if (preset === 'slide-left') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(-6em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0)' }))
} else if (preset === 'slide-right') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(6em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0px)' }))
} else if (preset === 'slide-up') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(-2em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
} else if (preset === 'slide-down') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(2em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
}
applyClasses(target, 'initial')
target.classList.add('transition-all')
target.style['transition-duration'] = target.getAttribute('data-animate-duration') + 'ms'
observer.observe(target)
})
})
})