xtablo-source/packages/auth-ui/src/AuthCardShell.tsx
Arthur Belleville 90d34833e8
Fix config.ts
2026-05-01 10:33:00 +02:00

127 lines
3.9 KiB
TypeScript

import { useTheme } from "@xtablo/shared/contexts/ThemeContext";
import { Button } from "@xtablo/ui/components/button";
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
import type { CSSProperties, MouseEventHandler, ReactNode } from "react";
import { twMerge } from "tailwind-merge";
type AuthCardShellProps = {
title: string;
description?: ReactNode;
children: ReactNode;
background?: ReactNode;
topLeft?: ReactNode;
showThemeToggle?: boolean;
onBackdropClick?: () => void;
wrapperClassName?: string;
wrapperStyle?: CSSProperties;
onWrapperMouseMove?: MouseEventHandler<HTMLDivElement>;
onWrapperMouseLeave?: () => void;
isHovered?: boolean;
cardClassName?: string;
};
const XTABLO_ASSETS_BASE_URL = "https://assets.xtablo.com";
export function AuthCardShell({
title,
description,
children,
background,
topLeft,
showThemeToggle = false,
onBackdropClick,
wrapperClassName,
wrapperStyle,
onWrapperMouseMove,
onWrapperMouseLeave,
isHovered = false,
cardClassName,
}: AuthCardShellProps) {
const { theme, setTheme } = useTheme();
const toggleTheme = () => {
if (theme === "light") {
setTheme("dark");
} else if (theme === "dark") {
setTheme("system");
} else {
setTheme("light");
}
};
const themeIcon =
theme === "light" ? (
<SunIcon className="h-5 w-5" />
) : theme === "dark" ? (
<MoonIcon className="h-5 w-5" />
) : (
<MonitorIcon className="h-5 w-5" />
);
return (
<div
className="min-h-screen flex items-center justify-center bg-linear-to-br from-primary/10 via-background to-secondary/5 relative overflow-hidden px-4 py-8 sm:px-6"
onClick={onBackdropClick}
>
{background}
<div
className={twMerge("w-full max-w-lg rounded-2xl relative", wrapperClassName)}
style={wrapperStyle}
onMouseMove={onWrapperMouseMove}
onMouseLeave={onWrapperMouseLeave}
onClick={(event) => event.stopPropagation()}
>
<div className="absolute inset-0 rounded-2xl bg-linear-to-br from-primary/10 via-primary/5 to-secondary/10 blur-xl -z-10" />
<div
data-testid="auth-card-shell"
className={twMerge(
"relative w-full h-full p-5 sm:p-8 bg-card/80 backdrop-blur-md rounded-2xl border border-border z-10 transition-shadow duration-200",
isHovered
? "shadow-[0_15px_35px_rgba(0,0,0,0.15)] dark:shadow-[0_15px_35px_rgba(0,0,0,0.3)]"
: "shadow-xl shadow-black/10 dark:shadow-black/25",
cardClassName
)}
>
{topLeft || showThemeToggle ? (
<div className="mb-6 flex items-center justify-between">
<div className="p-2">{topLeft}</div>
{showThemeToggle ? (
<Button
variant="ghost"
size="icon"
onClick={toggleTheme}
className="text-muted-foreground hover:text-foreground p-2"
aria-label={`change theme (${theme})`}
>
{themeIcon}
</Button>
) : null}
</div>
) : null}
<div className="mb-6 flex justify-center">
<img
src={`${XTABLO_ASSETS_BASE_URL}/logo_dark.png`}
alt="Xtablo"
className="w-16 h-16 object-contain block dark:hidden"
/>
<img
src={`${XTABLO_ASSETS_BASE_URL}/logo_white.png`}
alt="Xtablo"
className="w-16 h-16 object-contain hidden dark:block"
/>
</div>
<div className="space-y-2 text-center mb-6">
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">{title}</h1>
{description ? <div className="text-muted-foreground">{description}</div> : null}
</div>
{children}
</div>
</div>
</div>
);
}