import type { Icon } from "@phosphor-icons/react"; import type { ReactNode } from "react"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { EyeIcon, NotePencilIcon, PaletteIcon } from "@phosphor-icons/react"; import { Outlet } from "@tanstack/react-router"; import { useEffect, useState } from "react"; import { cn } from "@reactive-resume/utils/style"; import { usePreviewPausedStore } from "@/features/resume/builder/draft"; import { BuilderSidebarLeft } from "../-sidebar/left"; import { BuilderSidebarRight } from "../-sidebar/right"; import { BuilderHeader } from "./header"; type MobileBuilderTab = "edit" | "preview" | "design"; const MOBILE_BUILDER_TABS = [ { value: "edit", icon: NotePencilIcon }, { value: "preview", icon: EyeIcon }, { value: "design", icon: PaletteIcon }, ] as const satisfies readonly { value: MobileBuilderTab; icon: Icon }[]; type MobileSidebarPanelProps = { children: ReactNode; }; function MobileSidebarPanel({ children }: MobileSidebarPanelProps) { // Sits below the header (top-14) and above the tab bar (bottom-16). The sidebar's ScrollArea hardcodes // `h-[calc(100svh-3.5rem)]`; override it to fill this panel so its last item isn't hidden under the tab bar. return (
{children}
); } type MobileBuilderTabBarProps = { activeTab: MobileBuilderTab; onTabChange: (tab: MobileBuilderTab) => void; }; function MobileBuilderTabBar({ activeTab, onTabChange }: MobileBuilderTabBarProps) { const labels: Record = { edit: t`Edit`, preview: t`Preview`, design: t`Design` }; return ( ); } export function MobileBuilderShell() { // Local state is enough — mobile view mode is shell-scoped and doesn't need to persist. const [tab, setTab] = useState("edit"); const setPreviewPaused = usePreviewPausedStore((state) => state.setPaused); // The preview stays mounted under the Edit/Design overlay; pause its render while it's covered. useEffect(() => { setPreviewPaused(tab !== "preview"); return () => setPreviewPaused(false); }, [tab, setPreviewPaused]); return (
Skip to main content {/* The preview (fixed inset-0) stays mounted so zoom/pan state survives tab switches. */}
{tab === "edit" && ( )} {tab === "design" && ( )}
); }