transitions and buttons
This commit is contained in:
24
app/app.vue
24
app/app.vue
@@ -3,3 +3,27 @@
|
|||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.page-enter-active,
|
||||||
|
.page-leave-active {
|
||||||
|
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
.page-enter-from,
|
||||||
|
.page-leave-to {
|
||||||
|
scale: 0;
|
||||||
|
opacity: 0;
|
||||||
|
filter: blur(10rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-enter-active,
|
||||||
|
.layout-leave-active {
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
.layout-enter-from,
|
||||||
|
.layout-leave-to {
|
||||||
|
scale: 0;
|
||||||
|
opacity: 0;
|
||||||
|
filter: blur(10rem);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,5 +3,5 @@
|
|||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
font-family: Roboto, sans-serif;
|
font-family: Share Tech Mono, sans-serif;
|
||||||
}
|
}
|
||||||
23
app/components/ButtonLink.vue
Normal file
23
app/components/ButtonLink.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { to, text, icon = undefined, color = undefined } = defineProps<{
|
||||||
|
to: string,
|
||||||
|
text: string,
|
||||||
|
icon?: string
|
||||||
|
color?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const buttonClass = ref(`btn btn-outline ${color ? color : "btn-primary"}`)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button :class="buttonClass">
|
||||||
|
<NuxtLink :to="to" class=" flex flex-row items-center justify-center gap-2">
|
||||||
|
<Icon v-if="icon" :name="icon" class="w-6 h-6" />
|
||||||
|
{{ text }}
|
||||||
|
</NuxtLink>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -4,6 +4,7 @@ import {motion, frame} from "motion-v";
|
|||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
img = undefined,
|
img = undefined,
|
||||||
|
link = '/',
|
||||||
color = 'bg-white',
|
color = 'bg-white',
|
||||||
textTop = false,
|
textTop = false,
|
||||||
moveFactor = undefined,
|
moveFactor = undefined,
|
||||||
@@ -12,8 +13,10 @@ const {
|
|||||||
initialHeight = undefined,
|
initialHeight = undefined,
|
||||||
topTextOffset = undefined,
|
topTextOffset = undefined,
|
||||||
bottomTextOffset = undefined,
|
bottomTextOffset = undefined,
|
||||||
|
textSize = undefined,
|
||||||
} = defineProps<{
|
} = defineProps<{
|
||||||
name: string,
|
name: string,
|
||||||
|
link?: string,
|
||||||
img?: string,
|
img?: string,
|
||||||
color?: string,
|
color?: string,
|
||||||
textTop?: boolean,
|
textTop?: boolean,
|
||||||
@@ -23,6 +26,7 @@ const {
|
|||||||
initialHeight?: string,
|
initialHeight?: string,
|
||||||
topTextOffset?: string,
|
topTextOffset?: string,
|
||||||
bottomTextOffset?: string,
|
bottomTextOffset?: string,
|
||||||
|
textSize?: string,
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['positionChanged'])
|
const emit = defineEmits(['positionChanged'])
|
||||||
@@ -31,8 +35,8 @@ const isHoveringParent = ref(false)
|
|||||||
|
|
||||||
const imageMaskClass = `avatar mask mask-squircle ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
|
const imageMaskClass = `avatar mask mask-squircle ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
|
||||||
const roundedDivClass = `rounded-full absolute ${color} ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
|
const roundedDivClass = `rounded-full absolute ${color} ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
|
||||||
const topTextClass = `absolute w-full text-center ${topTextOffset ? topTextOffset : '-top-30'}`
|
const topTextClass = `absolute w-full text-center ${textSize ? textSize : 'text-2xl'} ${topTextOffset ? topTextOffset : '-top-30'}`
|
||||||
const bottomTextClass = `absolute w-full text-center ${bottomTextOffset ? bottomTextOffset : '-bottom-30'}`
|
const bottomTextClass = `absolute w-full text-center ${textSize ? textSize : 'text-2xl'} ${bottomTextOffset ? bottomTextOffset : '-bottom-30'}`
|
||||||
|
|
||||||
function getRandomArbitrary(min: number, max: number): number {
|
function getRandomArbitrary(min: number, max: number): number {
|
||||||
return Math.random() * (max - min) + min;
|
return Math.random() * (max - min) + min;
|
||||||
@@ -88,14 +92,18 @@ onUnmounted(() => {
|
|||||||
:while-hover="{ scale: scaleFactor }"
|
:while-hover="{ scale: scaleFactor }"
|
||||||
@hover-start="event => {isHoveringParent=true}"
|
@hover-start="event => {isHoveringParent=true}"
|
||||||
@hover-end="event => {isHoveringParent=false}">
|
@hover-end="event => {isHoveringParent=false}">
|
||||||
|
<NuxtLink :to="link">
|
||||||
<NuxtImg :src="img"/>
|
<NuxtImg :src="img"/>
|
||||||
|
</NuxtLink>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
<motion.div
|
<motion.div
|
||||||
v-else
|
v-else
|
||||||
:class="roundedDivClass"
|
:class="roundedDivClass"
|
||||||
:while-hover="{ scale: scaleFactor }"
|
:while-hover="{ scale: scaleFactor }"
|
||||||
@hover-start="event => {isHoveringParent=true}"
|
@hover-start="event => {isHoveringParent=true}"
|
||||||
@hover-end="event => {isHoveringParent=false}"/>
|
@hover-end="event => {isHoveringParent=false}">
|
||||||
|
<NuxtLink :to="link"/>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
<motion.p
|
<motion.p
|
||||||
|
|||||||
@@ -2,16 +2,18 @@
|
|||||||
|
|
||||||
const nodes = [
|
const nodes = [
|
||||||
{
|
{
|
||||||
name: "Hi, I'm Alex",
|
name: "👋 Hi, I'm Alex",
|
||||||
img: "/face.jpg",
|
img: "/face.jpg",
|
||||||
|
link: "/who-am-i",
|
||||||
textTop: true,
|
textTop: true,
|
||||||
moveFactor: 6,
|
moveFactor: 6,
|
||||||
initialWidth: 'w-50',
|
initialWidth: 'w-50',
|
||||||
initialHeight: 'h-50',
|
initialHeight: 'h-50',
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
hOffset: 'left-1/3',
|
hOffset: 'left-1/3',
|
||||||
vOffset: 'top-1/3',
|
vOffset: 'top-1/4',
|
||||||
topTextOffset: '-top-50',
|
topTextOffset: '-top-50',
|
||||||
|
textSize: 'text-3xl'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "DevOps engineer",
|
name: "DevOps engineer",
|
||||||
@@ -77,7 +79,7 @@ useRafFn(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="hero bg-base-200 min-h-screen">
|
<div class="hero min-h-screen">
|
||||||
<div class="overflow-hidden">
|
<div class="overflow-hidden">
|
||||||
<ul v-for="(line, index) in linesLocations" :key="index">
|
<ul v-for="(line, index) in linesLocations" :key="index">
|
||||||
<li>
|
<li>
|
||||||
@@ -86,7 +88,7 @@ useRafFn(() => {
|
|||||||
:x1="line.x1"
|
:x1="line.x1"
|
||||||
:y1="line.y1"
|
:y1="line.y1"
|
||||||
:x2="line.x2"
|
:x2="line.x2"
|
||||||
:y2="line.y2" stroke="white"/>
|
:y2="line.y2" stroke=" color-mix(in oklab, var(--color-primary-content)50%, transparent)"/>
|
||||||
</svg>
|
</svg>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -95,6 +97,7 @@ useRafFn(() => {
|
|||||||
<li>
|
<li>
|
||||||
<GraphNode
|
<GraphNode
|
||||||
:name="node.name"
|
:name="node.name"
|
||||||
|
:link="node.link"
|
||||||
:img="node.img"
|
:img="node.img"
|
||||||
:color="node.color"
|
:color="node.color"
|
||||||
:class="`${node.hOffset ? node.hOffset : ''} ${node.vOffset ? node.vOffset : ''}`"
|
:class="`${node.hOffset ? node.hOffset : ''} ${node.vOffset ? node.vOffset : ''}`"
|
||||||
@@ -105,6 +108,7 @@ useRafFn(() => {
|
|||||||
:initial-height="node.initialHeight"
|
:initial-height="node.initialHeight"
|
||||||
:top-text-offset="node.topTextOffset"
|
:top-text-offset="node.topTextOffset"
|
||||||
:bottom-text-offset="node.bottomTextOffset"
|
:bottom-text-offset="node.bottomTextOffset"
|
||||||
|
:text-size="node.textSize"
|
||||||
@position-changed="(x, y) => { nodeMoved(index, x, y) }"/>
|
@position-changed="(x, y) => { nodeMoved(index, x, y) }"/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="flex justify-center items-center p-8 max-w-4/5 mx-auto">
|
||||||
<slot/>
|
<slot/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
6
app/layouts/graph.vue
Normal file
6
app/layouts/graph.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
9
app/middleware/disable-vue-transitions.global.ts
Normal file
9
app/middleware/disable-vue-transitions.global.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default defineNuxtRouteMiddleware((to) => {
|
||||||
|
if (import.meta.server || !document.startViewTransition) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable built-in Vue transitions
|
||||||
|
// to.meta.pageTransition = false
|
||||||
|
// to.meta.layoutTransition = false
|
||||||
|
})
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'graph',
|
||||||
|
})
|
||||||
|
|
||||||
defineOgImageComponent('Default', {
|
defineOgImageComponent('Default', {
|
||||||
title: 'Portfolio',
|
title: 'Portfolio',
|
||||||
borderColor: 'green-300',
|
borderColor: 'green-300',
|
||||||
|
|||||||
43
app/pages/who-am-i.vue
Normal file
43
app/pages/who-am-i.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import ButtonLink from "~/components/ButtonLink.vue";
|
||||||
|
|
||||||
|
const img = ref('/face.jpg')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2 items-center justify-center w-full">
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="mask mask-squircle">
|
||||||
|
<NuxtImg :src="img" width="512" height="512"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 class="text-7xl pt-20">👋 Hi, I'm Alex</h1>
|
||||||
|
<div class="flex flex-row gap-2">
|
||||||
|
<ButtonLink to="https://github.com/Minimata" text="Github" icon="uil:github" />
|
||||||
|
<ButtonLink to="https://bsky.app/profile/game-dev.space" text="Bluesky" icon="ri:bluesky-fill" color="btn-secondary" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="pt-10 text-3xl flex flex-row items-center justify-center leading-[2] italic">
|
||||||
|
⭐I code
|
||||||
|
<span class="text-rotate px-2">
|
||||||
|
<span class="justify-items-center">
|
||||||
|
<span><span class="not-italic">🎮</span>Game</span>
|
||||||
|
<span><span class="not-italic">🌎</span>Web</span>
|
||||||
|
<span><span class="not-italic">🐍</span>Python </span>
|
||||||
|
<span><span class="not-italic">⌨️</span>DevOps </span>
|
||||||
|
<span><span class="not-italic">⛏️</span>Tools </span>
|
||||||
|
<span><span class="not-italic">💻</span>Qt </span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span>stuff⭐</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="divider">🎮Game stuff</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -16,6 +16,12 @@ export default defineNuxtConfig({
|
|||||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pageTransition: { name: 'page', mode: 'out-in' },
|
||||||
|
layoutTransition: { name: 'layout', mode: 'out-in' },
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
viewTransition: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
site: {
|
site: {
|
||||||
|
|||||||
Reference in New Issue
Block a user