fix cv animations

This commit is contained in:
2026-06-18 01:41:25 +02:00
parent 3e5be46503
commit 0d79adb104
15 changed files with 606 additions and 724 deletions

View File

@@ -1,4 +1,3 @@
'use client'
import CvEntry from "./CvEntry"
import type { RouterOutputs } from "~/server/routers/_app"
import { cn } from "~/lib/utils"
@@ -20,7 +19,7 @@ export default function CvCategory({ category, layout, position = 0 }: CvCategor
return (
<AnimatedCard position={position} className={cn(layout == "row" ? "w-full" : "", "h-screen")}>
<CardHeader>
<AnimateTextIn position={position + 0.2} animation="slide">
<AnimateTextIn once position={position + 0.2} animation="slide" debugId={`cv-category-title:${category.name}:${position + 0.2}`}>
<CardTitle>{category.name}</CardTitle>
</AnimateTextIn>
</CardHeader>
@@ -28,7 +27,7 @@ export default function CvCategory({ category, layout, position = 0 }: CvCategor
<CardContent className={cn(layout == "row" ? "flex flex-row flex-wrap justify-center lg:justify-between" : "flex flex-col", "gap-4", "overflow-scroll")}>
<ScrollArea>
{entries.map((entry, i) => (
<AnimatePopUp position={position + 0.4 + i * 0.2} key={entry.id}>
<AnimatePopUp position={position + 0.4 + i * 0.2} debugId={`cv-entry-wrapper:${category.name}:${entry.title}:${position + 0.4 + i * 0.2}`} key={entry.id}>
<CvEntry position={position + 0.4 + i * 0.2} entry={entry} className={layout == "row" ? "w-full lg:w-fit" : undefined} />
</AnimatePopUp>
))}

View File

@@ -4,6 +4,7 @@ import { format } from 'date-fns'
import type { ArrayElement } from "type-fest"
import AnimateTextIn from "~/app/_components/Animated/AnimateIn"
import AnimatePopUp from "~/app/_components/Animated/AnimatePopUp"
import { MDXRemote } from "next-mdx-remote/rsc";
import type { CvCategoryData } from "./CvCategory"
import { ClientMdx } from "~/components/ClientMdx"
@@ -18,7 +19,7 @@ export default function CvEntry({ entry, className, position = 0 }: {
<Card className={className ? cn("w-fit", className) : "w-fit"}>
{entry.title ?
<CardHeader>
<AnimateTextIn position={position} animation="slide">
<AnimateTextIn position={position} animation="slide" debugId={`cv-entry-title:${entry.title}:${position}`}>
<CardTitle> {entry.title} </CardTitle>
</AnimateTextIn>
</CardHeader> :
@@ -26,7 +27,7 @@ export default function CvEntry({ entry, className, position = 0 }: {
}
{entry.description ?
<CardContent className="text-sm lg:text-base">
<AnimatePopUp position={position + 0.2}>
<AnimatePopUp once position={position + 0.2} debugId={`cv-entry-description:${entry.title}:${position + 0.2}`}>
<article className="prose prose-zinc dark:prose-invert max-w-none">
<ClientMdx source={entry.description} fallback={entry.description} />
</article>
@@ -36,7 +37,7 @@ export default function CvEntry({ entry, className, position = 0 }: {
}
{!entry.hideDates ?
<CardFooter className="text-sm">
<AnimateTextIn position={position + 0.4}>
<AnimateTextIn position={position + 0.4} debugId={`cv-entry-dates:${entry.title}:${position + 0.4}`}>
{`von ${format(new Date(entry.fromTime), 'M. yyyy')} bis zum ${format(new Date(entry.toTime), 'M. yyyy')}`}
</AnimateTextIn>
</CardFooter> :

View File

@@ -0,0 +1,54 @@
'use client'
import { Sidebar, SidebarContent, SidebarProvider } from "~/components/ui/sidebar";
import type { RouterOutputs } from "~/server/routers/_app"
import SidebarTriggerDisappearsOnMobile from "./SidebarTriggerDisappearsOnMobile";
import CvCategory from "./CvCategory";
import { useTimeLine } from "~/app/_providers/GsapProvicer";
export default function CvPage(props: { cv: RouterOutputs['categoryv2']['listAllWithEntries'] }) {
useTimeLine(props.cv)
const byPosition = (pos: "sidebar" | "header" | "col1" | "col2") =>
props.cv?.filter((c) => c.layoutPosition === pos) ?? []
const sidebarCategories = byPosition("sidebar")
const headerCategories = byPosition("header")
const col1Categories = byPosition("col1")
const col2Categories = byPosition("col2")
return (
<>
<SidebarProvider>
{sidebarCategories.length > 0 &&
<>
<SidebarTriggerDisappearsOnMobile />
<Sidebar>
<SidebarContent className="p-2 lg:pt-[3.2rem]">
{sidebarCategories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</SidebarContent>
</Sidebar>
</>
}
<div className="h-full w-full flex flex-wrap flex-row p-4 pt-8 ">
<div id="mainwrap" className="flex w-full flex-col gap-4 lg:px-[15vw]">
<div id="header" className="flex w-full h-fit flex-row gap-4 flex-wrap">
{headerCategories.map((cat, i) => (
<CvCategory layout="row" position={i} category={cat} key={cat.id} />
))}
</div>
<div id="colwrapper" className="flex flex-col lg:flex-row w-full h-3/4 gap-4">
<div id="col1" className={`flex flex-col w-full ${col1Categories.length > 0 ? "lg:w-1/2" : ""} h-full gap-4`}>
{col1Categories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</div>
<div id="col2" className={`flex flex-col w-full ${col2Categories.length > 0 ? "lg:w-1/2" : ""} h-full gap-4`}>
{col2Categories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</div>
</div>
</div>
</div>
</SidebarProvider>
</>
)
}

View File

@@ -1,55 +1,11 @@
'use client'
import { useTimeLine } from "../_providers/GsapProvicer";
import { trpc } from "../_trpc/Client";
import { SidebarContent, SidebarProvider, Sidebar } from "~/components/ui/sidebar";
import SidebarTriggerDisappearsOnMobile from "./_components/SidebarTriggerDisappearsOnMobile";
import CvCategory from "./_components/CvCategory";
export default function CvPage() {
const cv = trpc.categoryv2.listAllWithEntries.useQuery();
useTimeLine(cv.data)
const byPosition = (pos: "sidebar" | "header" | "col1" | "col2") =>
cv.data?.filter((c) => c.layoutPosition === pos) ?? []
const sidebarCategories = byPosition("sidebar")
const headerCategories = byPosition("header")
const col1Categories = byPosition("col1")
const col2Categories = byPosition("col2")
import { Suspense } from "react";
import { servTrpc as trpc } from "../_trpc/ServerClient";
import Page from "./_components/Page";
export default async function CvPage() {
const cv = await trpc.categoryv2.listAllWithEntries();
return (
<>
<SidebarProvider>
{sidebarCategories.length > 0 &&
<>
<SidebarTriggerDisappearsOnMobile />
<Sidebar>
<SidebarContent className="p-2 lg:pt-[3.2rem]">
{sidebarCategories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</SidebarContent>
</Sidebar>
</>
}
<div className="h-full w-full flex flex-wrap flex-row p-4 pt-8 ">
<div id="mainwrap" className="flex w-full flex-col gap-4 lg:px-[15vw]">
<div id="header" className="flex w-full h-fit flex-row gap-4 flex-wrap">
{headerCategories.map((cat, i) => (
<CvCategory layout="row" position={i} category={cat} key={cat.id} />
))}
</div>
<div id="colwrapper" className="flex flex-col lg:flex-row w-full h-3/4 gap-4">
<div id="col1" className={`flex flex-col w-full ${col1Categories.length > 0 ? "lg:w-1/2" : ""} h-full gap-4`}>
{col1Categories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</div>
<div id="col2" className={`flex flex-col w-full ${col2Categories.length > 0 ? "lg:w-1/2" : ""} h-full gap-4`}>
{col2Categories.map((cat, i) => (
<CvCategory layout="col" position={i} category={cat} key={cat.id} />
))}
</div>
</div>
</div>
</div>
</SidebarProvider>
</>
<Suspense>
<Page cv={cv}/>
</Suspense>
)
}