Magic Input
Preview
Code
"use client";
import { cn } from "@/lib/utils";
import React, { useEffect, useRef, useState, type FC } from "react";
interface MagicInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
containerClassName?: string;
}
const MagicInput: FC<MagicInputProps> = ({
className,
containerClassName,
...props
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [isFocused, setIsFocused] = useState(false);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
let w = (canvas.width = canvas.offsetWidth);
let h = (canvas.height = canvas.offsetHeight);
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, w, h);
const cols = Math.floor(w / 20) + 1;
const ypos = Array(cols).fill(0);
const matrix = () => {
if (!ctx) return;
ctx.fillStyle = "#0001";
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = "#a855f7"; // purple-500
ctx.font = "15pt monospace";
ypos.forEach((y, ind) => {
const text = String.fromCharCode(Math.random() * 128);
const x = ind * 20;
ctx.fillText(text, x, y);
if (y > 100 + Math.random() * 10000) {
ypos[ind] = 0;
} else {
ypos[ind] = y + 20;
}
});
};
let animationFrameId: number;
const render = () => {
matrix();
animationFrameId = requestAnimationFrame(render);
};
if (isFocused) {
render();
}
const handleResize = () => {
w = canvas.width = canvas.offsetWidth;
h = canvas.height = canvas.offsetHeight;
};
window.addEventListener('resize', handleResize);
return () => {
cancelAnimationFrame(animationFrameId);
window.removeEventListener('resize', handleResize);
};
}, [isFocused]);
return (
<div
className={cn(
"relative w-full max-w-xs p-px rounded-lg",
"bg-gradient-to-r from-purple-500/30 to-indigo-500/30",
"transition-all duration-300",
isFocused && "from-purple-500 to-indigo-500",
containerClassName
)}
>
<div className="relative bg-black rounded-[7px] overflow-hidden">
<canvas ref={canvasRef} className="absolute inset-0 w-full h-full opacity-30 pointer-events-none" />
<input
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
className={cn(
"relative w-full p-3 bg-transparent text-white placeholder:text-gray-500 outline-none",
"focus:ring-0",
className
)}
{...props}
/>
</div>
</div>
);
};
export default MagicInput;