Update src/components/sections/contact/ContactSplit.tsx
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Mail } from "lucide-react";
|
||||
|
||||
export interface ContactSplitProps {
|
||||
tag?: string;
|
||||
tag: string;
|
||||
title: string;
|
||||
description: string;
|
||||
tagIcon?: React.ComponentType<any>;
|
||||
tagAnimation?: "none" | "opacity" | "slide-up" | "blur-reveal";
|
||||
background?: { variant: string };
|
||||
useInvertedBackground?: boolean;
|
||||
imageSrc?: string;
|
||||
@@ -17,10 +21,10 @@ export interface ContactSplitProps {
|
||||
buttonText?: string;
|
||||
termsText?: string;
|
||||
onSubmit?: (email: string) => void;
|
||||
ariaLabel?: string;
|
||||
className?: string;
|
||||
containerClassName?: string;
|
||||
contentClassName?: string;
|
||||
contactFormClassName?: string;
|
||||
tagClassName?: string;
|
||||
titleClassName?: string;
|
||||
descriptionClassName?: string;
|
||||
@@ -34,90 +38,107 @@ export interface ContactSplitProps {
|
||||
mediaClassName?: string;
|
||||
}
|
||||
|
||||
export const ContactSplit: React.FC<ContactSplitProps> = ({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
imageSrc,
|
||||
videoSrc,
|
||||
imageAlt = "", mediaPosition = "right", inputPlaceholder = "Enter your email", buttonText = "Sign Up", termsText,
|
||||
useInvertedBackground = false,
|
||||
className,
|
||||
containerClassName,
|
||||
contentClassName,
|
||||
tagClassName,
|
||||
titleClassName,
|
||||
descriptionClassName,
|
||||
formWrapperClassName,
|
||||
formClassName,
|
||||
inputClassName,
|
||||
buttonClassName,
|
||||
buttonTextClassName,
|
||||
termsClassName,
|
||||
mediaWrapperClassName,
|
||||
mediaClassName
|
||||
}) => {
|
||||
const [email, setEmail] = useState("");
|
||||
const ContactSplit = React.forwardRef<HTMLDivElement, ContactSplitProps>(
|
||||
(
|
||||
{
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
tagIcon: TagIcon,
|
||||
tagAnimation = "none", background,
|
||||
useInvertedBackground = false,
|
||||
imageSrc,
|
||||
videoSrc,
|
||||
imageAlt = "", videoAriaLabel = "Contact section video", mediaAnimation = "none", mediaPosition = "right", inputPlaceholder = "Enter your email", buttonText = "Sign Up", termsText = "By clicking Sign Up you're confirming that you agree with our Terms and Conditions.", onSubmit,
|
||||
ariaLabel = "Contact section", className = "", containerClassName = "", contentClassName = "", tagClassName = "", titleClassName = "", descriptionClassName = "", formWrapperClassName = "", formClassName = "", inputClassName = "", buttonClassName = "", buttonTextClassName = "", termsClassName = "", mediaWrapperClassName = "", mediaClassName = ""},
|
||||
ref
|
||||
) => {
|
||||
const [email, setEmail] = useState("");
|
||||
|
||||
const handleFormSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setEmail("");
|
||||
};
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
onSubmit?.(email);
|
||||
setEmail("");
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"w-full py-20 px-4", useInvertedBackground && "bg-accent/10", containerClassName
|
||||
)}
|
||||
>
|
||||
<div className={cn("max-w-6xl mx-auto", contentClassName)}>
|
||||
<div className={cn("grid grid-cols-1 md:grid-cols-2 gap-12 items-center", className)}>
|
||||
{mediaPosition === "left" && imageSrc && (
|
||||
<div className={cn("order-first", mediaWrapperClassName)}>
|
||||
<img src={imageSrc} alt={imageAlt} className={cn("w-full rounded-lg", mediaClassName)} />
|
||||
</div>
|
||||
)}
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={`w-full py-20 ${className}`}
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
<div className={`max-w-7xl mx-auto px-4 ${containerClassName}`}>
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 gap-12 ${contentClassName}`}>
|
||||
{/* Text Content */}
|
||||
<div className={formWrapperClassName}>
|
||||
{tag && (
|
||||
<div className={`flex items-center gap-2 mb-4 ${tagClassName}`}>
|
||||
{TagIcon && <TagIcon className="w-4 h-4" />}
|
||||
<span className="text-sm font-medium">{tag}</span>
|
||||
</div>
|
||||
)}
|
||||
<h2 className={`text-4xl font-bold mb-4 ${titleClassName}`}>
|
||||
{title}
|
||||
</h2>
|
||||
<p
|
||||
className={`text-lg text-foreground/75 mb-8 ${descriptionClassName}`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className={cn("space-y-6", contactFormClassName)}>
|
||||
{tag && <p className={cn("text-sm font-semibold text-accent", tagClassName)}>{tag}</p>}
|
||||
<h2 className={cn("text-4xl font-bold", titleClassName)}>{title}</h2>
|
||||
<p className={cn("text-lg text-muted-foreground", descriptionClassName)}>{description}</p>
|
||||
|
||||
<form onSubmit={handleFormSubmit} className={cn("space-y-4", formWrapperClassName)}>
|
||||
<div className={cn("space-y-2", formClassName)}>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className={`space-y-4 ${formClassName}`}
|
||||
>
|
||||
<input
|
||||
type="email"
|
||||
placeholder={inputPlaceholder}
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className={cn(
|
||||
"w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary", inputClassName
|
||||
)}
|
||||
placeholder={inputPlaceholder}
|
||||
required
|
||||
className={`w-full px-4 py-3 bg-secondary-cta text-foreground rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta ${inputClassName}`}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className={cn(
|
||||
"w-full px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors", buttonClassName
|
||||
)}
|
||||
className={`w-full px-4 py-3 bg-primary-cta text-primary-cta-text font-medium rounded-lg hover:opacity-90 transition-opacity ${buttonClassName}`}
|
||||
>
|
||||
<span className={buttonTextClassName}>{buttonText}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
{termsText && <p className={cn("text-xs text-muted-foreground", termsClassName)}>{termsText}</p>}
|
||||
</div>
|
||||
|
||||
{mediaPosition === "right" && imageSrc && (
|
||||
<div className={cn("order-last", mediaWrapperClassName)}>
|
||||
<img src={imageSrc} alt={imageAlt} className={cn("w-full rounded-lg", mediaClassName)} />
|
||||
{termsText && (
|
||||
<p className={`text-xs text-foreground/60 mt-4 ${termsClassName}`}>
|
||||
{termsText}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Media */}
|
||||
{(imageSrc || videoSrc) && (
|
||||
<div className={`flex items-center justify-center ${mediaWrapperClassName}`}>
|
||||
{videoSrc ? (
|
||||
<video
|
||||
src={videoSrc}
|
||||
aria-label={videoAriaLabel}
|
||||
controls
|
||||
className={`w-full h-full object-cover rounded-lg ${mediaClassName}`}
|
||||
/>
|
||||
) : imageSrc ? (
|
||||
<img
|
||||
src={imageSrc}
|
||||
alt={imageAlt}
|
||||
className={`w-full h-full object-cover rounded-lg ${mediaClassName}`}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ContactSplit.displayName = "ContactSplit";
|
||||
|
||||
export default ContactSplit;
|
||||
|
||||
Reference in New Issue
Block a user