Hero Bento Preview Grid
blockmarketingAsymmetric 3-column bento hero section with interactive OKLCH palette customizer, dual-framework parity toggle, bundle bloat calculator, and edge latency telemetry.
Installation
$pnpm dlx shadcn@latest add https://uipkge.dev/r/react/hero-bento-preview-grid.json$npx shadcn@latest add https://uipkge.dev/r/react/hero-bento-preview-grid.json$yarn dlx shadcn@latest add https://uipkge.dev/r/react/hero-bento-preview-grid.json$bunx shadcn@latest add https://uipkge.dev/r/react/hero-bento-preview-grid.jsonNamed registry:
npx shadcn@latest add @uipkge-react/hero-bento-preview-gridInstalls 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/HeroBentoPreviewGrid.tsx13.2 kB
'use client' import * as React from 'react' import { Activity, ArrowRight, CheckCircle2, Code2, Cpu, Layers, Moon, Palette, Play, Sun, Zap } from 'lucide-react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { cn } from '@/lib/utils' // Tile 1: OKLCH Palette preview state const colorThemes = [ { name: 'Emerald', hue: 'oklch(0.65 0.22 145)', hex: '#10b981' }, { name: 'Indigo', hue: 'oklch(0.60 0.24 275)', hex: '#6366f1' }, { name: 'Amber', hue: 'oklch(0.75 0.18 70)', hex: '#f59e0b' }, { name: 'Rose', hue: 'oklch(0.65 0.24 15)', hex: '#f43f5e' }, ] export interface HeroBentoPreviewGridProps { className?: string } export function HeroBentoPreviewGrid({ className }: HeroBentoPreviewGridProps) { const [activeColorIndex, setActiveColorIndex] = React.useState(0) const [isDarkPreview, setIsDarkPreview] = React.useState(true) const [activeFramework, setActiveFramework] = React.useState<'vue' | 'react'>('vue') const [componentCount, setComponentCount] = React.useState(12) const [isRunningQuery, setIsRunningQuery] = React.useState(false) const [queryLatency, setQueryLatency] = React.useState('12ms') const estimatedSavings = (componentCount * 42).toFixed(0) const triggerQuery = () => { setIsRunningQuery(true) setTimeout(() => { setQueryLatency(`${Math.floor(Math.random() * 8) + 8}ms`) setIsRunningQuery(false) }, 400) } return ( <section data-slot="hero-bento-preview-grid" className={cn('bg-background relative overflow-hidden px-4 py-16 sm:px-6 sm:py-24 lg:px-8', className)} > {/* Center Ambient Glow */} <div className="bg-primary/10 pointer-events-none absolute top-1/4 left-1/2 -z-10 h-96 w-full max-w-5xl -translate-x-1/2 -translate-y-1/2 rounded-full blur-xl" /> <div className="mx-auto max-w-7xl space-y-12 text-center"> {/* Headline & Subtitle */} <div className="mx-auto max-w-3xl space-y-5"> <Badge variant="secondary" className="gap-1.5 px-3 py-1 font-mono text-xs shadow-xs"> <Layers className="text-primary size-3.5" /> The Unbundled Design Engineering Platform </Badge> <h1 className="text-foreground text-4xl leading-[1.12] font-bold tracking-tight sm:text-5xl lg:text-6xl"> Everything design engineers need to build at lightspeed. </h1> <p className="text-muted-foreground text-base leading-relaxed sm:text-lg"> Tactile workbenches, OKLCH fluid color palettes, and guaranteed cross-framework parity—composed right in your hero. </p> {/* CTA Buttons */} <div className="flex flex-wrap items-center justify-center gap-3 pt-2"> <Button asChild size="lg" className="gap-2 font-semibold shadow-xs"> <a href="#explore"> <span>Explore 300+ Workbenches</span> <ArrowRight className="size-4" /> </a> </Button> <Button asChild variant="outline" size="lg" className="gap-2 font-medium"> <a href="#docs"> <Code2 className="text-muted-foreground size-4" /> <span>View Architecture</span> </a> </Button> </div> </div> {/* 3-Column Asymmetric Bento Hero Grid */} <div className="mx-auto grid max-w-6xl grid-cols-1 gap-4 pt-4 text-left sm:gap-6 md:grid-cols-3"> {/* Tile 1: OKLCH Theme Customizer (2 Cols) */} <Card className="border-border bg-card flex flex-col justify-between space-y-6 rounded-2xl p-6 shadow-sm md:col-span-2"> <div className="space-y-2"> <div className="flex items-center justify-between"> <span className="text-primary inline-flex items-center gap-1.5 font-mono text-xs font-semibold"> <Palette className="size-3.5" /> OKLCH Dynamic Theme Engine </span> <Badge variant="outline" className="font-mono text-xs"> Zero Runtime CSS </Badge> </div> <h3 className="text-foreground text-lg font-bold">Interactive Palette & Contrast Synthesizer</h3> <p className="text-muted-foreground text-xs"> Select a brand accent and watch UI components dynamically adjust perceptual contrast. </p> </div> {/* Color Buttons & Live Preview */} <div className="border-border bg-background/60 space-y-4 rounded-xl border p-4"> <div className="flex items-center justify-between"> <div className="flex items-center gap-2"> {colorThemes.map((c, idx) => ( <button key={c.name} type="button" className={cn( 'size-6 rounded-full border-2 transition-transform active:scale-90', activeColorIndex === idx ? 'border-foreground scale-125 shadow-xs' : 'border-transparent opacity-70 hover:opacity-100', )} style={{ backgroundColor: c.hex }} onClick={() => setActiveColorIndex(idx)} /> ))} </div> <div className="text-muted-foreground flex items-center gap-1 font-mono text-xs"> <span>Mode:</span> <button type="button" className="border-border hover:bg-muted rounded border p-1 transition-[colors,transform] duration-150 active:scale-90" onClick={() => setIsDarkPreview(!isDarkPreview)} > {!isDarkPreview ? ( <Sun className="text-warning size-3.5" /> ) : ( <Moon className="text-muted-foreground size-3.5" /> )} </button> </div> </div> {/* Live Button Demo with Active Hue */} <div className="flex flex-wrap items-center gap-3 pt-2"> <button type="button" className="rounded-lg px-4 py-2 text-xs font-semibold text-white shadow-xs transition-transform active:scale-95" style={{ backgroundColor: colorThemes[activeColorIndex].hex }} > Synthesized Action Button </button> <button type="button" className="border-border bg-background text-foreground hover:bg-muted rounded-lg border px-4 py-2 text-xs font-medium transition-[colors,transform] duration-150 active:scale-95" > Secondary Token </button> </div> </div> </Card> {/* Tile 2: Dual Framework Parity (1 Col) */} <Card className="border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm"> <div className="space-y-2"> <div className="flex items-center justify-between"> <span className="text-success inline-flex items-center gap-1.5 font-mono text-xs font-semibold"> <CheckCircle2 className="size-3.5" /> 100% Mirror Parity </span> </div> <h3 className="text-foreground text-lg font-bold">Vue 3.5 & React 19</h3> <p className="text-muted-foreground text-xs"> Identical CVA variant matrix and AST output across both frameworks. </p> </div> {/* Framework Toggle */} <div className="space-y-3"> <div className="bg-muted/40 border-border grid grid-cols-2 gap-1 rounded-lg border p-1"> <button type="button" className={cn( 'rounded-md py-1.5 font-mono text-xs font-semibold transition-[color,background-color,transform] duration-150 active:scale-95', activeFramework === 'vue' ? 'bg-background text-success shadow-xs' : 'text-muted-foreground', )} onClick={() => setActiveFramework('vue')} > Vue 3.5 SFC </button> <button type="button" className={cn( 'rounded-md py-1.5 font-mono text-xs font-semibold transition-[color,background-color,transform] duration-150 active:scale-95', activeFramework === 'react' ? 'bg-background text-info shadow-xs' : 'text-muted-foreground', )} onClick={() => setActiveFramework('react')} > React 19 TSX </button> </div> {/* Code snippet snippet */} <div className="bg-muted/30 border-border/80 text-muted-foreground rounded-lg border p-3 font-mono text-xs"> <span className="text-primary font-bold">></span> <span> <Button variant="primary"></span> <div className="text-success mt-0.5 font-medium">✓ CVA Type Contract Validated</div> </div> </div> </Card> {/* Tile 3: Zero Bundle Bloat Calculator (1 Col) */} <Card className="border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm"> <div className="space-y-2"> <span className="text-warning inline-flex items-center gap-1.5 font-mono text-xs font-semibold"> <Cpu className="size-3.5" /> Zero NPM Overhead </span> <h3 className="text-foreground text-lg font-bold">Own Your Source Code</h3> <p className="text-muted-foreground text-xs"> Slide to calculate bundle weight saved compared to monolithic packages. </p> </div> {/* Slider Widget */} <div className="border-border bg-background/60 space-y-3 rounded-xl border p-4"> <div className="flex items-center justify-between font-mono text-xs"> <span className="text-muted-foreground">Installed Blocks:</span> <span className="text-foreground font-bold">{componentCount}</span> </div> <input value={componentCount} onChange={(e) => setComponentCount(Number(e.target.value))} type="range" min="1" max="50" className="accent-primary w-full cursor-pointer" /> <div className="border-border/60 flex items-center justify-between border-t pt-1 font-mono text-xs"> <span className="text-muted-foreground">Bundle Saved:</span> <span className="text-success font-mono font-bold">~{estimatedSavings} kB</span> </div> </div> </Card> {/* Tile 4: Sub-millisecond Execution Speed (2 Cols) */} <Card className="border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm md:col-span-2"> <div className="flex items-center justify-between"> <div className="space-y-1"> <span className="text-primary inline-flex items-center gap-1.5 font-mono text-xs font-semibold"> <Zap className="size-3.5" /> Instant Hydration & Zero Latency </span> <h3 className="text-foreground text-lg font-bold">Edge Optimized Architecture</h3> </div> <Button size="sm" variant="outline" className="gap-1.5 font-mono text-xs active:scale-95" onClick={triggerQuery} > {!isRunningQuery ? ( <Play className="size-3 fill-current" /> ) : ( <Activity className="size-3 animate-spin" /> )} <span>Ping Edge</span> </Button> </div> {/* Latency Telemetry Row */} <div className="grid grid-cols-3 gap-3"> <div className="border-border bg-background/50 space-y-0.5 rounded-lg border p-3"> <p className="text-muted-foreground font-mono text-xs">Round-Trip Latency</p> <p className="text-success font-mono text-xl font-bold">{queryLatency}</p> </div> <div className="border-border bg-background/50 space-y-0.5 rounded-lg border p-3"> <p className="text-muted-foreground font-mono text-xs">DOM Mutation Time</p> <p className="text-foreground font-mono text-xl font-bold">< 1.2ms</p> </div> <div className="border-border bg-background/50 space-y-0.5 rounded-lg border p-3"> <p className="text-muted-foreground font-mono text-xs">Accessibility Score</p> <p className="text-primary font-mono text-xl font-bold">100 / 100</p> </div> </div> </Card> </div> </div> </section> ) } export default HeroBentoPreviewGrid
Raw manifest:https://uipkge.dev/r/react/hero-bento-preview-grid.json