feat: better page transitions

This commit is contained in:
not-nullptr 2024-11-12 16:59:56 +00:00
parent 06353b5ae3
commit 11d3a6abd9
4 changed files with 164 additions and 43 deletions

View File

@ -18,6 +18,7 @@
--fg-muted: hsl(0, 0%, 50%); --fg-muted: hsl(0, 0%, 50%);
--fg-muted-alt: hsl(0, 0%, 75%); --fg-muted-alt: hsl(0, 0%, 75%);
--fg-failure: hsl(0, 67%, 49%); --fg-failure: hsl(0, 67%, 49%);
--transition: linear(0, 0.006, 0.025 2.8%, 0.101 6.1%, 0.539 18.9%, 0.721 25.3%, 0.849 31.5%, 0.937 38.1%, 0.968 41.8%, 0.991 45.7%, 1.006 50.1%, 1.015 55%, 1.017 63.9%, 1.001);
} }
body { body {

View File

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { transition } from "$lib/animation";
import Uploader from "$lib/components/functional/Uploader.svelte"; import Uploader from "$lib/components/functional/Uploader.svelte";
import { converters } from "$lib/converters"; import { converters } from "$lib/converters";
import { files } from "$lib/store/index.svelte"; import { files } from "$lib/store/index.svelte";
@ -95,19 +96,24 @@
</li> </li>
{/snippet} {/snippet}
<div class="[@media(max-height:768px)]:block mt-10"> <div class="[@media(max-height:768px)]:block mt-10 picker-fly">
<Uploader bind:files={ourFiles} onupload={runUpload} /> <Uploader bind:files={ourFiles} onupload={runUpload} />
</div> </div>
<div class="text-center mt-20"> <div class="text-center mt-20">
<h1 class="text-3xl font-display"> <h1 class="text-3xl font-display header-fly-in">
Free, fast, and awesome file converting Free, fast, and awesome file converting
</h1> </h1>
<div class="flex justify-center mt-10"> <div class="flex justify-center mt-10">
<div class="grid gap-4"> <div class="grid gap-4">
{@render sellingPoint("Very fast, all processing done on device")} <!-- {@render sellingPoint("Very fast, all processing done on device")}
{@render sellingPoint("No ads, and open source")} {@render sellingPoint("No ads, and open source")}
{@render sellingPoint("Beautiful and straightforward UI")} {@render sellingPoint("Beautiful and straightforward UI")} -->
{#each ["Very fast, all processing done on device", "No ads, and open source", "Beautiful and straightforward UI"] as text, i}
<div class="fly-in" style="--delay: {i * 50}ms;">
{@render sellingPoint(text)}
</div>
{/each}
</div> </div>
</div> </div>
</div> </div>
@ -117,4 +123,58 @@
:global(html, body) { :global(html, body) {
height: 100%; height: 100%;
} }
@keyframes fly-in {
from {
opacity: 0;
transform: translateY(50px);
filter: blur(18px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
@keyframes picker-fly {
from {
opacity: 0;
transform: translateY(48px);
filter: blur(18px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
@keyframes header-fly-in {
from {
opacity: 0;
transform: translateY(30px) scale(0.9);
filter: blur(18px);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
filter: blur(0);
}
}
.header-fly-in {
animation: header-fly-in var(--transition) 750ms forwards;
opacity: 0;
}
.fly-in {
animation: fly-in var(--transition) 750ms var(--delay) forwards;
opacity: 0;
}
.picker-fly {
animation: picker-fly var(--transition) 750ms forwards;
opacity: 0;
}
</style> </style>

View File

@ -1,57 +1,82 @@
<script lang="ts"> <script lang="ts">
import avatarNullptr from "$lib/assets/avatars/nullptr.jpg"; import avatarNullptr from "$lib/assets/avatars/nullptr.jpg";
import avatarRealmy from "$lib/assets/avatars/realmy.jpg"; import avatarRealmy from "$lib/assets/avatars/realmy.jpg";
const multiplier = 50;
const credits = [
{
name: "nullptr",
avatar: avatarNullptr,
url: "https://nullp.tr",
description: "car mrrow 🐱🐱🐱",
},
{
name: "Realmy",
avatar: avatarRealmy,
url: "https://realmy.net",
description: "scayr dragon 😱 (grrr)",
},
];
</script> </script>
<div class="text-lg mx-auto max-w-screen-md"> <div class="text-lg mx-auto max-w-screen-md">
<h1 class="font-display text-3xl">⁉️ about VERT</h1> <h1
<p class="mt-6"> class="font-display text-3xl text-transition"
style="--delay: {0 * multiplier}ms"
>
⁉️ about VERT
</h1>
<p class="mt-6 text-transition" style="--delay: {1 * multiplier}ms">
You know what sucks? File converters! They're usually riddled with ads, You know what sucks? File converters! They're usually riddled with ads,
and take an ungodly amount of time to complete. <b and take an ungodly amount of time to complete. <b
>So we made a better one!</b >So we made a better one!</b
> >
</p> </p>
<p class="mt-4"> <p class="mt-4 text-transition" style="--delay: {2 * multiplier}ms">
VERT is a file converter that's open source, completely ad free, and VERT is a file converter that's open source, completely ad free, and
much much faster than you're used to. All the converting is done on your much much faster than you're used to. All the converting is done on your
device, which makes it both private and very speedy. And it of course device, which makes it both private and very speedy. And it of course
has a beautiful UI! ✨ has a beautiful UI! ✨
</p> </p>
<h2 class="font-display text-3xl mt-12">🖼️ supported formats</h2> <h2
<p class="mt-6"> class="font-display text-3xl mt-12 text-transition"
style="--delay: {3 * multiplier}ms"
>
🖼️ supported formats
</h2>
<p class="mt-6 text-transition" style="--delay: {4 * multiplier}ms">
As of right now, VERT only supports image conversion of most popular As of right now, VERT only supports image conversion of most popular
formats. Don't worry though, as we'll add support for more formats in formats. Don't worry though, as we'll add support for more formats in
the future! the future!
</p> </p>
<h2 class="font-display text-3xl mt-12">🎨 credits</h2> <h2
class="font-display text-3xl mt-12 text-transition"
style="--delay: {5 * multiplier}ms"
>
🎨 credits
</h2>
<div class="flex gap-4 mt-8"> <div class="flex gap-4 mt-8">
<a {#each credits as credit, i}
class="w-48 border-2 border-solid border-foreground-muted-alt rounded-2xl overflow-hidden transition-all hover:scale-105" <div class="hover:scale-105 w-48 transition-transform">
href="https://nullp.tr" <div
> class="border-2 credit-transition border-solid border-foreground-muted-alt rounded-2xl overflow-hidden"
<img src={avatarNullptr} alt="nullptr's cat avatar" /> style="--delay: {i * 50 + multiplier * 5}ms;"
<div class="text-center py-4 px-2"> >
<p class="font-display text-xl">nullptr</p> <a class="w-48" href={credit.url} target="_blank">
<p class="text-sm text-foreground-muted mt-2"> <img src={credit.avatar} alt="{credit.name}'s avatar" />
car mrrow 🐱🐱🐱 <div class="text-center py-4 px-2">
</p> <p class="font-display text-xl">{credit.name}</p>
<p class="text-sm text-foreground-muted mt-2">
{credit.description}
</p>
</div>
</a>
</div>
</div> </div>
</a> {/each}
<a
class="w-48 border-2 border-solid border-foreground-muted-alt rounded-2xl overflow-hidden transition-all hover:scale-105"
href="https://realmy.net"
>
<img src={avatarRealmy} alt="nullptr's cat avatar" />
<div class="text-center py-4 px-2">
<p class="font-display text-xl">Realmy</p>
<p class="text-sm text-foreground-muted mt-2">
scayr dragon 😱 (grrr)
</p>
</div>
</a>
</div> </div>
<p class="text-foreground-muted text-base mt-10"> <p class="text-foreground-muted text-base mt-10">
@ -61,3 +86,42 @@
>) >)
</p> </p>
</div> </div>
<style>
@keyframes credit-transition {
from {
opacity: 0;
transform: translateX(60px);
filter: blur(18px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
@keyframes text-transition {
from {
opacity: 0;
transform: translateY(60px);
filter: blur(18px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
.credit-transition {
animation: credit-transition 750ms var(--transition) var(--delay)
forwards;
opacity: 0;
}
.text-transition {
animation: text-transition 750ms var(--transition) var(--delay) forwards;
opacity: 0;
}
</style>

View File

@ -24,7 +24,7 @@
onMount(() => { onMount(() => {
finisheds.forEach((_, i) => { finisheds.forEach((_, i) => {
const duration = 750 + i * 50 - 32; const duration = 575 + i * 50 - 32;
setTimeout(() => { setTimeout(() => {
finisheds[i] = true; finisheds[i] = true;
console.log(`finished ${i}`); console.log(`finished ${i}`);
@ -240,7 +240,6 @@
easing: quintOut, easing: quintOut,
blurMultiplier: 16, blurMultiplier: 16,
}} }}
style="--transition: ease-in-out;"
> >
<div <div
class={clsx( class={clsx(
@ -249,9 +248,8 @@
"initial-fade": !finisheds[i], "initial-fade": !finisheds[i],
}, },
)} )}
style="--delay: {i * style="--delay: {i * 50}ms; z-index: {files.files
50}ms; --transition: {transition}; --duration: {duration}ms; z-index: {files .length - i}; border: solid 3px {file.result
.files.length - i}; border: solid 3px {file.result
? 'var(--accent-bg)' ? 'var(--accent-bg)'
: 'var(--fg-muted-alt)'}; transition: border 1000ms ease;" : 'var(--fg-muted-alt)'}; transition: border 1000ms ease;"
> >
@ -382,8 +380,7 @@
} }
.initial-fade { .initial-fade {
animation: initial-transition 750ms var(--delay) ease-out; animation: initial-transition 600ms var(--delay) var(--transition);
animation-timing-function: var(--transition);
opacity: 0; opacity: 0;
} }
@ -393,7 +390,6 @@
} }
.finished-anim { .finished-anim {
animation: finished-animation 750ms; animation: finished-animation 750ms var(--transition);
animation-timing-function: var(--transition);
} }
</style> </style>