shadimage
Forgeui
uibot-detectionsource: ok · refreshed

Bot Detection

Animated radar-style component that simulates real-time bot detection using glowing pulses and scanning motion.

npx shadcn add "https://forgeui.in/r/bot-detection.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Files1 · source cached 10/8/2026, 4:10:17 AM

registry/components/botdetection/botdetection.tsx
"use client";

import { cn } from "@/lib/utils";
import { motion } from "motion/react";
import React, { useEffect, useState } from "react";

type BotDetectionProps = {
  cardTitle?: string;
  cardDescription?: string;
  className?: string;
};

const positions = [
  { top: "80px", left: "34px" },
  { top: "161px", left: "90px" },
  { top: "120px", left: "230px" },
  { top: "203px", left: "165px" },
  { top: "100px", left: "120px" },
  { top: "164px", left: "15px" },
  { top: "238px", left: "61px" },
  { top: "180px", left: "237px" },
  { top: "53px", left: "204px" },
];

const BotDetection = ({
  cardTitle = "Bot Detection",
  cardDescription = "Experience fewer fraudulent sign-ups with our sophisticated, AI-driven bot detection that constantly adapts, ensuring high accuracy and efficient platform protection.",
  className,
}: BotDetectionProps) => {
  const [currentIndex, setCurrentIndex] = useState(0);

  useEffect(() => {
    setCurrentIndex(1);
    const interval = setInterval(() => {
      setCurrentIndex((prev) => (prev + 1) % positions.length);
    }, 3000);

    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div
      className={cn(
        "relative overflow-hidden",
        "h-120 w-full max-w-87.5",
        "rounded-md border border-neutral-800 bg-black",
        className,
      )}
    >
      <div className="absolute left-1/2 h-full max-w-75 min-w-75 -translate-x-1/2">
        <div className="relative h-[80%] w-full">
          <motion.div
            className="pointer-events-none absolute bottom-5 left-37 h-62.5 w-62.5 origin-bottom-left"
            style={{
              background:
                "radial-gradient(circle at 0% 100%, rgba(255, 255, 255, 0.3) 5%, transparent 60%)",
            }}
            initial={{ opacity: 0.7, rotate: -55 }}
            animate={{
              opacity: [0.7, 1, 0.7],
              rotate: [-55, -40, -50, -45, -55, -50, -45, -50, -45, -55],
            }}
            transition={{
              duration: 18,
              repeat: Infinity,
              ease: "easeInOut",
            }}
          />

          <ContainerMask />
          <svg
            width="100%"
            height="100%"
            className="pointer-events-none absolute top-0 left-0 animate-pulse"
          >
            {positions.map((pos, i) => (
              <g key={i}>
                <rect
                  x={pos.left}
                  y={pos.top}
                  width={5}
                  height={5}
                  rx={1}
                  ry={1}
                  fill="#404040"
                />
              </g>
            ))}
          </svg>
          <motion.div
            layoutId="highlight-dot"
            className="absolute flex h-[6.5px] w-[6.5px] -translate-x-[0.5px] -translate-y-[0.5px] items-center justify-center rounded-[1px] border-t border-red-400 bg-red-500 shadow-[0_0_10px_4px_rgba(239,68,68,0.9)]"
            style={positions[currentIndex]}
            transition={{
              type: "spring",
              stiffness: 300,
              damping: 70,
            }}
          >
            <motion.div
              key={`pulse-${currentIndex}`}
              className="absolute -top-1.5 -left-1.5 h-[300%] w-[270%] rounded-full border border-red-500"
              initial={{ scale: 1, opacity: 0.7 }}
              animate={{ scale: 1.7, opacity: [0.7, 1, 0] }}
              transition={{
                duration: 1.2,
                ease: "easeOut",
                delay: 1.3,
              }}
            />
            <motion.div
              key={currentIndex}
              initial={{
                scale: 1,
              }}
              animate={{
                scale: [1, 1.2, 1],
              }}
              transition={{
                duration: 1,
                ease: "easeInOut",
                delay: 1.3,
              }}
              className="absolute -top-1.5 -left-1.5 h-[300%] w-[270%] scale-[1.3] rounded-full border border-red-500 shadow-[0_0_20px_4px_rgba(239,68,68,0.6)]"
            />
          </motion.div>
          <div className="absolute bottom-2 left-1/2 h-28 w-28 -translate-x-1/2 rounded-full border border-neutral-800 bg-black" />
        </div>
      </div>
      <div className="absolute bottom-5 left-0 w-full px-3">
        <h3 className="text-sm font-semibold text-neutral-100">{cardTitle}</h3>
        <p className="mt-2 text-xs text-neutral-400">{cardDescription}</p>
      </div>
    </div>
  );
};

export default BotDetection;

const ContainerMask = () => {
  return (
    <>
      <div className="absolute top-12 left-1/2 h-full w-[130%] -translate-x-1/2 rounded-full border-t border-dashed border-neutral-700/80" />
      <div className="absolute top-25 left-1/2 h-full w-[110%] -translate-x-1/2 rounded-full border-t border-dashed border-neutral-700/80" />
      <div className="absolute top-38 left-1/2 h-full w-full -translate-x-1/2 rounded-full border-t border-dashed border-neutral-700/80" />
      <div className="absolute top-51 left-1/2 h-full w-[80%] -translate-x-1/2 rounded-full border-t border-dashed border-neutral-700/80" />
    </>
  );
};

More from Forgeui

Browse all components in this library →