Spaces:
Running
Running
deepsite
/
Website-Generation-Request (1)
/src
/components
/blocks
/contact-forms
/contact-form-grid-with-details.tsx
"use client"; | |
import React from "react"; | |
import { Shield } from "lucide-react"; | |
import { useId } from "react"; | |
import { cn } from "@/lib/utils"; | |
import Image from "next/image"; | |
import { motion } from "motion/react"; | |
export function ContactFormGridWithDetails() { | |
return ( | |
<div className="mx-auto grid w-full max-w-7xl grid-cols-1 gap-10 px-4 py-10 md:px-6 md:py-20 lg:grid-cols-2"> | |
<div className="relative flex flex-col items-center overflow-hidden lg:items-start"> | |
<motion.div | |
initial={{ scale: 0, opacity: 0 }} | |
animate={{ scale: 1, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.2 }} | |
className="flex items-start justify-start" | |
> | |
<FeatureIconContainer className="flex items-center justify-center overflow-hidden"> | |
<motion.div | |
animate={{ rotate: [0, 360] }} | |
transition={{ duration: 2, repeat: Infinity, ease: "linear" }} | |
> | |
<Shield className="h-6 w-6 text-red-primary" /> | |
</motion.div> | |
</FeatureIconContainer> | |
</motion.div> | |
<motion.h2 | |
initial={{ y: -50, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.4 }} | |
className="mt-9 bg-gradient-to-b from-dark-gray-secondary to-dark-gray-secondary bg-clip-text text-left text-xl font-bold text-transparent md:text-3xl lg:text-5xl" | |
> | |
Get Your Free Quote | |
</motion.h2> | |
<motion.p | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.6 }} | |
className="mt-8 max-w-lg text-center text-base text-supporting-gray md:text-left" | |
> | |
Contact our experts for a personalized consultation and quote. | |
</motion.p> | |
<motion.div | |
initial={{ x: -50, opacity: 0 }} | |
animate={{ x: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.8 }} | |
className="mt-10 hidden flex-col items-center gap-4 md:flex-row lg:flex" | |
> | |
<motion.p | |
whileHover={{ scale: 1.1 }} | |
transition={{ duration: 0.3 }} | |
className="text-sm text-supporting-gray" | |
> | |
raghavsukhadia@gmail.com | |
</motion.p> | |
<div className="h-1 w-1 rounded-full bg-supporting-gray" /> | |
<motion.p | |
whileHover={{ scale: 1.1 }} | |
transition={{ duration: 0.3 }} | |
className="text-sm text-supporting-gray" | |
> | |
+91 8657081114 | |
</motion.p> | |
<div className="h-1 w-1 rounded-full bg-supporting-gray" /> | |
<motion.p | |
whileHover={{ scale: 1.1 }} | |
transition={{ duration: 0.3 }} | |
className="text-sm text-supporting-gray" | |
> | |
303 Western Palace, Congress Nagar, Opposite Park, Nagpur | |
</motion.p> | |
</motion.div> | |
<motion.div | |
initial={{ y: 30, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 1.0 }} | |
className="mt-8 space-y-2 hidden lg:flex lg:flex-col" | |
> | |
<h3 className="text-lg font-semibold text-dark-gray-secondary">Business Hours</h3> | |
<div className="space-y-1 text-sm text-supporting-gray"> | |
<motion.p | |
whileHover={{ x: 10 }} | |
transition={{ duration: 0.3 }} | |
> | |
Monday - Saturday: 10:00 AM - 08:00 PM | |
</motion.p> | |
<motion.p | |
whileHover={{ x: 10 }} | |
transition={{ duration: 0.3 }} | |
> | |
Sunday: Closed | |
</motion.p> | |
</div> | |
<motion.p | |
animate={{ | |
color: ["#DC2626", "#EF4444", "#DC2626"], | |
textShadow: ["0 0 5px #DC2626", "0 0 10px #DC2626", "0 0 5px #DC2626"] | |
}} | |
transition={{ duration: 2, repeat: Infinity }} | |
className="text-sm text-red-primary font-medium pt-2" | |
> | |
Free on-site consultations available | |
</motion.p> | |
</motion.div> | |
<motion.div | |
initial={{ scale: 0, opacity: 0 }} | |
animate={{ scale: 1, opacity: 1 }} | |
transition={{ duration: 1, delay: 1.2 }} | |
className="div relative mt-20 flex w-[600px] flex-shrink-0 -translate-x-10 items-center justify-center [perspective:800px] [transform-style:preserve-3d] sm:-translate-x-0 lg:-translate-x-32" | |
> | |
<Pin className="top-0 right-1" /> | |
<motion.div | |
animate={{ rotateY: [0, 360] }} | |
transition={{ duration: 20, repeat: Infinity, ease: "linear" }} | |
> | |
<Image | |
src="/world.svg" | |
width={500} | |
height={500} | |
alt="world map" | |
className="[transform:rotateX(45deg)_translateZ(0px)] dark:invert dark:filter" | |
/> | |
</motion.div> | |
</motion.div> | |
</div> | |
<motion.div | |
initial={{ x: 50, opacity: 0 }} | |
animate={{ x: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.4 }} | |
className="relative mx-auto flex w-full max-w-2xl flex-col items-start gap-4 overflow-hidden rounded-3xl bg-gradient-to-b from-gray-100 to-gray-200 p-4 sm:p-10 dark:from-neutral-900 dark:to-neutral-950" | |
> | |
<Grid size={20} /> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 0.6 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="name" | |
> | |
Name | |
</label> | |
<input | |
id="name" | |
type="text" | |
placeholder="Your Full Name" | |
className="shadow-input h-10 w-full rounded-md border border-transparent bg-white pl-4 text-sm text-dark-gray-secondary placeholder-supporting-gray outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
/> | |
</motion.div> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 0.7 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="email" | |
> | |
</label> | |
<input | |
id="email" | |
type="email" | |
placeholder="your@email.com" | |
className="shadow-input h-10 w-full rounded-md border border-transparent bg-white pl-4 text-sm text-dark-gray-secondary placeholder-supporting-gray outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
/> | |
</motion.div> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 0.8 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="phone" | |
> | |
Phone | |
</label> | |
<input | |
id="phone" | |
type="tel" | |
placeholder="+91 8657081114" | |
className="shadow-input h-10 w-full rounded-md border border-transparent bg-white pl-4 text-sm text-dark-gray-secondary placeholder-supporting-gray outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
/> | |
</motion.div> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 0.9 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="property-type" | |
> | |
Property Type | |
</label> | |
<select | |
id="property-type" | |
className="shadow-input h-10 w-full rounded-md border border-transparent bg-white pl-4 text-sm text-dark-gray-secondary outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
> | |
<option value="">Select Property Type</option> | |
<option value="residential">Residential</option> | |
<option value="commercial">Commercial</option> | |
<option value="automotive">Automotive</option> | |
</select> | |
</motion.div> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 1.0 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="service-needed" | |
> | |
Service Needed | |
</label> | |
<select | |
id="service-needed" | |
className="shadow-input h-10 w-full rounded-md border border-transparent bg-white pl-4 text-sm text-dark-gray-secondary outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
> | |
<option value="">Select Service</option> | |
<option value="new-installation">New Installation</option> | |
<option value="replacement">Replacement</option> | |
<option value="consultation">Consultation</option> | |
</select> | |
</motion.div> | |
<motion.div | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 1.1 }} | |
className="relative z-20 mb-4 w-full" | |
> | |
<label | |
className="mb-2 inline-block text-sm font-medium text-dark-gray-secondary" | |
htmlFor="message" | |
> | |
Message | |
</label> | |
<textarea | |
id="message" | |
rows={5} | |
placeholder="Tell us about your project..." | |
className="shadow-input w-full rounded-md border border-transparent bg-white pt-4 pl-4 text-sm text-dark-gray-secondary placeholder-supporting-gray outline-none focus:ring-2 focus:ring-red-primary focus:outline-none active:outline-none transition-all duration-300 focus:scale-105" | |
/> | |
</motion.div> | |
<motion.button | |
initial={{ y: 20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.6, delay: 1.2 }} | |
whileHover={{ scale: 1.05 }} | |
whileTap={{ scale: 0.95 }} | |
className="relative z-10 flex items-center justify-center rounded-md border border-transparent bg-red-primary px-4 py-2 text-sm font-medium text-white shadow-[0px_1px_0px_0px_#FFFFFF20_inset] transition-all duration-300 hover:bg-red-600 hover:shadow-lg hover:shadow-red-600/25 md:text-sm" | |
> | |
Get Free Quote | |
</motion.button> | |
</motion.div> | |
</div> | |
); | |
} | |
const Pin = ({ className }: { className?: string }) => { | |
return ( | |
<motion.div | |
style={{ transform: "translateZ(1px)" }} | |
className={cn( | |
"pointer-events-none absolute z-[60] flex h-40 w-96 items-center justify-center opacity-100 transition duration-500", | |
className | |
)} | |
> | |
<div className="h-full w-full"> | |
<motion.div | |
initial={{ y: -20, opacity: 0 }} | |
animate={{ y: 0, opacity: 1 }} | |
transition={{ duration: 0.8, delay: 0.5 }} | |
className="absolute inset-x-0 top-0 z-20 mx-auto inline-block w-fit rounded-lg bg-neutral-200 px-2 py-1 text-xs font-normal text-neutral-700 dark:bg-neutral-800 dark:text-white" | |
> | |
We are here | |
<motion.span | |
animate={{ | |
background: ["linear-gradient(to right, rgba(59, 130, 246, 0) 0%, rgba(59, 130, 246, 0.9) 50%, rgba(59, 130, 246, 0) 100%)", | |
"linear-gradient(to right, rgba(220, 38, 38, 0) 0%, rgba(220, 38, 38, 0.9) 50%, rgba(220, 38, 38, 0) 100%)", | |
"linear-gradient(to right, rgba(59, 130, 246, 0) 0%, rgba(59, 130, 246, 0.9) 50%, rgba(59, 130, 246, 0) 100%)"] | |
}} | |
transition={{ duration: 3, repeat: Infinity }} | |
className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-blue-400/0 via-blue-400/90 to-blue-400/0 transition-opacity duration-500" | |
/> | |
</motion.div> | |
<div | |
style={{ | |
perspective: "800px", | |
transform: "rotateX(70deg) translateZ(0px)", | |
}} | |
className="absolute top-1/2 left-1/2 mt-4 ml-[0.09375rem] -translate-x-1/2 -translate-y-1/2" | |
> | |
<> | |
<motion.div | |
initial={{ opacity: 0, scale: 0 }} | |
animate={{ | |
opacity: [0, 1, 0.5, 0], | |
scale: 1, | |
}} | |
transition={{ duration: 6, repeat: Infinity, delay: 0 }} | |
className="absolute top-1/2 left-1/2 h-20 w-20 -translate-x-1/2 -translate-y-1/2 rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)] dark:bg-sky-500/[0.2]" | |
/> | |
<motion.div | |
initial={{ opacity: 0, scale: 0 }} | |
animate={{ | |
opacity: [0, 1, 0.5, 0], | |
scale: 1, | |
}} | |
transition={{ duration: 6, repeat: Infinity, delay: 2 }} | |
className="absolute top-1/2 left-1/2 h-20 w-20 -translate-x-1/2 -translate-y-1/2 rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)] dark:bg-sky-500/[0.2]" | |
/> | |
<motion.div | |
initial={{ opacity: 0, scale: 0 }} | |
animate={{ | |
opacity: [0, 1, 0.5, 0], | |
scale: 1, | |
}} | |
transition={{ duration: 6, repeat: Infinity, delay: 4 }} | |
className="absolute top-1/2 left-1/2 h-20 w-20 -translate-x-1/2 -translate-y-1/2 rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)] dark:bg-sky-500/[0.2]" | |
/> | |
</> | |
</div> | |
<> | |
<motion.div | |
animate={{ | |
background: ["linear-gradient(to bottom, transparent, #3b82f6)", | |
"linear-gradient(to bottom, transparent, #dc2626)", | |
"linear-gradient(to bottom, transparent, #3b82f6)"] | |
}} | |
transition={{ duration: 3, repeat: Infinity }} | |
className="absolute right-1/2 bottom-1/2 h-20 w-px translate-y-[14px] bg-gradient-to-b from-transparent to-blue-500 blur-[2px]" | |
/> | |
<motion.div | |
animate={{ | |
background: ["linear-gradient(to bottom, transparent, #3b82f6)", | |
"linear-gradient(to bottom, transparent, #dc2626)", | |
"linear-gradient(to bottom, transparent, #3b82f6)"] | |
}} | |
transition={{ duration: 3, repeat: Infinity }} | |
className="absolute right-1/2 bottom-1/2 h-20 w-px translate-y-[14px] bg-gradient-to-b from-transparent to-blue-500" | |
/> | |
<motion.div | |
animate={{ | |
backgroundColor: ["#2563eb", "#dc2626", "#2563eb"], | |
boxShadow: ["0 0 10px #2563eb", "0 0 15px #dc2626", "0 0 10px #2563eb"] | |
}} | |
transition={{ duration: 3, repeat: Infinity }} | |
className="absolute right-1/2 bottom-1/2 z-40 h-[4px] w-[4px] translate-x-[1.5px] translate-y-[14px] rounded-full bg-blue-600 blur-[3px]" | |
/> | |
<motion.div | |
animate={{ | |
backgroundColor: ["#93c5fd", "#fca5a5", "#93c5fd"] | |
}} | |
transition={{ duration: 3, repeat: Infinity }} | |
className="absolute right-1/2 bottom-1/2 z-40 h-[2px] w-[2px] translate-x-[0.5px] translate-y-[14px] rounded-full bg-blue-300" | |
/> | |
</> | |
</div> | |
</motion.div> | |
); | |
}; | |
export const FeatureIconContainer = ({ | |
children, | |
className, | |
}: { | |
children: React.ReactNode; | |
className?: string; | |
}) => { | |
return ( | |
<div | |
className={cn( | |
"relative h-14 w-14 rounded-md bg-gradient-to-b from-gray-50 to-neutral-200 p-[4px] dark:from-neutral-800 dark:to-neutral-950", | |
className | |
)} | |
> | |
<div | |
className={cn( | |
"relative z-20 h-full w-full rounded-[5px] bg-gray-50 dark:bg-neutral-800", | |
className | |
)} | |
> | |
{children} | |
</div> | |
<div className="absolute inset-x-0 bottom-0 z-30 mx-auto h-4 w-full rounded-full bg-neutral-600 opacity-50 blur-lg"></div> | |
<div className="absolute inset-x-0 bottom-0 mx-auto h-px w-[60%] bg-gradient-to-r from-transparent via-red-primary to-transparent"></div> | |
<div className="absolute inset-x-0 bottom-0 mx-auto h-px w-[60%] bg-gradient-to-r from-transparent via-red-600 to-transparent dark:h-[8px] dark:blur-sm"></div> | |
</div> | |
); | |
}; | |
export const Grid = ({ | |
pattern, | |
size, | |
}: { | |
pattern?: number[][]; | |
size?: number; | |
}) => { | |
const p = pattern ?? [ | |
[Math.floor(Math.random() * 4) + 7, Math.floor(Math.random() * 6) + 1], | |
[Math.floor(Math.random() * 4) + 7, Math.floor(Math.random() * 6) + 1], | |
[Math.floor(Math.random() * 4) + 7, Math.floor(Math.random() * 6) + 1], | |
[Math.floor(Math.random() * 4) + 7, Math.floor(Math.random() * 6) + 1], | |
[Math.floor(Math.random() * 4) + 7, Math.floor(Math.random() * 6) + 1], | |
]; | |
return ( | |
<div className="pointer-events-none absolute top-0 left-1/2 -mt-2 -ml-20 h-full w-full [mask-image:linear-gradient(white,transparent)]"> | |
<div className="absolute inset-0 bg-gradient-to-r from-zinc-900/30 to-zinc-900/30 opacity-10 [mask-image:radial-gradient(farthest-side_at_top,white,transparent)] dark:from-zinc-900/30 dark:to-zinc-900/30"> | |
<GridPattern | |
width={size ?? 20} | |
height={size ?? 20} | |
x="-12" | |
y="4" | |
squares={p} | |
className="absolute inset-0 h-full w-full fill-black/100 stroke-black/100 mix-blend-overlay dark:fill-white/100 dark:stroke-white/100" | |
/> | |
</div> | |
</div> | |
); | |
}; | |
export function GridPattern({ width, height, x, y, squares, ...props }: any) { | |
const patternId = useId(); | |
return ( | |
<svg aria-hidden="true" {...props}> | |
<defs> | |
<pattern | |
id={patternId} | |
width={width} | |
height={height} | |
patternUnits="userSpaceOnUse" | |
x={x} | |
y={y} | |
> | |
<path d={`M.5 ${height}V.5H${width}`} fill="none" /> | |
</pattern> | |
</defs> | |
<rect | |
width="100%" | |
height="100%" | |
strokeWidth={0} | |
fill={`url(#${patternId})`} | |
/> | |
{squares && ( | |
<svg x={x} y={y} className="overflow-visible"> | |
{squares.map(([x, y]: any, idx: number) => ( | |
<rect | |
strokeWidth="0" | |
key={`${x}-${y}-${idx}`} | |
width={width + 1} | |
height={height + 1} | |
x={x * width} | |
y={y * height} | |
/> | |
))} | |
</svg> | |
)} | |
</svg> | |
); | |
} |