62 lines
1.6 KiBLFS
TypeScript
62 lines
1.6 KiBLFS
TypeScript
import Link from "next/link";
|
|
import { ArrowLeft } from "lucide-react";
|
|
import { ReactNode } from "react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface PageLayoutProps {
|
|
title: string;
|
|
description?: ReactNode;
|
|
icon?: ReactNode | null;
|
|
children: ReactNode;
|
|
actions?: ReactNode;
|
|
backLinkHref?: string;
|
|
backLinkLabel?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function PageLayout({
|
|
title,
|
|
description,
|
|
icon,
|
|
children,
|
|
actions,
|
|
backLinkHref = "/",
|
|
backLinkLabel = "Back to Home",
|
|
className,
|
|
}: PageLayoutProps) {
|
|
return (
|
|
<div className="flex flex-col min-h-screen">
|
|
<main className={cn("flex-1 max-w-6xl mx-auto px-4 md:px-8 pt-24 pb-16 md:pt-28 w-full", className)}>
|
|
<div className="mb-12">
|
|
<Link
|
|
href={backLinkHref}
|
|
className="text-muted-foreground text-sm hover:text-foreground transition-colors flex items-center gap-2 mb-6 group w-fit"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
|
|
{backLinkLabel}
|
|
</Link>
|
|
|
|
<div className="flex items-center gap-3 mb-4">
|
|
{icon && (
|
|
<div className="p-2 bg-primary/5 rounded-lg">
|
|
{icon}
|
|
</div>
|
|
)}
|
|
<h1 className="text-3xl font-bold tracking-tight">{title}</h1>
|
|
</div>
|
|
|
|
{description && (
|
|
<p className="text-muted-foreground max-w-2xl text-lg">
|
|
{description}
|
|
</p>
|
|
)}
|
|
|
|
{actions && <div className="mt-8 flex flex-wrap gap-4">{actions}</div>}
|
|
</div>
|
|
|
|
{children}
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|