Docs

VPN Connection

Shows the Vpn Connectivity

requires interactionclick

Installation

Install dependencies

npm install lucide-react

Run the following command

It will create a new file called vpn-widget.tsx inside the components/animata/widget directory.

mkdir -p components/animata/widget && touch components/animata/widget/vpn-widget.tsx

Paste the code

Open the newly created file and paste the following code:

"use client";
import { useState } from "react";
import { FlagIcon, ShieldBan, ShieldCheck } from "lucide-react";
 
import { cn } from "@/lib/utils";
 
interface SlidingButtonProps {
  initialConnected?: boolean;
  className?: string;
}
 
interface VpnConnectionProps {
  userName?: string;
  latency?: string;
  netSpeed?: string;
  className?: string;
  defaultConnected?: boolean;
}
 
function SlidingButton({ initialConnected = false, className }: SlidingButtonProps) {
  const [connected, setConnected] = useState(initialConnected);
 
  return (
    <div
      className={cn(
        "relative flex w-full cursor-pointer items-center justify-between overflow-hidden rounded-2xl bg-gray-200/75 transition-colors",
        className,
      )}
      onClick={() => setConnected(!connected)}
    >
      <div className="flex h-12 w-8 items-center justify-center">
        <div
          className={cn("h-3 w-3 rounded-full bg-red-500 transition-opacity", {
            "opacity-0 duration-300": connected,
            "opacity-100": !connected,
          })}
        />
      </div>
      <div
        className={cn(
          "absolute z-10 flex h-11 w-36 flex-1 flex-col items-center justify-center rounded-[14px] bg-white py-2 transition-all duration-200 ease-in-out hover:bg-gray-50/95 active:bg-gray-50/70",
          {
            "left-0.5": connected,
            "left-[34px]": !connected,
          },
        )}
      >
        <strong className="select-none text-sm text-black">
          {connected ? "Connected" : "Disconnected"}
        </strong>
        <span
          className={cn("-mt-1 inline-flex select-none items-center gap-1 text-xs font-semibold", {
            "text-blue-700/50": connected,
            "text-red-700/50": !connected,
          })}
        >
          {connected ? <ShieldCheck size={12} /> : <ShieldBan size={12} />}
          {connected ? "Secured" : "Not Secured"}
        </span>
      </div>
      <div className="flex h-12 w-8 items-center justify-center">
        <div
          className={cn("h-3 w-3 rounded-full bg-green-500 transition-opacity", {
            "opacity-0 duration-300": !connected,
            "opacity-100 group-hover:animate-pulse": connected,
          })}
        />
      </div>
    </div>
  );
}
 
export default function VpnConnection({
  userName = "Animata",
  latency = "53ms",
  netSpeed = "57.4",
  className,
  defaultConnected = false,
}: VpnConnectionProps) {
  return (
    <div className={className}>
      <div className={cn("group flex size-52 flex-col rounded-3xl bg-blue-900 p-0.5")}>
        <div className="flex items-center gap-2 px-4 pb-2 pt-4">
          <FlagIcon size={24} className="fill-yellow-500 text-yellow-500" />
          <h3 className={cn("text-xl font-semibold tracking-wide text-yellow-500")}>{userName}</h3>
        </div>
        <div className={cn("group flex w-full flex-1 flex-col gap-1 rounded-[22px] bg-white p-3")}>
          <div
            className={cn(
              "inline-flex max-w-fit items-center justify-center gap-1 rounded-xl bg-green-100 px-2 text-sm font-semibold",
            )}
          >
            <div className="animate-sl h-2 w-2 animate-pulse rounded-full bg-green-500" />
            <h6 className="text-green-600">{latency}</h6>
          </div>
          <h2 className={cn("mt-2 text-4xl font-semibold text-zinc-900")}>
            {netSpeed}
            <sup className={cn("font-bold tracking-tighter text-gray-700/50")}>mb</sup>
          </h2>
          <div className="mt-auto">
            <SlidingButton initialConnected={defaultConnected} />
          </div>
        </div>
      </div>
    </div>
  );
}

Credits

Built by Chiranjibi Ranabhat yevhenyurchuk.com