feat: snappier feel

- adds transitions on page load with starting-style
- change header's feel (unintentional but like iOS 26)
- change some colors about
This commit is contained in:
trafficlunar 2025-11-14 22:22:06 +00:00
parent e3d41cf239
commit 15dfd08c20
14 changed files with 246 additions and 178 deletions

View file

@ -19,4 +19,4 @@
});
</script>
<span class="font-mono">{age}</span>
<span class="font-mono mx-1">{age}</span>

View file

@ -2,41 +2,48 @@
const links = [
{ name: "home", url: "/" },
{ name: "status", url: "/status/" },
{ name: "uses", url: "/uses/" },
];
let pathname = $state("/");
let isTransitioning = $state(false);
let activeIndex = $derived(links.findIndex((link) => link.url === pathname));
// Astro.url.pathname did not work here presumably due to swup
const getPathname = () => {
pathname = window.location.pathname;
const newPath = window.location.pathname;
if (newPath !== pathname) {
isTransitioning = true;
pathname = newPath;
setTimeout(() => {
isTransitioning = false;
}, 150); // Half of 300ms transition
}
};
getPathname();
document.addEventListener("astro:page-load", getPathname);
</script>
<section class="!p-1.5 mb-8 w-fit">
<div class="relative grid grid-cols-3 gap-1.5">
<section class="p-1.5! mb-8 w-fit">
<div class="relative grid grid-cols-2 gap-1.5">
<!-- Animated background for active link -->
{#if activeIndex !== -1}
<div
class="absolute inset-0 bg-peach rounded w-[calc((100%/3)-0.25rem)] transition-transform duration-300 ease-out"
style="transform: translateX(calc({activeIndex * 100}% + {activeIndex * 0.375}rem));"
class="absolute inset-0 bg-peach rounded w-[calc((100%/2)-0.25rem)] pointer-events-none z-10 transition-all duration-300 ease-out"
style="transform: translateX(calc({activeIndex * 100}% + {activeIndex * 0.375}rem)) {isTransitioning ? 'scale(1.1)' : 'scale(1)'};"
></div>
{/if}
{#each links as item}
<!-- Div here to hide the hover background behind the animated background -->
<a
href={item.url}
class="z-10 w-full font-medium text-sm text-center px-4 py-1 rounded-sm transition-colors duration-200 {pathname === item.url
? '!text-base'
: 'hover:bg-surface0'}"
>
{item.name}
</a>
<div class="relative group">
<div class="absolute inset-0 rounded-sm opacity-0 group-hover:opacity-100 transition-opacity duration-200 bg-surface0/50 z-0"></div>
<a
href={item.url}
class="relative w-full font-medium text-sm text-center px-4 py-1 rounded-sm block {pathname === item.url ? 'text-base! z-20' : 'z-20'}"
>
{item.name}
</a>
</div>
{/each}
</div>
</section>

View file

@ -26,32 +26,36 @@
});
</script>
<a href={url} class="block relative h-24 group">
<div class="absolute size-full rounded-md bg-mantle border border-surface0 z-10"></div>
<div class="relative transition-all duration-300 delay-100 starting:opacity-0 starting:translate-y-4">
<div class="flex justify-center items-center absolute -top-2 right-2 z-0">
<div class="w-4 h-4 rounded-full {playing ? 'bg-green' : 'bg-red'}"></div>
<div class="w-4 h-4 rounded-full absolute animate-duration-2s animate-delay-2s {playing ? 'bg-green animate-ping' : 'bg-red'}"></div>
</div>
<div class="absolute p-2 flex gap-2 z-30 w-full">
<img src={image} alt="album cover" class="size-20 rounded-full animate-spin animate-duration-30s" />
<section class="p-2!">
<legend>last.fm</legend>
<div class="flex flex-col w-full min-w-0">
<h1 class="font-medium">{song}</h1>
<span class="text-xs">{artist}</span>
</div>
</div>
<a href={url} class="block relative h-24 group">
<div class="absolute p-2 flex gap-2 z-30 w-full">
<img src={image} alt="album cover" class="size-20 rounded-full animate-spin animate-duration-30s" />
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
viewBox="0 0 20 20"
class="absolute right-2 top-2 z-10 text-overlay1 transition-all group-hover:top-1.5 group-hover:right-1.5 group-hover:text-peach"
><path
fill="currentColor"
d="M6.25 4.5A1.75 1.75 0 0 0 4.5 6.25v7.5c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 0 0 1.75-1.75v-2a.75.75 0 0 1 1.5 0v2A3.25 3.25 0 0 1 13.75 17h-7.5A3.25 3.25 0 0 1 3 13.75v-7.5A3.25 3.25 0 0 1 6.25 3h2a.75.75 0 0 1 0 1.5zm4.25-.75a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0V5.56l-3.72 3.72a.75.75 0 1 1-1.06-1.06l3.72-3.72h-3.19a.75.75 0 0 1-.75-.75"
/></svg
>
</a>
<div class="flex flex-col w-full min-w-0">
<h1 class="font-medium text-lg">{song}</h1>
<span class="text-sm">{artist}</span>
</div>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
viewBox="0 0 20 20"
class="absolute right-1 top-1 z-10 text-overlay1 transition-all group-hover:top-0.5 group-hover:right-0.5 group-hover:text-peach"
><path
fill="currentColor"
d="M6.25 4.5A1.75 1.75 0 0 0 4.5 6.25v7.5c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 0 0 1.75-1.75v-2a.75.75 0 0 1 1.5 0v2A3.25 3.25 0 0 1 13.75 17h-7.5A3.25 3.25 0 0 1 3 13.75v-7.5A3.25 3.25 0 0 1 6.25 3h2a.75.75 0 0 1 0 1.5zm4.25-.75a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0V5.56l-3.72 3.72a.75.75 0 1 1-1.06-1.06l3.72-3.72h-3.19a.75.75 0 0 1-.75-.75"
/></svg
>
</a>
</section>
</div>

