Auth Page SectionShell para páginas de autenticação: barra com marca, formulário centrado ou em duas colunas com slot aside.
"use client";
import type { ContainerProps } from "@zexon/ui/components/container";
import { Container } from "@zexon/ui/components/container";
import { cn } from "@zexon/ui/lib/utils";
import type * as React from "react";
export interface AuthPageSectionProps
extends Omit<React.ComponentProps<"div">, "title"> {
/** Marca (ex.: envolver em `<a href=\"/\">`). */
logo: React.ReactNode;
title?: React.ReactNode;
description?: React.ReactNode;
/** Formulário ou cartão de autenticação. */
children: React.ReactNode;
/** Ligações ou notas abaixo do formulário (termos, voltar ao site, etc.). */
footer?: React.ReactNode;
/** Painel lateral (marca / marketing). Em `md+` aparece à esquerda; em ecrã pequeno fica abaixo do formulário. */
aside?: React.ReactNode;
/** Props do `Container` da barra superior. */
containerProps?: Omit<ContainerProps, "children">;
/** Classe da faixa interior da barra (padding). */
headerContentClassName?: string;
/** Classe da área principal (padding, alinhamento). */
mainClassName?: string;
}
export function AuthPageSection({
logo,
title,
description,
children,
footer,
aside,
containerProps,
headerContentClassName,
mainClassName,
className,
...props
}: AuthPageSectionProps) {
const hasAside = Boolean(aside);
return (
<div
data-slot="auth-page-section"
className={cn(
"flex min-h-svh min-w-0 flex-col bg-background text-foreground",
className,
)}
{...props}
>
<header className="w-full shrink-0 border-b border-border bg-background">
<Container {...containerProps}>
<div
className={cn(
"flex min-h-14 min-w-0 w-full items-center px-4 py-3 md:px-6",
headerContentClassName,
)}
>
<div className="min-w-0 shrink-0">{logo}</div>
</div>
</Container>
</header>
<div
className={cn(
"flex min-h-0 min-w-0 flex-1 flex-col",
hasAside && "md:grid md:grid-cols-2 md:items-stretch md:gap-0",
)}
>
<main
className={cn(
"flex min-h-0 min-w-0 flex-1 flex-col justify-center px-4 py-8 md:py-12",
hasAside && "order-1 md:order-2 md:px-8 lg:px-12",
!hasAside && "items-center",
mainClassName,
)}
>
<div
className={cn(
"w-full min-w-0",
!hasAside && "max-w-md",
hasAside && "md:mx-auto md:max-w-md",
)}
>
{(title != null || description != null) && (
<div
className={cn(
"mb-6 space-y-2",
hasAside ? "text-center md:text-left" : "text-center",
)}
>
{title != null ? (
<h1 className="text-2xl font-semibold tracking-tight">
{title}
</h1>
) : null}
{description != null ? (
<p className="text-sm text-muted-foreground">
{description}
</p>
) : null}
</div>
)}
{children}
{footer != null ? (
<div
className={cn(
"mt-6 text-center text-sm text-muted-foreground",
hasAside && "md:text-left",
)}
>
{footer}
</div>
) : null}
</div>
</main>
{aside != null ? (
<aside
className={cn(
"order-2 flex min-h-0 min-w-0 flex-col justify-center border-border px-4 py-10 md:order-1 md:border-r md:px-8 md:py-12 lg:px-12",
)}
>
{aside}
</aside>
) : null}
</div>
</div>
);
}