
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
Split-pane enterprise demo request workbench with benefit highlights, team size selectors, framework focus filters, and interactive submission feedback.
Also available for Vue ->$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.jsonnpx shadcn@latest add @uipkge-react/cta-split-demo-request-modalInstalls to:components/blocks/| Name | Type / Values | Default | Required |
|---|---|---|---|
className | string | — | optional |
'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="[email protected]"
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