119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
/** SHADCN */
|
|
import { ButtonProps } from "@/components/ui/button";
|
|
/** THEME */
|
|
import Button from "$/uwil/Button";
|
|
import SafeHtml from "@/components/safe-html";
|
|
import {
|
|
BgColorName,
|
|
bgColors,
|
|
VerticalPlacementName,
|
|
verticalPlacements,
|
|
} from "@/front/lib/constants";
|
|
import { cn } from "@/lib/utils";
|
|
import { CustomButtonVariant, TextProps } from "@/types/front";
|
|
|
|
type Props = {
|
|
/** Button configuration */
|
|
button: {
|
|
/** Button label */
|
|
label: string;
|
|
/** Link URL */
|
|
href: string;
|
|
/** Button vertical placement (top or bottom). Default: bottom */
|
|
placement?: VerticalPlacementName;
|
|
/** Custom button variant (optional) */
|
|
variant?: ButtonProps["variant"] | CustomButtonVariant;
|
|
};
|
|
|
|
/** Background color variant. Default: PRIMARY */
|
|
variant?: BgColorName;
|
|
|
|
/** Text content configuration */
|
|
text: TextProps;
|
|
};
|
|
|
|
/**
|
|
* ActionSection
|
|
*
|
|
* A reusable section component displaying a call-to-action with text and a button.
|
|
* The button can be positioned either above or below the text.
|
|
*
|
|
* This component is designed to be flexible and theme-aware through background variants
|
|
* and button styles.
|
|
*
|
|
* @component
|
|
*
|
|
* @param {Object} props - Component props
|
|
* @param {Object} props.button - Button configuration
|
|
* @param {string} props.button.label - Text displayed inside the button
|
|
* @param {string} props.button.href - URL the button links to
|
|
* @param {VerticalPlacementName} [props.button.placement="bottom"] - Vertical position of the button relative to the text ("top" or "bottom")
|
|
* @param {ButtonProps["variant"] | CustomButtonVariant} [props.button.variant] - Optional custom button variant (overrides default behavior)
|
|
*
|
|
* @param {BgColorName} [props.variant=bgColors.PRIMARY] - Background color variant of the section
|
|
*
|
|
* @param {TextProps} props.text - Text content configuration
|
|
* @param {string} props.text.text - HTML string displayed as the main text (rendered using dangerouslySetInnerHTML)
|
|
* @param {string} props.text.font - CSS class applied to the text for font styling
|
|
*
|
|
* @return {JSX.Element} A styled section with text and a call-to-action button
|
|
*
|
|
* @example
|
|
* <ActionSection
|
|
* variant={bgColors.SECONDARY}
|
|
* text={{
|
|
* text: "<strong>Start now</strong> and boost your productivity",
|
|
* font: "font-semibold"
|
|
* }}
|
|
* button={{
|
|
* label: "Get Started",
|
|
* href: "/signup",
|
|
* placement: verticalPlacements.BOTTOM
|
|
* }}
|
|
* />
|
|
*/
|
|
export default function ActionSection(props: Readonly<Props>) {
|
|
const { button, variant = bgColors.PRIMARY, text } = props;
|
|
|
|
const placement = button.placement ?? verticalPlacements.BOTTOM;
|
|
const btnVariant = variant === bgColors.PRIMARY ? "inverted" : "default";
|
|
|
|
return (
|
|
<div className={cn("text-center py-20", variant)}>
|
|
<div className="max-w-7xl mx-auto px-4 md:px-0 space-y-6">
|
|
{placement === verticalPlacements.TOP && (
|
|
<Button
|
|
variant={button.variant ?? btnVariant}
|
|
icon={{
|
|
icon: "chevron-right",
|
|
placement: "right",
|
|
}}
|
|
link={{
|
|
label: button.label,
|
|
href: button.href,
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
<SafeHtml
|
|
as="p"
|
|
className={cn("text-2xl", text.font)}
|
|
html={text.text}
|
|
/>
|
|
{placement === verticalPlacements.BOTTOM && (
|
|
<Button
|
|
variant={button.variant ?? btnVariant}
|
|
icon={{
|
|
icon: "chevron-right",
|
|
placement: "right",
|
|
}}
|
|
link={{
|
|
label: button.label,
|
|
href: button.href,
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|