Map of USA

This component centers around a fully interactive SVG-based United States map that responds dynamically to user hover interactions. Each state is individually mapped and detectable, enabling precise geographic targeting and real-time visual feedback. When a user hovers over a state, it is elevated within the SVG layer hierarchy to emphasize selection while triggering a smoothly positioned tooltip that follows the cursor. The tooltip displays the active state name with refined animated styling, creating a seamless and engaging exploration experience across the map. The interaction system ensures accurate cursor alignment, smooth transitions, and consistent responsiveness across all regions. By leveraging SVG manipulation, intelligent layering, and motion-enhanced UI feedback, this implementation transforms a static U.S. map into a highly interactive geographic interface — ideal for dashboards, analytics platforms, educational tools, and modern web applications.

Implementation

Usage Guide

Integrate the component into your project by importing the vector asset and wrapping it in our motion container.

Fully Responsive
Dark Mode Ready
Download SVG Component Code

Parent Component. SVG component is wrapped into this. Just Copy-PASTE-USE

.tsx
"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import UsaMap from "./UsaMap";

export default function MapPositionUsa() {
  const [tooltip, setTooltip] = useState<{
    name: string;
    x: number;
    y: number;
  } | null>(null);
  const [hover, setHover] = useState(false);

  const handleMouseMove = (e: React.MouseEvent<SVGPathElement>) => {
    const target = e.currentTarget;
    const name = target.dataset.name;

    if (!name) return;

    target.parentNode?.appendChild(target);

    setTooltip({
      name,
      x: e.clientX,
      y: e.clientY,
    });

    setHover(true);
  };

  const handleMouseLeave = () => {
    setTooltip(null);
    setHover(false);
  };

  return (
    <div className="relative w-full min-h-screen bg-white dark:bg-[#050505] overflow-hidden flex justify-center items-center transition-colors duration-500">
      
      <AnimatePresence>
        {tooltip && (
          <motion.div
            initial={{ opacity: 0, scale: 0.9, y: 20 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.95, y: 10 }}
            transition={{ type: "spring", stiffness: 150, damping: 20 }}
            className="fixed z-50 pointer-events-none"
            style={{
              left: tooltip.x,
              top: tooltip.y,
              transform: "translate(-50%, -50%)",
            }}
          >
          
            <motion.div
              initial={{ height: 0 }}
              animate={{ height: 140 }}
              className="absolute -top-[160px] left-0 -translate-x-1/2 w-px bg-gradient-to-b from-black dark:from-white via-black/10 to-transparent opacity-30"
            />

         
            <div className="absolute z-30 -top-[240px] -left-36 w-72">
              <div className="relative px-6 py-6 bg-white/90 dark:bg-black/90 backdrop-blur-xl border border-black/10 dark:border-white/10 shadow-2xl overflow-hidden">
   
                <div className="absolute top-0 left-0 w-2 h-2 border-t border-l border-black dark:border-white opacity-20" />
                <div className="absolute bottom-0 right-0 w-2 h-2 border-b border-r border-black dark:border-white opacity-20" />

                <div className="flex justify-between items-center mb-4">
                  <span className="font-mono text-[9px] uppercase tracking-[0.3em] opacity-40">
                    Geo.Registry
                  </span>
                  <div className="h-1 w-1 rounded-full bg-black dark:bg-white animate-pulse" />
                </div>

                <h2 className="text-3xl font-extralight tracking-tighter text-black dark:text-white uppercase">
                  {tooltip.name}
                </h2>

                <div className="mt-6 flex justify-between items-end border-t border-black/5 dark:border-white/5 pt-4">
                  <div className="space-y-1">
                    <p className="font-mono text-[8px] opacity-30">X_POS</p>
                    <p className="font-mono text-[10px] tabular-nums">
                      {tooltip.x.toFixed(1)}
                    </p>
                  </div>
                  <div className="space-y-1 text-right">
                    <p className="font-mono text-[8px] opacity-30">Y_POS</p>
                    <p className="font-mono text-[10px] tabular-nums">
                      {tooltip.y.toFixed(1)}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>


      <motion.div
        className="w-full h-full flex justify-center items-center"
        animate={{
          rotateX: hover ? 2 : 0,
          rotateY: hover ? -2 : 0,
        }}
        transition={{ type: "spring", stiffness: 50, damping: 20 }}
      >
        <div className="w-full max-w-5xl px-12 transition-all duration-700">
          <UsaMap
            onMouseMove={handleMouseMove}
            onMouseLeave={handleMouseLeave}
            hover={hover}
            setHover={setHover}
            toolTipName={tooltip ? tooltip.name : ""}
          />
        </div>
      </motion.div>


      <div
        className="absolute inset-0 pointer-events-none opacity-[0.03] dark:opacity-[0.07]"
        style={{
          backgroundImage: `radial-gradient(circle, currentColor 1px, transparent 1px)`,
          backgroundSize: "40px 40px",
        }}
      />
    </div>
  );
}