View file

@ -15,7 +15,7 @@
</script>
<div class="group relative hover:-translate-y-1 transition-transform duration-200">
<section class="h-full !p-0 flex flex-col transition-colors group-hover:!border-peach/50">
<section class="h-full p-0! flex flex-col transition-colors group-hover:border-peach/50!">
{#if year}
<span class="absolute top-2 left-2 bg-peach text-base px-2 py-1 rounded-full text-xs font-medium z-10 shadow-md">{year}</span>
{/if}
@ -24,7 +24,7 @@
{#if image}
<div class="relative overflow-hidden">
<img src={image} alt="thumbnail" class="rounded-t-lg object-cover aspect-video w-full" />
<div class="absolute inset-0 bg-gradient-to-t from-mantle/90 via-mantle/30 to-transparent"></div>
<div class="absolute inset-0 bg-linear-to-t from-mantle/90 via-mantle/30 to-transparent"></div>
</div>
{/if}
@ -52,7 +52,7 @@
<!-- Buttons -->
<hr class="border-surface0 my-4" />
<div class="grid grid-cols-2 gap-2 {!websiteUrl && '!grid-cols-1'}">
<div class="grid grid-cols-2 gap-2 {!websiteUrl && 'grid-cols-1!'}">
<a
href={sourceUrl}
class="bg-surface0/50 border border-surface1/50 text-subtext1 font-medium p-2 rounded-md flex justify-center items-center gap-2 text-sm"

View file

@ -133,7 +133,7 @@
</div>
{/snippet}
<div class="grid grid-cols-2 gap-4 max-sm:grid-cols-1">
<div class="grid grid-cols-2 gap-4 max-sm:grid-cols-1 transition-all duration-300 delay-300 starting:opacity-0 starting:translate-y-4">
{@render projectColumn(leftColumn)}
{@render projectColumn(rightColumn)}
</div>

View file

@ -9,7 +9,7 @@ import LastFMIcon from "../assets/icons/socials/lastfm.svg";
import MailIcon from "../assets/icons/socials/mail.svg";
---
<section class="side !p-2">
<section class="side p-2!">
<legend>socials</legend>
<ul class="grid grid-cols-4 [&_a]:flex [&_a]:justify-center [&_a]:size-full [&_a]:py-1">
<!-- z-50 for tooltips -->

View file

@ -16,17 +16,19 @@ import DockerIcon from "../assets/icons/coding/docker.svg";
import LinuxIcon from "../assets/icons/coding/linux.svg";
---
<section class="!mb-0">
<section class="mb-0! transition-all duration-300 delay-200 starting:opacity-0 starting:translate-y-4">
<legend>tools</legend>
<!-- separator -->
<div class="flex items-center gap-2 text-overlay2 text-sm font-medium mb-2">
<hr class="w-4 border-surface1" />
<div class="flex items-center gap-2 text-overlay1 text-sm font-medium mb-2">
<hr class="w-4 border-surface0" />
<span>editors</span>
<hr class="flex-grow border-surface1" />
<hr class="grow border-surface0" />
</div>
<div class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:border *:border-surface1 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5">
<div
class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:shadow *:border *:border-surface1/50 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5"
>
<div>
<VSCodiumIcon class="size-5" />
<span>VSCodium</span>
@ -38,13 +40,15 @@ import LinuxIcon from "../assets/icons/coding/linux.svg";
</div>
<!-- separator -->
<div class="flex items-center gap-2 text-overlay2 text-sm font-medium my-2">
<hr class="w-4 border-surface1" />
<div class="flex items-center gap-2 text-overlay1 text-sm font-medium my-2">
<hr class="w-4 border-surface0" />
<span>languages</span>
<hr class="flex-grow border-surface1" />
<hr class="grow border-surface0" />
</div>
<div class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:border *:border-surface1 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5">
<div
class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:shadow *:border *:border-surface1/50 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5"
>
<div>
<TypeScriptIcon class="size-5" />
<span>TypeScript</span>
@ -68,13 +72,15 @@ import LinuxIcon from "../assets/icons/coding/linux.svg";
</div>
<!-- separator -->
<div class="flex items-center gap-2 text-overlay2 text-sm font-medium my-2">
<hr class="w-4 border-surface1" />
<div class="flex items-center gap-2 text-overlay1 text-sm font-medium my-2">
<hr class="w-4 border-surface0" />
<span>frameworks</span>
<hr class="flex-grow border-surface1" />
<hr class="grow border-surface0" />
</div>
<div class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:border *:border-surface1 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5">
<div
class="flex flex-wrap gap-1 mb-4 *:bg-surface0/50 *:shadow *:border *:border-surface1/50 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5"
>
<div>
<SvelteIcon class="size-5" />
<span>Svelte</span>
@ -98,12 +104,12 @@ import LinuxIcon from "../assets/icons/coding/linux.svg";
</div>
<!-- separator -->
<div class="flex flex-wrap items-center gap-2 text-overlay2 text-sm font-medium my-2">
<hr class="w-4 border-surface1" />
<div class="flex flex-wrap items-center gap-2 text-overlay1 text-sm font-medium my-2">
<hr class="w-4 border-surface0" />
<span>infrastructure</span>
<hr class="flex-grow border-surface1" />
<hr class="grow border-surface0" />
</div>
<div class="flex gap-1 *:bg-surface0/50 *:border *:border-surface1 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5">
<div class="flex gap-1 *:bg-surface0/50 *:shadow *:border *:border-surface1/50 *:rounded-md *:p-1.5 *:text-sm *:flex *:items-center *:gap-1.5">
<div>
<PostgresIcon class="size-5" />
<span>PostgreSQL</span>

View file

@ -55,7 +55,7 @@ import Lunar from "../assets/lunar.svg";
</div>
</div>
<div class="min-sm:col-span-4 flex flex-col relative">
<div class="sm:col-span-4 flex flex-col relative">
<TrafficConeAlt class="absolute size-12 bottom-full left-16 text-peach" />
<TrafficConeAlt class="absolute size-14 bottom-full left-27 text-peach" />

View file

@ -10,7 +10,7 @@ import LocationIcon from "../assets/icons/location.svg";
---
<Layout>
<section>
<section class="transition-all duration-300 delay-100 starting:opacity-0 starting:translate-y-4">
<legend>about</legend>
<p>
Hey! I'm <strong class="text-peach">trafficlunar</strong>. I'm a <Age client:only /> year old self-proclaimed full-stack developer.
@ -31,11 +31,13 @@ import LocationIcon from "../assets/icons/location.svg";
<Tools />
<div class="flex items-center gap-4 text-subtext0 text-sm font-medium my-4">
<hr class="flex-grow border-surface1" />
<div
class="flex items-center gap-4 text-subtext0 text-sm font-medium my-4 transition-all duration-300 delay-250 starting:opacity-0 starting:translate-y-4"
>
<hr class="grow border-surface1" />
<span>projects</span>
<hr class="flex-grow border-surface1" />
<hr class="grow border-surface1" />
</div>
<Projects client:only />
<Projects client:load />
</Layout>

View file

@ -6,21 +6,11 @@ import Computer from "../components/Computer.svelte";
---
<Layout>
<section class="!mb-0 !pt-3">
<legend>status</legend>
<Music client:load />
<div class="flex items-center gap-4 text-subtext0 text-sm font-medium mb-4">
<hr class="flex-grow border-surface1" />
<span>last.fm</span>
<hr class="flex-grow border-surface1" />
</div>
<Music client:only />
<section class="pt-0! transition-all duration-300 delay-200 starting:opacity-0 starting:translate-y-4">
<legend>computer</legend>
<div class="flex items-center gap-4 text-subtext0 text-sm font-medium mt-4">
<hr class="flex-grow border-surface1" />
<span>computer</span>
<hr class="flex-grow border-surface1" />
</div>
<Computer client:only />
<Computer client:load />
</section>
</Layout>

View file

@ -1,11 +0,0 @@
---
import Layout from "../layouts/Layout.astro";
---
<Layout>
<section>
<legend>uses</legend>
<p>Coming soon...</p>
</section>
</Layout>