Improved the Right to Left Direction implementation for relevant languages. (#2583)

* Added support for right to left direction of bullet points in the page render and text editor

* Added right to left direction support by adding a toggle button in the layout and enhancing the css element of the page render to support it without affecting the default left to right direction

* Moved the Right to Life Direction Toggle feature to be integrated with the Languages section using locale

* change all occurrances of pl, pr, ml, mr, left, right to start/end equivalents

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
This commit is contained in:
Ibrahim
2026-01-25 22:18:20 +05:00
committed by GitHub
parent 0c65612368
commit 3f55c24e36
125 changed files with 484 additions and 264 deletions
+50
View File
@@ -66,4 +66,54 @@
small {
font-size: calc(var(--page-body-font-size) * 0.9pt);
}
/* RTL Support: Apply RTL direction when text is right-aligned */
p[style*="text-align: right"],
h1[style*="text-align: right"],
h2[style*="text-align: right"],
h3[style*="text-align: right"],
h4[style*="text-align: right"],
h5[style*="text-align: right"],
h6[style*="text-align: right"],
li[style*="text-align: right"],
ul[style*="text-align: right"],
ol[style*="text-align: right"] {
direction: rtl;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: normal;
}
/* LTR Support: Apply LTR direction when text is left-aligned */
p[style*="text-align: left"],
h1[style*="text-align: left"],
h2[style*="text-align: left"],
h3[style*="text-align: left"],
h4[style*="text-align: left"],
h5[style*="text-align: left"],
h6[style*="text-align: left"],
li[style*="text-align: left"],
ul[style*="text-align: left"],
ol[style*="text-align: left"] {
direction: ltr;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: normal;
}
/* When list items are RTL, make bullets/numbers appear on the right */
li[style*="text-align: right"] {
text-align: right;
}
/* Parent list inherits direction from its items */
ul:has(li[style*="text-align: right"]),
ol:has(li[style*="text-align: right"]) {
direction: rtl;
}
ul:has(li[style*="text-align: left"]),
ol:has(li[style*="text-align: left"]) {
direction: ltr;
}
}
+3 -3
View File
@@ -147,7 +147,7 @@ function PageContainer({ pageIndex, pageLayout, pageClassName, showPageNumbers =
return (
<div data-page-index={pageIndex} className="relative">
{showPageNumbers && totalNumberOfPages > 1 && (
<div className="absolute -top-6 left-0 print:hidden">
<div className="absolute start-0 -top-6 print:hidden">
<span className="font-medium text-foreground text-xs">
<Trans>
Page {pageNumber} of {totalNumberOfPages}
@@ -161,7 +161,7 @@ function PageContainer({ pageIndex, pageLayout, pageClassName, showPageNumbers =
</div>
{pageHeight > maxPageHeight && (
<div className="absolute top-full left-0 mt-4 print:hidden">
<div className="absolute start-0 top-full mt-4 print:hidden">
<a
rel="noopener"
target="_blank"
@@ -177,7 +177,7 @@ function PageContainer({ pageIndex, pageLayout, pageClassName, showPageNumbers =
</AlertTitle>
<AlertDescription className="text-xs underline-offset-2 group-hover/link:underline">
<Trans>Learn more about how to fit content on a page</Trans>
<ArrowRightIcon color="currentColor" className="ml-1 inline size-3" />
<ArrowRightIcon color="currentColor" className="ms-1 inline size-3" />
</AlertDescription>
</Alert>
</a>
+55 -47
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -7,61 +8,68 @@ import { PagePicture } from "../shared/page-picture";
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",
// Section in Main Layout
"group-data-[layout=main]:[&>.section-content]:relative",
"group-data-[layout=main]:[&>.section-content]:ml-4",
"group-data-[layout=main]:[&>.section-content]:pl-4",
"group-data-[layout=main]:[&>.section-content]:border-l",
"group-data-[layout=main]:[&>.section-content]:border-(--page-primary-color)",
// Timeline Marker in Main Layout
"group-data-[layout=main]:[&>.section-content]:after:content-['']",
"group-data-[layout=main]:[&>.section-content]:after:absolute",
"group-data-[layout=main]:[&>.section-content]:after:top-5",
"group-data-[layout=main]:[&>.section-content]:after:left-0",
"group-data-[layout=main]:[&>.section-content]:after:size-2.5",
"group-data-[layout=main]:[&>.section-content]:after:translate-x-[-50%]",
"group-data-[layout=main]:[&>.section-content]:after:translate-y-[-50%]",
"group-data-[layout=main]:[&>.section-content]:after:rounded-full",
"group-data-[layout=main]:[&>.section-content]:after:border",
"group-data-[layout=main]:[&>.section-content]:after:border-(--page-primary-color)",
"group-data-[layout=main]:[&>.section-content]:after:bg-(--page-background-color)",
);
/**
* Template: Azurill
*/
export function AzurillTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
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:start-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:end-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",
// Section in Main Layout
"group-data-[layout=main]:[&>.section-content]:relative",
"group-data-[layout=main]:[&>.section-content]:ms-4",
"group-data-[layout=main]:[&>.section-content]:ps-4",
"group-data-[layout=main]:[&>.section-content]:border-s",
"group-data-[layout=main]:[&>.section-content]:border-(--page-primary-color)",
// Timeline Marker in Main Layout
"group-data-[layout=main]:[&>.section-content]:after:content-['']",
"group-data-[layout=main]:[&>.section-content]:after:absolute",
"group-data-[layout=main]:[&>.section-content]:after:top-5",
"group-data-[layout=main]:[&>.section-content]:after:start-0",
"group-data-[layout=main]:[&>.section-content]:after:size-2.5",
rtlDirection
? "group-data-[layout=main]:[&>.section-content]:after:[transform:translate(50%,-50%)]"
: "group-data-[layout=main]:[&>.section-content]:after:translate-x-[-50%]",
"group-data-[layout=main]:[&>.section-content]:after:translate-y-[-50%]",
"group-data-[layout=main]:[&>.section-content]:after:rounded-full",
"group-data-[layout=main]:[&>.section-content]:after:border",
"group-data-[layout=main]:[&>.section-content]:after:border-(--page-primary-color)",
"group-data-[layout=main]:[&>.section-content]:after:bg-(--page-background-color)",
);
return (
<div className="template-azurill page-content space-y-(--page-gap-y) px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<div
className="template-azurill page-content space-y-(--page-gap-y) px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{isFirstPage && <Header />}
<div className="flex gap-x-(--page-gap-x)">
+7 -1
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -21,9 +22,14 @@ const sectionClassName = cn(
export function BronzorTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-bronzor page-content space-y-(--page-gap-y) px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<div
className="template-bronzor page-content space-y-(--page-gap-y) px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{isFirstPage && <Header />}
<div className="space-y-(--page-gap-y)">
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -33,12 +34,16 @@ const sectionClassName = cn(
export function ChikoritaTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-chikorita page-content">
<div className="template-chikorita page-content" style={{ direction: rtlDirection ? "rtl" : "ltr" }}>
{/* 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)" />
<div
className={`page-sidebar-background absolute inset-y-0 ${rtlDirection ? "start-0" : "end-0"} z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)`}
/>
)}
{isFirstPage && <Header />}
@@ -75,7 +80,7 @@ function Header() {
return (
<div className="page-header relative flex">
<div className="flex flex-1 items-center pt-(--page-margin-y) pl-(--page-margin-x)">
<div className="flex flex-1 items-center ps-(--page-margin-x) pt-(--page-margin-y)">
<PagePicture />
<div className="page-basics space-y-2 px-(--page-margin-x)">
+20 -5
View File
@@ -1,3 +1,4 @@
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -15,10 +16,10 @@ const sectionClassName = cn(
"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]:ps-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]:-ms-2.5",
"group-data-[layout=main]:[&_.section-item-header]:border-s-2",
"group-data-[layout=main]:[&_.section-item-header]:border-(--page-primary-color)",
);
@@ -28,18 +29,32 @@ const sectionClassName = cn(
export function DitgarTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
const SummaryComponent = getSectionComponent("summary", {
sectionClassName: cn(sectionClassName, "px-(--page-margin-x) pt-(--page-margin-y)"),
});
return (
<div className="template-ditgar page-content">
<div
className="template-ditgar page-content grid min-h-[inherit] grid-cols-3"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{/* 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={`page-sidebar-background absolute inset-y-0 ${rtlDirection ? "end-0" : "start-0"} z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20`}
/>
)}
<div
data-layout="sidebar"
className={cn("sidebar group flex flex-col", !(isFirstPage || !fullWidth) && "hidden")}
>
{isFirstPage && <Header />}
</div>
<div className="flex">
{(!fullWidth || isFirstPage) && (
<aside data-layout="sidebar" className="sidebar group z-10 flex w-(--page-sidebar-width) shrink-0 flex-col">
+6 -3
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -19,16 +20,18 @@ const sectionClassName = cn(
export function DittoTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-ditto page-content">
<div className="template-ditto page-content" style={{ direction: rtlDirection ? "rtl" : "ltr" }}>
{isFirstPage && <Header />}
<div className="flex pt-(--page-margin-y)">
{!fullWidth && (
<aside
data-layout="sidebar"
className="group page-sidebar w-(--page-sidebar-width) shrink-0 space-y-4 overflow-x-hidden pl-(--page-margin-x)"
className="group page-sidebar w-(--page-sidebar-width) shrink-0 space-y-4 overflow-x-hidden ps-(--page-margin-x)"
>
{sidebar.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
@@ -55,7 +58,7 @@ function Header() {
<div className="page-header relative">
<div className="page-basics bg-(--page-primary-color) text-(--page-background-color)">
<div className="basics-header flex items-center">
<div className="flex w-(--page-sidebar-width) shrink-0 justify-center pl-(--page-margin-x)">
<div className="flex w-(--page-sidebar-width) shrink-0 justify-center ps-(--page-margin-x)">
<PagePicture className="absolute top-8" />
</div>
+7 -2
View File
@@ -1,3 +1,4 @@
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -22,12 +23,16 @@ const sectionClassName = cn(
export function GengarTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-gengar page-content">
<div className="template-gengar page-content" style={{ direction: rtlDirection ? "rtl" : "ltr" }}>
{/* 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={`page-sidebar-background absolute inset-y-0 ${rtlDirection ? "end-0" : "start-0"} z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20`}
/>
)}
<div className="flex">
+7 -2
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -22,12 +23,16 @@ const sectionClassName = cn(
export function GlalieTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-glalie page-content">
<div className="template-glalie page-content" style={{ direction: rtlDirection ? "rtl" : "ltr" }}>
{/* 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={`page-sidebar-background absolute inset-y-0 ${rtlDirection ? "end-0" : "start-0"} z-0 w-(--page-sidebar-width) shrink-0 bg-(--page-primary-color)/20`}
/>
)}
<div className="flex">
+7 -1
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -18,9 +19,14 @@ const sectionClassName = cn(
export function KakunaTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-kakuna page-content space-y-4 px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<div
className="template-kakuna page-content space-y-4 px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{isFirstPage && <Header />}
<main data-layout="main" className="group page-main space-y-4">
+5 -1
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -21,6 +22,8 @@ const sectionClassName = cn(
export function LaprasTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
const containerBorderRadius = useResumeStore((state) => Math.min(state.resume.data.picture.borderRadius, 30));
const headingNegativeMargin = useResumeStore((state) => state.resume.data.metadata.typography.heading.fontSize + 6);
@@ -31,6 +34,7 @@ export function LaprasTemplate({ pageIndex, pageLayout }: TemplateProps) {
{
"--container-border-radius": `${containerBorderRadius}pt`,
"--heading-negative-margin": `${headingNegativeMargin}pt`,
direction: rtlDirection ? "rtl" : "ltr",
} as React.CSSProperties
}
className="template-lapras page-content space-y-6 px-(--page-margin-x) pt-(--page-margin-y) print:p-0"
@@ -74,7 +78,7 @@ function Header() {
<p className="basics-headline">{basics.headline}</p>
</div>
<div className="basics-items flex flex-wrap gap-x-2 gap-y-0.5 *:flex *:items-center *:gap-x-1.5 *:border-(--page-primary-color) *:border-r *:py-0.5 *:pr-2 *:last:border-r-0">
<div className="basics-items flex flex-wrap gap-x-2 gap-y-0.5 *:flex *:items-center *:gap-x-1.5 *:border-(--page-primary-color) *:border-e *:py-0.5 *:pe-2 *:last:border-e-0">
{basics.email && (
<div className="basics-item-email">
<EnvelopeIcon />
+4 -1
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -19,9 +20,11 @@ const sectionClassName = cn(
export function LeafishTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-leafish page-content space-y-4">
<div className="template-leafish page-content space-y-4" style={{ direction: rtlDirection ? "rtl" : "ltr" }}>
{isFirstPage && <Header />}
<div className="flex gap-x-(--page-margin-x) px-(--page-margin-x) pt-(--page-margin-y)">
+7 -1
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -15,9 +16,14 @@ const sectionClassName = cn();
export function OnyxTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-onyx page-content space-y-(--page-gap-y) px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<div
className="template-onyx page-content space-y-(--page-gap-y) px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{isFirstPage && <Header />}
<main data-layout="main" className="group page-main space-y-(--page-gap-y)">
+34 -26
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -22,39 +23,46 @@ const sectionClassName = cn(
export function PikachuTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-pikachu page-content flex gap-x-(--page-margin-x) px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<aside
data-layout="sidebar"
className="group page-sidebar flex w-(--page-sidebar-width) shrink-0 flex-col space-y-(--page-gap-y)"
>
{isFirstPage && (
<div className="flex max-w-(--page-sidebar-width) items-center justify-start">
<PagePicture />
</div>
)}
<div
className="template-pikachu page-content px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
<div className="flex gap-x-(--page-margin-x)">
<aside
data-layout="sidebar"
className="group page-sidebar flex w-(--page-sidebar-width) shrink-0 flex-col space-y-3"
>
{isFirstPage && (
<div className="flex items-center justify-center">
<PagePicture />
</div>
)}
{!fullWidth && (
<div className="shrink-0 space-y-(--page-gap-y) overflow-x-hidden">
{sidebar.map((section) => {
{!fullWidth && (
<div className="shrink-0 space-y-(--page-gap-y) overflow-x-hidden">
{sidebar.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
)}
</aside>
<main data-layout="main" className="group page-main flex-1 space-y-(--page-margin-y)">
{isFirstPage && <Header />}
<div className="space-y-(--page-gap-y)">
{main.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
)}
</aside>
<main data-layout="main" className="group page-main flex-1 space-y-(--page-margin-y)">
{isFirstPage && <Header />}
<div className="space-y-(--page-gap-y)">
{main.map((section) => {
const Component = getSectionComponent(section, { sectionClassName });
return <Component key={section} id={section} />;
})}
</div>
</main>
</main>
</div>
</div>
);
}
+8 -2
View File
@@ -1,4 +1,5 @@
import { EnvelopeIcon, GlobeIcon, MapPinIcon, PhoneIcon } from "@phosphor-icons/react";
import { isRTL } from "@/utils/locale";
import { cn } from "@/utils/style";
import { getSectionComponent } from "../shared/get-section-component";
import { PageIcon } from "../shared/page-icon";
@@ -18,9 +19,14 @@ const sectionClassName = cn(
export function RhyhornTemplate({ pageIndex, pageLayout }: TemplateProps) {
const isFirstPage = pageIndex === 0;
const { main, sidebar, fullWidth } = pageLayout;
const locale = useResumeStore((state) => state.resume.data.metadata.page.locale);
const rtlDirection = isRTL(locale);
return (
<div className="template-rhyhorn page-content space-y-4 px-(--page-margin-x) pt-(--page-margin-y) print:p-0">
<div
className="template-rhyhorn page-content space-y-4 px-(--page-margin-x) py-(--page-margin-y) print:p-0"
style={{ direction: rtlDirection ? "rtl" : "ltr" }}
>
{isFirstPage && <Header />}
<main data-layout="main" className="group page-main space-y-4">
@@ -53,7 +59,7 @@ function Header() {
<p className="basics-headline">{basics.headline}</p>
</div>
<div className="basics-items flex flex-wrap gap-x-2 gap-y-0.5 *:flex *:items-center *:gap-x-1.5 *:border-(--page-primary-color) *:border-r *:py-0.5 *:pr-2 *:last:border-r-0">
<div className="basics-items flex flex-wrap gap-x-2 gap-y-0.5 *:flex *:items-center *:gap-x-1.5 *:border-(--page-primary-color) *:border-e *:py-0.5 *:pe-2 *:last:border-e-0">
{basics.email && (
<div className="basics-item-email">
<EnvelopeIcon />