Use fly-in animation

This commit is contained in:
JovannMC 2025-01-21 18:42:47 +03:00
parent 7649c8e014
commit fb7ec5e3b2
No known key found for this signature in database
7 changed files with 65 additions and 54 deletions

View File

@ -7,6 +7,38 @@
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
%sveltekit.head% %sveltekit.head%
<script>
// FIXME: flash of dark mode when using light mode
(function() {
// Apply theme before DOM is loaded
let theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
console.log(`Theme: ${theme || "default"}, prefers dark: ${prefersDark}`);
if (theme !== "light" && theme !== "dark") {
console.log("Invalid theme, setting to default");
if (!theme) {
console.log("First time visitor, setting theme");
// first time visitor
window.addEventListener("load", () => {
window.plausible("Theme set", {
props: { theme: prefersDark ? "dark" : "light" },
});
});
}
// invalid theme or first time visitor, set to default
theme = prefersDark ? "dark" : "light";
console.log(`Setting theme to ${theme}`);
localStorage.setItem("theme", theme);
}
console.log(`Applying theme: ${theme}`);
document.documentElement.classList.add(theme);
})();
</script>
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>

View File

@ -6,25 +6,6 @@ export const transition =
export const duration = 500; export const duration = 500;
interface FadeOptions {
delay?: number;
duration?: number;
easing?: (t: number) => number;
type?: "in" | "out";
}
export function fade(
node: HTMLElement,
{ delay = 0, duration = 400, easing = cubicOut, type = "in" }: FadeOptions = {}
): AnimationConfig {
return {
delay,
duration,
easing,
css: (t) => `opacity: ${type === "in" ? t : 1 - t};`,
};
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export function is_function(thing: unknown): thing is Function { export function is_function(thing: unknown): thing is Function {
return typeof thing === "function"; return typeof thing === "function";

View File

@ -1,8 +1,9 @@
<script lang="ts"> <script lang="ts">
import { duration, fade, transition } from "$lib/animation"; import { duration, transition } from "$lib/animation";
import { ChevronDown } from "lucide-svelte"; import { ChevronDown } from "lucide-svelte";
import { onMount } from "svelte"; import { onMount } from "svelte";
import { quintOut } from "svelte/easing"; import { quintOut } from "svelte/easing";
import { fade } from "svelte/transition";
type Props = { type Props = {
options: string[]; options: string[];

View File

@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { browser } from "$app/environment";
import { page } from "$app/stores"; import { page } from "$app/stores";
import { fly } from "svelte/transition";
import { duration } from "$lib/animation"; import { duration } from "$lib/animation";
import clsx from "clsx";
import { onMount, tick } from "svelte";
import { quintOut } from "svelte/easing"; import { quintOut } from "svelte/easing";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import clsx from "clsx"; import { fly } from "svelte/transition";
import { browser } from "$app/environment";
import { onMount, tick } from "svelte";
interface Props { interface Props {
links: { links: {

View File

@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import { browser } from "$app/environment"; import { browser } from "$app/environment";
import { page } from "$app/stores"; import { page } from "$app/stores";
import { duration, fade } from "$lib/animation"; import { duration } from "$lib/animation";
import { setTheme } from "$lib/store/index.svelte"; import { setTheme } from "$lib/store/index.svelte";
import clsx from "clsx"; import clsx from "clsx";
import { MoonIcon, SunIcon } from "lucide-svelte"; import { MoonIcon, SunIcon } from "lucide-svelte";
import { quintOut } from "svelte/easing"; import { quintOut } from "svelte/easing";
import { fade } from "svelte/transition";
import Panel from "../visual/Panel.svelte"; import Panel from "../visual/Panel.svelte";
import Logo from "../visual/svg/Logo.svelte"; import Logo from "../visual/svg/Logo.svelte";

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { beforeNavigate, goto } from "$app/navigation"; import { beforeNavigate, goto } from "$app/navigation";
import { PUB_HOSTNAME, PUB_PLAUSIBLE_URL } from "$env/static/public"; import { PUB_HOSTNAME, PUB_PLAUSIBLE_URL } from "$env/static/public";
import { duration, fade } from "$lib/animation"; import { duration } from "$lib/animation";
import featuredImage from "$lib/assets/VERT_Feature.webp"; import featuredImage from "$lib/assets/VERT_Feature.webp";
import Navbar from "$lib/components/functional/Navbar.svelte"; import Navbar from "$lib/components/functional/Navbar.svelte";
import Footer from "$lib/components/visual/Footer.svelte"; import Footer from "$lib/components/visual/Footer.svelte";
@ -20,6 +20,7 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { quintOut } from "svelte/easing"; import { quintOut } from "svelte/easing";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import { fade, fly } from "svelte/transition";
import "../app.scss"; import "../app.scss";
let { children, data } = $props(); let { children, data } = $props();
@ -111,35 +112,10 @@
src="{PUB_PLAUSIBLE_URL}/js/script.pageview-props.tagged-events.js" src="{PUB_PLAUSIBLE_URL}/js/script.pageview-props.tagged-events.js"
></script>{/if} ></script>{/if}
<script src="/coi-serviceworker.min.js"></script> <script src="/coi-serviceworker.min.js"></script>
<script type="module">
// Apply theme before DOM is loaded
let theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme !== "light" && theme !== "dark") {
if (!theme) {
// first time visitor
window.addEventListener("load", () => {
window.plausible("Theme set", {
props: { theme: prefersDark ? "dark" : "light" },
});
});
}
// invalid theme or first time visitor, set to default
theme = prefersDark ? "dark" : "light";
localStorage.setItem("theme", theme);
}
document.documentElement.classList.add(theme);
</script>
</svelte:head> </svelte:head>
<div class="flex flex-col min-h-screen h-full"> <div class="flex flex-col min-h-screen h-full">
<!-- FIXME: if user resizes between desktop/mobile, highlight of page disappears (only shows on original size) --> <!-- FIXME: if user resizes between desktop/mobile, highlight of page disappears (only shows on original size) -->
<!-- FIXME: if user has to scroll in a page, transitioning to a page that fits users viewport makes the elements jump after transition ends -->
<div> <div>
<!-- Mobile logo --> <!-- Mobile logo -->
@ -167,12 +143,31 @@
{#key data.pathname} {#key data.pathname}
<div <div
class="row-start-1 col-start-1" class="row-start-1 col-start-1"
transition:fade={{ in:fly={{
x: goingLeft ? -window.innerWidth : window.innerWidth,
duration,
easing: quintOut,
delay: 25,
}}
out:fly={{
x: goingLeft ? window.innerWidth : -window.innerWidth,
duration, duration,
easing: quintOut, easing: quintOut,
}} }}
> >
<div class="flex flex-col h-full pb-36 md:pb-0"> <div
class="flex flex-col h-full pb-36 md:pb-0"
in:fade={{
duration,
easing: quintOut,
delay: 100,
}}
out:fade={{
duration,
easing: quintOut,
delay: 200,
}}
>
{@render children()} {@render children()}
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { duration, fade } from "$lib/animation"; import { duration } from "$lib/animation";
import ConversionPanel from "$lib/components/functional/ConversionPanel.svelte"; import ConversionPanel from "$lib/components/functional/ConversionPanel.svelte";
import Dropdown from "$lib/components/functional/Dropdown.svelte"; import Dropdown from "$lib/components/functional/Dropdown.svelte";
import Uploader from "$lib/components/functional/Uploader.svelte"; import Uploader from "$lib/components/functional/Uploader.svelte";
@ -21,6 +21,7 @@
XIcon, XIcon,
} from "lucide-svelte"; } from "lucide-svelte";
import { quintOut } from "svelte/easing"; import { quintOut } from "svelte/easing";
import { fade } from "svelte/transition";
$effect(() => { $effect(() => {
if (files.files.length === 1 && files.files[0].blobUrl) { if (files.files.length === 1 && files.files[0].blobUrl) {