ldc-ovoteam/resources/ts/front/Components/Theme/Section.tsx
2026-04-15 09:31:53 +02:00

125 lines
3.6 KiB
TypeScript

import { cn } from "@/lib/utils";
import {
BgColorName,
bgColors,
sidePlacements,
VerticalPlacementName,
verticalPlacements,
} from "@/front/lib/constants";
import { ButtonProps, IconConfig, TextProps } from "@/types/front";
import { forwardRef, ReactNode } from "react";
import Container from "./Container";
import Button from "./Button";
import { Link } from "@inertiajs/react";
export type ButtonSectionProps = ButtonProps & {
/** Button vertical placement (top or bottom). Default: bottom */
placement?: VerticalPlacementName;
icon?: IconConfig;
};
type Props = {
variant?: BgColorName;
title?: TextProps;
subtitle?: TextProps;
description?: TextProps;
children: ReactNode;
className?: string;
containerClassName?: string;
button?: ButtonSectionProps;
};
const Section = forwardRef<HTMLDivElement, Props>((props, ref) => {
const {
variant = bgColors.BACKGROUND,
title,
subtitle,
description,
children,
className,
button,
containerClassName,
} = props;
const btnVariant = variant === bgColors.BACKGROUND ? "default" : "inverted";
const btnPlacement =
(button && button.placement) ?? verticalPlacements.BOTTOM;
return (
<section ref={ref} className={cn(variant, "text-center py-20", className)}>
<Container className={cn(containerClassName)}>
{btnPlacement === verticalPlacements.TOP && button && (
<div className="mb-10">
<Button
variant={btnVariant}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(button.icon && {
icon: {
icon: button.icon.icon,
placement: button.icon.placement ?? sidePlacements.RIGHT,
},
})}
asChild
>
<Link href={button.href}>{button.label}</Link>
</Button>
</div>
)}
{(title || subtitle || description) && (
<Container className={cn("space-y-5 mb-16")}>
{title && (
<h2
className={cn(
"text-3xl md:text-5xl max-w-5xl mx-auto uppercase",
title.font,
title.weight ?? "font-bold",
)}
>
{title.text}
</h2>
)}
{subtitle && (
<h3
className={cn(
"text-2xl md:text-3xl mx-auto max-w-2xl uppercase",
subtitle.font,
subtitle.weight ?? "font-bold",
)}
>
{subtitle.text}
</h3>
)}
{description && (
<p
className={cn(
"mx-auto max-w-3xl",
description.font,
description.weight ?? "font-normal",
)}
>
{description.text}
</p>
)}
</Container>
)}
<div>{children}</div>
{btnPlacement === verticalPlacements.BOTTOM && button && (
<div className="mt-16">
<Button
variant={btnVariant}
link={{
href: button.href,
label: button.label,
}}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(button.icon && {
icon: {
icon: button.icon.icon,
placement: button.icon.placement ?? sidePlacements.RIGHT,
},
})}
/>
</div>
)}
</Container>
</section>
);
});
export default Section;