- fixes #2562, add better error messages for duplicate resume slugs

- improvements made to ditgar template
- general improvements to all templates with backgrounds
- update dependencies and translations
- improved print function that handles single page and multi page resumes
This commit is contained in:
Amruth Pillai
2026-01-23 23:31:24 +01:00
parent ed74fb67f2
commit 4e73a81d4b
96 changed files with 3996 additions and 3418 deletions
@@ -8,6 +8,26 @@ import { useResumeStore } from "../store/resume";
import type { TemplateProps } from "./types";
const sectionClassName = cn(
// Heading Decoration in Sidebar Layout
"group-data-[layout=sidebar]:[&>h6]:px-4",
"group-data-[layout=sidebar]:[&>h6]:relative",
"group-data-[layout=sidebar]:[&>h6]:inline-flex",
"group-data-[layout=sidebar]:[&>h6]:items-center",
"group-data-[layout=sidebar]:[&>h6]:before:content-['']",
"group-data-[layout=sidebar]:[&>h6]:before:absolute",
"group-data-[layout=sidebar]:[&>h6]:before:left-0",
"group-data-[layout=sidebar]:[&>h6]:before:rounded-full",
"group-data-[layout=sidebar]:[&>h6]:before:size-2",
"group-data-[layout=sidebar]:[&>h6]:before:border",
"group-data-[layout=sidebar]:[&>h6]:before:border-(--page-primary-color)",
"group-data-[layout=sidebar]:[&>h6]:after:content-['']",
"group-data-[layout=sidebar]:[&>h6]:after:absolute",
"group-data-[layout=sidebar]:[&>h6]:after:right-0",
"group-data-[layout=sidebar]:[&>h6]:after:rounded-full",
"group-data-[layout=sidebar]:[&>h6]:after:size-2",
"group-data-[layout=sidebar]:[&>h6]:after:border",
"group-data-[layout=sidebar]:[&>h6]:after:border-(--page-primary-color)",
// Section in Sidebar Layout
"group-data-[layout=sidebar]:[&_.section-item-header>div]:flex-col",
"group-data-[layout=sidebar]:[&_.section-item-header>div]:items-start",
+15 -3
View File
@@ -18,6 +18,10 @@ const sectionClassName = cn(
// Icon Colors in Sidebar Layout
"group-data-[layout=sidebar]:[&_.section-item_i]:text-(--page-background-color)!",
// Level Display in Sidebar Layout
"group-data-[layout=sidebar]:[&_.section-item-level>div]:bg-(--page-background-color)",
"group-data-[layout=sidebar]:[&_.section-item-level>div]:text-(--page-background-color)",
// Section Item Header in Sidebar Layout
"group-data-[layout=sidebar]:[&_.section-item-header>div]:flex-col",
"group-data-[layout=sidebar]:[&_.section-item-header>div]:items-start",
@@ -32,10 +36,18 @@ export function ChikoritaTemplate({ pageIndex, pageLayout }: TemplateProps) {
return (
<div className="template-chikorita page-content">
{/* Sidebar Background */}
{!fullWidth && (
<div className="page-sidebar-background absolute inset-y-0 right-0 z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)" />
)}
{isFirstPage && <Header />}
<div className="flex">
<main data-layout="main" className="group page-main flex-1 space-y-4 px-(--page-margin-x) py-(--page-margin-y)">
<main
data-layout="main"
className="group page-main z-10 flex-1 space-y-4 px-(--page-margin-x) py-(--page-margin-y)"
>
{main.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
@@ -45,7 +57,7 @@ export function ChikoritaTemplate({ pageIndex, pageLayout }: TemplateProps) {
{!fullWidth && (
<aside
data-layout="sidebar"
className="group page-sidebar w-(--page-sidebar-width) shrink-0 space-y-4 overflow-x-hidden bg-(--page-primary-color) px-(--page-margin-x) pb-(--page-margin-y) text-(--page-background-color)"
className="group page-sidebar z-10 w-(--page-sidebar-width) shrink-0 space-y-4 overflow-x-hidden px-(--page-margin-x) py-(--page-margin-y) text-(--page-background-color)"
>
{sidebar.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
@@ -111,7 +123,7 @@ function Header() {
</div>
</div>
<div className="w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)" />
<div className="w-(--page-sidebar-width) shrink-0" />
</div>
);
}
+32 -21
View File
@@ -13,6 +13,13 @@ const sectionClassName = cn(
// Section Item Header in Sidebar Layout
"group-data-[layout=sidebar]:[&_.section-item-header>div]:flex-col",
"group-data-[layout=sidebar]:[&_.section-item-header>div]:items-start",
// Decoration Line in Section Item Header
"group-data-[layout=main]:[&_.section-item-header]:pl-2",
"group-data-[layout=main]:[&_.section-item-header]:py-0.5",
"group-data-[layout=main]:[&_.section-item-header]:-ml-2.5",
"group-data-[layout=main]:[&_.section-item-header]:border-l-2",
"group-data-[layout=main]:[&_.section-item-header]:border-(--page-primary-color)",
);
/**
@@ -27,32 +34,36 @@ export function DitgarTemplate({ pageIndex, pageLayout }: TemplateProps) {
});
return (
<div className="template-ditgar page-content grid min-h-[inherit] grid-cols-3">
<div
data-layout="sidebar"
className={cn("sidebar group flex flex-col", !(isFirstPage || !fullWidth) && "hidden")}
>
{isFirstPage && <Header />}
<div className="template-ditgar page-content">
{/* Sidebar Background */}
{!fullWidth && (
<div className="page-sidebar-background absolute inset-y-0 left-0 z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20" />
)}
<div className="flex-1 space-y-4 bg-(--page-primary-color)/20 px-(--page-margin-x) py-(--page-margin-y)">
{sidebar.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
</div>
<div className="flex">
<aside data-layout="sidebar" className="sidebar group z-10 flex w-(--page-sidebar-width) shrink-0 flex-col">
{isFirstPage && <Header />}
<div data-layout="main" className={cn("main group", !fullWidth ? "col-span-2" : "col-span-3")}>
{isFirstPage && <SummaryComponent id="summary" />}
<div className="space-y-4 px-(--page-margin-x) py-(--page-margin-y)">
{main
.filter((section) => section !== "summary")
.map((section) => {
<div className="flex-1 space-y-4 px-(--page-margin-x) py-(--page-margin-y)">
{sidebar.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
</div>
</aside>
<main data-layout="main" className={cn("main group z-10", !fullWidth ? "col-span-2" : "col-span-3")}>
{isFirstPage && <SummaryComponent id="summary" />}
<div className="space-y-4 px-(--page-margin-x) py-(--page-margin-y)">
{main
.filter((section) => section !== "summary")
.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
</main>
</div>
</div>
);
+24 -14
View File
@@ -25,23 +25,33 @@ export function GengarTemplate({ pageIndex, pageLayout }: TemplateProps) {
return (
<div className="template-gengar page-content">
{/* Sidebar Background */}
{(!fullWidth || isFirstPage) && (
<div className="page-sidebar-background absolute inset-y-0 left-0 z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20" />
)}
<div className="flex">
<div data-layout="sidebar" className="group page-sidebar flex w-(--page-sidebar-width) shrink-0 flex-col">
{isFirstPage && <Header />}
{(!fullWidth || isFirstPage) && (
<aside
data-layout="sidebar"
className="group page-sidebar z-10 flex w-(--page-sidebar-width) shrink-0 flex-col"
>
{isFirstPage && <Header />}
{!fullWidth && (
<aside className="shrink-0 space-y-4 overflow-x-hidden bg-(--page-primary-color)/20 px-(--page-margin-x) pt-4 pb-(--page-margin-y)">
{sidebar
.filter((section) => section !== "summary")
.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</aside>
)}
</div>
{!fullWidth && (
<div className="shrink-0 space-y-4 overflow-x-hidden px-(--page-margin-x) pt-4 pb-(--page-margin-y)">
{sidebar
.filter((section) => section !== "summary")
.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
)}
</aside>
)}
<main data-layout="main" className="group page-main">
<main data-layout="main" className="group page-main z-10">
{isFirstPage && (
<PageSummary
className={cn(
+7 -2
View File
@@ -25,10 +25,15 @@ export function GlalieTemplate({ pageIndex, pageLayout }: TemplateProps) {
return (
<div className="template-glalie page-content">
{/* Sidebar Background */}
{(!fullWidth || isFirstPage) && (
<div className="page-sidebar-background absolute inset-y-0 left-0 z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20" />
)}
<div className="flex">
<aside
data-layout="sidebar"
className="group page-sidebar flex w-(--page-sidebar-width) shrink-0 flex-col space-y-4 bg-(--page-primary-color)/20 px-(--page-margin-x) py-(--page-margin-y)"
className="group page-sidebar flex w-(--page-sidebar-width) shrink-0 flex-col space-y-4 px-(--page-margin-x) py-(--page-margin-y)"
>
{isFirstPage && <Header />}
@@ -60,7 +65,7 @@ function Header() {
return (
<div className="page-header relative flex">
<div className="flex w-full shrink-0 flex-col items-center justify-center gap-y-2">
<div className="flex w-full shrink-0 flex-col items-center justify-center gap-y-3">
<PagePicture />
<div className="text-center">
+2 -2
View File
@@ -9,7 +9,7 @@ import type { TemplateProps } from "./types";
const sectionClassName = cn(
// Container
"rounded-(--container-border-radius) border border-(--page-text-color)/10 bg-(--page-background-color) p-4 shadow-md",
"rounded-(--container-border-radius) border border-(--page-text-color)/10 bg-(--page-background-color) p-4",
// Section Heading
"[&>h6]:-mt-(--heading-negative-margin) [&>h6]:max-w-fit [&>h6]:bg-(--page-background-color) [&>h6]:px-4 [&>h6]:pb-0.5",
@@ -63,7 +63,7 @@ function Header() {
<div
className={cn(
"page-header flex items-center gap-x-4",
"rounded-(--picture-border-radius) border border-(--page-text-color)/10 bg-(--page-background-color) p-4 shadow-md",
"rounded-(--picture-border-radius) border border-(--page-text-color)/10 bg-(--page-background-color) p-4",
)}
>
<PagePicture />