Components
Loading preview...
A stunning animated retro grid component with customizable colors, scanlines, and neon glow effects. Perfect for synthwave, vaporwave, and cyberpunk UI designs. Features smooth 3D perspective animation, dynamic gradient sky, and interactive color controls. Built with React, TypeScript, and Canvas API. Fully responsive and optimized for performance. Ideal for landing pages, hero sections, and nostalgic 80s-inspired web applications. Easy to integrate with customizable props for grid color, CRT scanlines, and glow effects.
npx shadcn@latest add https://21st.dev/r/waleedkibhen/retro-gridimport { useState } from "react";
import Component from "@/components/ui/retro-grid";
export default function Demo() {
const [gridColor, setGridColor] = useState("#ff00ff");
const [showScanlines, setShowScanlines] = useState(true);
const [glowEffect, setGlowEffect] = useState(true);
const [panelPosition, setPanelPosition] = useState({ x: 24, y: 24 });
const [isDragging, setIsDragging] = useState(false);
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
return (
<div className="relative w-full h-screen">
<Component
gridColor={gridColor}
showScanlines={showScanlines}
glowEffect={glowEffect}
className="fixed inset-0 w-full h-full"
/>
<div
className="absolute bg-black/80 backdrop-blur-sm p-6 rounded-lg border-2 border-purple-500/50 shadow-xl cursor-move select-none"
style={{
left: `${panelPosition.x}px`,
top: `${panelPosition.y}px`,
}}
onMouseDown={(e) => {
setIsDragging(true);
setDragOffset({
x: e.clientX - panelPosition.x,
y: e.clientY - panelPosition.y,
});
}}
onMouseMove={(e) => {
if (isDragging) {
setPanelPosition({
x: e.clientX - dragOffset.x,
y: e.clientY - dragOffset.y,
});
}
}}
onMouseUp={() => setIsDragging(false)}
onMouseLeave={() => setIsDragging(false)}
>
<h2 className="text-purple-300 font-bold text-lg mb-4 tracking-wide">
RETRO CONTROLS
</h2>
<div className="space-y-4">
<div>
<label className="text-purple-200 text-sm block mb-2">Grid Color</label>
<div className="flex gap-2 flex-wrap">
{["#ff00ff", "#00ffff", "#ff0066", "#00ff00", "#ffff00", "#ff6600"].map(
(color) => (
<button
key={color}
onClick={() => setGridColor(color)}
className={`w-10 h-10 rounded border-2 transition-all ${
gridColor === color ? "border-white scale-110" : "border-gray-600"
}`}
style={{ backgroundColor: color }}
/>
)
)}
<input
type="color"
value={gridColor}
onChange={(e) => setGridColor(e.target.value)}
className="w-10 h-10 rounded cursor-pointer"
/>
</div>
</div>
<div className="space-y-2">
<label className="flex items-center gap-3 text-purple-200 text-sm cursor-pointer">
<input
type="checkbox"
checked={showScanlines}
onChange={(e) => setShowScanlines(e.target.checked)}
className="w-4 h-4"
/>
<span>CRT Scanlines</span>
</label>
<label className="flex items-center gap-3 text-purple-200 text-sm cursor-pointer">
<input
type="checkbox"
checked={glowEffect}
onChange={(e) => setGlowEffect(e.target.checked)}
className="w-4 h-4"
/>
<span>Neon Glow</span>
</label>
</div>
</div>
</div>
</div>
);
}