revert
This commit is contained in:
parent
248868b1bd
commit
372984e55b
1
.prettierigonore
Normal file
1
.prettierigonore
Normal file
@ -0,0 +1 @@
|
|||||||
|
.nuxt
|
1
.prettierrc.json
Normal file
1
.prettierrc.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -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
44
assets/css/tailwind.css
Normal 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
41
components/About.vue
Normal 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
40
components/Heading.vue
Normal 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
85
components/Skills.vue
Normal 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>
|
@ -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
4833
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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
9
pages/index.vue
Normal 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
101
plugins/motion.js
Normal 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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user