Schedule a Demo
See it in action
Get a personalized walkthrough of our platform and discover how we can help your team succeed.
- 30-minute personalized demo
- See real-world use cases
- Get answers to your questions
- No commitment required
Get Your Free Demo
Installation
Copy and paste the following code into your project.
"use client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Calendar, Check, Loader2, Mail, User } from "lucide-react";
import { useState } from "react";
interface DemoRequestProps {
headline: string;
description?: string;
benefits?: string[];
onSubmit?: (data: DemoFormData) => Promise<void> | void;
}
interface DemoFormData {
name: string;
email: string;
company: string;
}
export function CTADemoRequest({
headline,
description,
benefits,
onSubmit,
}: DemoRequestProps) {
const [formData, setFormData] = useState<DemoFormData>({
name: "",
email: "",
company: "",
});
const [isLoading, setIsLoading] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (onSubmit) {
setIsLoading(true);
try {
await onSubmit(formData);
setIsSuccess(true);
setFormData({ name: "", email: "", company: "" });
} catch (error) {
console.error("Demo request error:", error);
} finally {
setIsLoading(false);
}
}
};
const handleChange = (field: keyof DemoFormData, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};
return (
<section className="relative overflow-hidden bg-violet-600 py-20 sm:py-24 rounded">
{/* Background decoration */}
<div className="absolute inset-0 bg-[linear-gradient(to_right,#ffffff08_1px,transparent_1px),linear-gradient(to_bottom,#ffffff08_1px,transparent_1px)] bg-[size:24px_24px]" />
<div className="absolute right-0 top-0 h-[500px] w-[500px] rounded-full bg-violet-500/20 blur-3xl" />
<div className="absolute bottom-0 left-0 h-[500px] w-[500px] rounded-full bg-violet-700/20 blur-3xl" />
<div className="container relative mx-auto px-6">
<div className="mx-auto max-w-6xl">
<div className="grid gap-12 lg:grid-cols-2 lg:gap-16">
{/* Left side - Content */}
<div className="flex flex-col justify-center">
<div className="mb-6 w-fit inline-flex items-center gap-2 rounded-full bg-white/10 px-4 py-1.5 backdrop-blur-sm">
<Calendar className="h-4 w-4 text-white" />
<span className="text-sm font-semibold text-white">
Schedule a Demo
</span>
</div>
<h2 className="mb-6 text-4xl font-bold tracking-tight text-white sm:text-5xl lg:text-6xl">
{headline}
</h2>
{description && (
<p className="mb-8 text-lg text-violet-100 sm:text-xl">
{description}
</p>
)}
{benefits && benefits.length > 0 && (
<ul className="space-y-4">
{benefits.map((benefit, index) => (
<li key={index} className="flex items-start gap-3">
<div className="mt-0.5 flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-white/20">
<Check className="h-4 w-4 text-white" strokeWidth={3} />
</div>
<span className="text-base text-violet-50">
{benefit}
</span>
</li>
))}
</ul>
)}
</div>
{/* Right side - Form */}
<div className="flex items-center">
{isSuccess ? (
<div className="w-full rounded-2xl bg-violet-50 p-8 text-center shadow-xl">
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-green-500">
<Check className="h-8 w-8 text-white" strokeWidth={3} />
</div>
<h3 className="mb-2 text-2xl font-bold text-gray-900">
Request Received!
</h3>
<p className="text-gray-700">
We'll reach out within 24 hours to schedule your
personalized demo.
</p>
</div>
) : (
<div className="w-full rounded-2xl bg-violet-50 p-8 shadow-xl">
<h3 className="mb-6 text-2xl font-bold text-gray-900">
Get Your Free Demo
</h3>
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label
htmlFor="name"
className="mb-2 block text-sm font-medium text-gray-900"
>
Full Name
</label>
<div className="relative">
<User className="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-500" />
<Input
id="name"
type="text"
placeholder="John Doe"
value={formData.name}
onChange={(e) => handleChange("name", e.target.value)}
required
disabled={isLoading}
className="h-12 rounded-lg border-violet-200 bg-white pl-10 text-base focus:border-violet-500 focus:ring-violet-500"
/>
</div>
</div>
<div>
<label
htmlFor="email"
className="mb-2 block text-sm font-medium text-gray-900"
>
Work Email
</label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-500" />
<Input
id="email"
type="email"
placeholder="john@company.com"
value={formData.email}
onChange={(e) =>
handleChange("email", e.target.value)
}
required
disabled={isLoading}
className="h-12 rounded-lg border-violet-200 bg-white pl-10 text-base focus:border-violet-500 focus:ring-violet-500"
/>
</div>
</div>
<div>
<label
htmlFor="company"
className="mb-2 block text-sm font-medium text-gray-900"
>
Company Name
</label>
<Input
id="company"
type="text"
placeholder="Acme Inc"
value={formData.company}
onChange={(e) =>
handleChange("company", e.target.value)
}
required
disabled={isLoading}
className="h-12 rounded-lg border-violet-200 bg-white text-base focus:border-violet-500 focus:ring-violet-500"
/>
</div>
<Button
type="submit"
disabled={isLoading}
className="h-12 w-full rounded-lg bg-violet-600 text-base font-semibold text-white shadow-lg shadow-violet-600/30 transition-all hover:bg-violet-700 hover:shadow-xl hover:shadow-violet-600/40"
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
Submitting...
</>
) : (
"Schedule Demo"
)}
</Button>
<p className="text-center text-xs text-gray-600">
No credit card required. Free 30-minute session.
</p>
</form>
</div>
)}
</div>
</div>
</div>
</div>
</section>
);
}Update the import paths to match your project setup.
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";Features
- ✅ Beautiful gradient - Blue to indigo background
- ✅ Multi-field form - Name, email, and company inputs
- ✅ Icon inputs - User and mail icons in fields
- ✅ Success state - Animated confirmation message
- ✅ Loading states - Visual feedback during submission
- ✅ Benefits list - Checkmarks for key selling points
- ✅ Badge indicator - "Schedule a Demo" badge
- ✅ Responsive layout - Side-by-side on desktop, stacked on mobile
- ✅ Form validation - Built-in required field validation
- ✅ TypeScript support - Full type safety
Usage
Basic Usage
import CTADemoRequest from "@/components/ui/cta-demo-request";
export default function Page() {
return (
<CTADemoRequest
headline="See it in action"
description="Get a personalized demo of our platform."
onSubmit={(data) => console.log("Demo request:", data)}
/>
);
}With Benefits List
<CTADemoRequest
headline="See it in action"
description="Get a personalized walkthrough of our platform."
benefits={[
"30-minute personalized demo",
"See real-world use cases",
"Get answers to your questions",
"No commitment required",
]}
onSubmit={(data) => console.log(data)}
/>With API Integration
"use client";
import CTADemoRequest from "@/components/ui/cta-demo-request";
export default function Page() {
const handleSubmit = async (data: {
name: string;
email: string;
company: string;
}) => {
try {
const response = await fetch("/api/demo-request", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (response.ok) {
// Success handled by component
}
} catch (error) {
console.error("Demo request failed:", error);
}
};
return (
<CTADemoRequest
headline="See it in action"
description="Get a personalized demo."
benefits={[
"30-minute personalized demo",
"See real-world use cases",
"Get answers to your questions",
]}
onSubmit={handleSubmit}
/>
);
}Minimal Version
<CTADemoRequest
headline="Request a Demo"
onSubmit={(data) => console.log(data)}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
headline | string | Required | Main headline text |
description | string | undefined | Supporting description |
benefits | string[] | undefined | List of benefits with checkmarks |
onSubmit | (data: DemoFormData) => void | undefined | Form submission handler |
TypeScript Interface
interface DemoRequestProps {
headline: string;
description?: string;
benefits?: string[];
onSubmit?: (data: DemoFormData) => Promise<void> | void;
}
interface DemoFormData {
name: string;
email: string;
company: string;
}Use Cases
Perfect for:
- SaaS product demos
- B2B lead generation
- Sales team scheduling
- Product walkthroughs
- Consultation requests
- Trial signups
- Enterprise sales
- Platform previews