Files
cozsweet-frontend-nextjs/src/app/_components/back-button.tsx
T

88 lines
2.7 KiB
TypeScript

"use client";
import { ChevronLeft } from "lucide-react";
import Link, { type LinkProps } from "next/link";
interface BackButtonBaseProps {
className?: string;
ariaLabel?: string;
analyticsKey?: string;
iconSize?: number;
variant?: "floating" | "soft" | "ghost" | "dark" | "unstyled";
}
type BackButtonLinkProps = BackButtonBaseProps & {
href: LinkProps["href"];
onClick?: never;
};
type BackButtonActionProps = BackButtonBaseProps & {
href?: never;
onClick: () => void;
};
export type BackButtonProps = BackButtonLinkProps | BackButtonActionProps;
const BASE_CLASS_NAME =
"inline-flex cursor-pointer items-center justify-center rounded-full border-0 p-0 text-auth-text-primary no-underline transition-[background,box-shadow,transform] duration-150 ease-out focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-[#f657a0]";
const VARIANT_CLASS_NAMES = {
floating:
"absolute left-[calc(var(--spacing-xl,20px)+var(--app-safe-left,0))] top-[calc(var(--spacing-xl,20px)+var(--app-safe-top,0))] z-2 size-(--back-button-size) bg-(--color-auth-surface) pr-0.5 shadow-[0_2px_8px_rgba(0,0,0,0.1)] hover:bg-[rgba(0,0,0,0.04)] active:scale-96",
soft:
"size-(--responsive-icon-button-size,42px) border border-[rgba(25,19,22,0.08)] bg-[rgba(255,255,255,0.82)] text-[#21191d] shadow-[0_10px_22px_rgba(50,30,40,0.08)] hover:-translate-y-px hover:bg-white hover:shadow-[0_14px_26px_rgba(50,30,40,0.12)] active:translate-y-px",
ghost:
"size-8 bg-transparent text-black hover:opacity-70 active:scale-96",
dark:
"size-(--responsive-icon-button-size,42px) border border-[rgba(255,255,255,0.12)] bg-[rgba(13,11,20,0.7)] text-white shadow-[0_10px_24px_rgba(0,0,0,0.2)] backdrop-blur-md hover:bg-[rgba(28,24,39,0.82)] active:scale-96",
unstyled: "",
} satisfies Record<NonNullable<BackButtonBaseProps["variant"]>, string>;
export function BackButton({
href,
onClick,
className,
ariaLabel = "Back",
analyticsKey,
iconSize = 24,
variant = "floating",
}: BackButtonProps) {
const buttonClassName = [
BASE_CLASS_NAME,
VARIANT_CLASS_NAMES[variant],
className,
]
.filter(Boolean)
.join(" ");
const icon = (
<ChevronLeft size={iconSize} strokeWidth={2.5} aria-hidden="true" />
);
if (href) {
return (
<Link
href={href}
className={buttonClassName}
aria-label={ariaLabel}
data-analytics-key={analyticsKey}
data-analytics-label={ariaLabel}
>
{icon}
</Link>
);
}
return (
<button
type="button"
className={buttonClassName}
onClick={onClick}
aria-label={ariaLabel}
data-analytics-key={analyticsKey}
data-analytics-label={ariaLabel}
>
{icon}
</button>
);
}