Cta Split Demo Request Modal
blockmarketingSplit-pane enterprise demo request workbench with benefit highlights, team size selectors, framework focus filters, and interactive submission feedback.
Installation
$pnpm dlx shadcn@latest add https://uipkge.dev/r/react/cta-split-demo-request-modal.json$npx shadcn@latest add https://uipkge.dev/r/react/cta-split-demo-request-modal.json$yarn dlx shadcn@latest add https://uipkge.dev/r/react/cta-split-demo-request-modal.json$bunx shadcn@latest add https://uipkge.dev/r/react/cta-split-demo-request-modal.jsonNamed registry:
npx shadcn@latest add @uipkge-react/cta-split-demo-request-modalInstalls to:components/blocks/Variants
Loading interactive previews…
Loading interactive previews…
Props
| Name | Type / Values | Default | Required |
|---|---|---|---|
className | string | — | optional |
npm dependencies
Files installed (1)
components/blocks/CtaSplitDemoRequestModal.tsx9.5 kB
'use client' import * as React from 'react' import { ArrowRight, Calendar, CheckCircle2, Lock, Mail, Palette, ShieldCheck, Zap } from 'lucide-react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { cn } from '@/lib/utils' export interface CtaSplitDemoRequestModalProps { className?: string } export function CtaSplitDemoRequestModal({ className }: CtaSplitDemoRequestModalProps) { const [email, setEmail] = React.useState('') const [teamSize, setTeamSize] = React.useState('11-50') const [frameworkFocus, setFrameworkFocus] = React.useState('Dual-Framework Monorepo') const [isSubmitted, setIsSubmitted] = React.useState(false) const submitDemoRequest = () => { if (!email) return setIsSubmitted(true) } return ( <section data-slot="cta-split-demo-request-modal" className={cn('bg-background relative overflow-hidden px-4 py-16 sm:px-6 sm:py-24 lg:px-8', className)} > <div className="mx-auto max-w-6xl space-y-12"> {/* Section Header */} <div className="mx-auto max-w-3xl space-y-4 text-center"> <Badge variant="secondary" className="gap-1.5 px-3 py-1 font-mono text-xs shadow-xs"> <Calendar className="text-primary size-3.5" /> Enterprise Design System Strategy </Badge> <h2 className="text-foreground text-3xl font-bold tracking-tight sm:text-4xl"> Schedule an architectural walkthrough. </h2> <p className="text-muted-foreground text-base"> See how unbundled registries and dual-framework tokens accelerate enterprise frontend velocity. </p> </div> {/* Split Workbench Container */} <div className="grid grid-cols-1 items-stretch gap-8 lg:grid-cols-12"> {/* Left Column: Enterprise Benefits (6 Cols) */} <Card className="border-border bg-card/95 flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-xl sm:p-8 lg:col-span-6"> <div className="space-y-6"> <h3 className="text-foreground font-mono text-xl font-bold">What you'll discover on the call:</h3> <div className="space-y-4"> <div className="flex items-start gap-3"> <div className="bg-primary/10 border-primary/20 text-primary shrink-0 rounded-lg border p-2"> <Zap className="size-4" /> </div> <div> <h4 className="text-foreground font-mono text-xs font-bold">Eliminating NPM Semver Bottlenecks</h4> <p className="text-muted-foreground mt-0.5 text-xs"> How code ownership prevents breaking upgrades and unblocks feature teams. </p> </div> </div> <div className="flex items-start gap-3"> <div className="bg-primary/10 border-primary/20 text-primary shrink-0 rounded-lg border p-2"> <ShieldCheck className="size-4" /> </div> <div> <h4 className="text-foreground font-mono text-xs font-bold"> Private Registry Mirroring & Air-Gapping </h4> <p className="text-muted-foreground mt-0.5 text-xs"> Host internal organizational registries behind your enterprise firewall with custom security audits. </p> </div> </div> <div className="flex items-start gap-3"> <div className="bg-primary/10 border-primary/20 text-primary shrink-0 rounded-lg border p-2"> <Palette className="size-4" /> </div> <div> <h4 className="text-foreground font-mono text-xs font-bold">Tailwind CSS v4 Token Architecture</h4> <p className="text-muted-foreground mt-0.5 text-xs"> 100% mathematical token sync across Vue 3.5 SFCs and React 19 TSX islands. </p> </div> </div> </div> </div> {/* Trust footer */} <div className="border-border text-muted-foreground flex items-center justify-between border-t pt-4 font-mono text-xs"> <span className="flex items-center gap-1.5"> <Lock className="text-primary size-3.5" /> NDA Protected • No Obligation </span> <span className="text-success font-semibold">✓ 30-Min Fast Track</span> </div> </Card> {/* Right Column: Interactive Scheduling Form (6 Cols) */} <Card className="border-border bg-card/95 flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-sm sm:p-8 lg:col-span-6"> {!isSubmitted ? ( <div className="space-y-5"> <div className="space-y-1"> <h3 className="text-foreground font-mono text-lg font-bold">Request Your Custom Demo</h3> <p className="text-muted-foreground text-xs"> Fill in your team details to receive an instant calendar invite. </p> </div> {/* Email Field */} <div className="space-y-1.5"> <label className="text-muted-foreground font-mono text-xs">Work Email Address</label> <div className="relative"> <Mail className="text-muted-foreground absolute top-1/2 left-3.5 size-4 -translate-y-1/2" /> <Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="alex@company.com" className="bg-card border-border h-10 rounded-xl pl-10 font-mono text-xs shadow-xs" /> </div> </div> {/* Team Size Picker */} <div className="space-y-1.5"> <label className="text-muted-foreground font-mono text-xs">Engineering Team Size</label> <div className="grid grid-cols-4 gap-1.5"> {['1-10', '11-50', '50-200', '200+'].map((size) => ( <button key={size} type="button" className={cn( 'rounded-lg border py-1.5 text-center font-mono text-xs transition-colors', teamSize === size ? 'border-primary bg-primary text-primary-foreground font-semibold shadow-xs' : 'border-border bg-card text-muted-foreground hover:text-foreground', )} onClick={() => setTeamSize(size)} > {size} </button> ))} </div> </div> {/* Framework Focus */} <div className="space-y-1.5"> <label className="text-muted-foreground font-mono text-xs">Primary Architecture Focus</label> <div className="grid grid-cols-3 gap-1.5"> {['Vue / Nuxt', 'React / Next', 'Dual-Framework'].map((fw) => ( <button key={fw} type="button" className={cn( 'rounded-lg border py-1.5 text-center font-mono text-xs transition-colors', frameworkFocus === fw ? 'border-primary bg-primary text-primary-foreground font-semibold shadow-xs' : 'border-border bg-card text-muted-foreground hover:text-foreground', )} onClick={() => setFrameworkFocus(fw)} > {fw} </button> ))} </div> </div> <Button className="mt-2 h-10 w-full gap-1.5 font-mono text-xs shadow-md" onClick={submitDemoRequest}> <span>Confirm & Pick Time Slot</span> <ArrowRight className="size-3.5" /> </Button> </div> ) : ( <div className="space-y-4 py-12 text-center"> <div className="border-success/20 bg-success/10 text-success mx-auto flex size-12 items-center justify-center rounded-full border"> <CheckCircle2 className="size-6" /> </div> <div className="space-y-1"> <h4 className="text-foreground font-mono text-base font-bold">Demo Request Received</h4> <p className="text-muted-foreground mx-auto max-w-xs text-xs"> We've sent calendar access to{' '} <span className="text-foreground font-mono font-semibold">{email}</span>. Check your inbox to select a time. </p> </div> <Button size="sm" variant="outline" className="font-mono text-xs" onClick={() => setIsSubmitted(false)}> Submit Another Request </Button> </div> )} </Card> </div> </div> </section> ) } export default CtaSplitDemoRequestModal
Raw manifest:https://uipkge.dev/r/react/cta-split-demo-request-modal.json