Secure App
An animated secure app authentication component with fingerprint scanning, orbiting security provider icons, and beam animations, perfect for showcasing multi-factor authentication or secure login systems.
Preview
Generate with AI
Want to create this component using AI? Copy the prompt below and paste it into any LLM (ChatGPT, Claude, etc.):
Installation
npx shadcn@latest add https://uiregistry.cappychat.com/registry/secure-app.jsonInstall dependencies
npm i framer-motion clsx tailwind-merge react-iconsAdd util file
lib/utils.ts
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}Copy the source code
components/ui/secure-app.tsx
"use client";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { motion } from "framer-motion";
import type { IconType } from "react-icons";
import { MdEmail } from "react-icons/md";
import { SiAppwrite } from "react-icons/si";
import { FaApple } from "react-icons/fa";
import { SiClerk } from "react-icons/si";
import { RiFirebaseFill } from "react-icons/ri";
import { cn } from "@/lib/utils";
import { SiMongodb } from "react-icons/si";
const fingerprintPaths = [
"M32.18,105.73c0.7-1.11,2.16-1.44,3.27-0.74c1.11,0.7,1.44,2.16,0.74,3.27l-4.81,7.68c-0.7,1.11-2.16,1.44-3.27,0.74c-1.11-0.7-1.44-2.16-0.74-3.27L32.18,105.73L32.18,105.73z",
"M6.57,75.32c0.33,1.27-0.42,2.57-1.69,2.9c-1.27,0.33-2.57-0.42-2.9-1.69c-0.39-1.5-0.73-3.01-1.02-4.54c-0.28-1.52-0.5-3.03-0.66-4.54c-0.1-0.98-0.18-1.98-0.22-2.99C0.02,63.37,0,62.36,0,61.44C0,44.47,6.88,29.11,18,18C29.11,6.88,44.47,0,61.44,0c16.97,0,32.34,6.83,43.47,17.91c11.11,11.06,17.97,26.36,17.97,43.3c0,1.31-1.07,2.38-2.38,2.38c-1.31,0-2.38-1.07-2.38-2.38c0-15.64-6.33-29.74-16.56-39.93C91.3,11.06,77.12,4.76,61.44,4.76c-15.65,0-29.82,6.34-40.08,16.6C11.11,31.62,4.76,45.79,4.76,61.44c0,1.04,0.02,1.97,0.06,2.8c0.04,0.91,0.11,1.82,0.2,2.73c0.15,1.4,0.35,2.79,0.61,4.17C5.89,72.51,6.2,73.9,6.57,75.32L6.57,75.32z",
"M12.97,96.87c-0.99,0.86-2.49,0.75-3.35-0.24c-0.86-0.99-0.75-2.49,0.24-3.35c0.6-0.52,1.13-1.14,1.58-1.86c0.47-0.74,0.86-1.61,1.17-2.6c1.59-5.06,0.63-10.34-0.34-15.69c-0.66-3.64-1.33-7.31-1.3-11.14c0.12-19.6,12.38-35.58,28.42-43.77c6.73-3.44,14.15-5.5,21.63-5.89c7.51-0.39,15.08,0.93,22.07,4.25C98.7,24,111.38,41.37,114.02,72.13c0.11,1.31-0.87,2.46-2.18,2.57c-1.31,0.11-2.46-0.87-2.57-2.18c-2.47-28.79-14.02-44.89-28.21-51.64c-6.26-2.98-13.05-4.15-19.8-3.81c-6.79,0.35-13.55,2.24-19.71,5.38C26.96,29.89,15.82,44.34,15.71,62c-0.02,3.4,0.61,6.86,1.23,10.29c1.08,5.94,2.14,11.8,0.21,17.95c-0.43,1.38-1,2.62-1.69,3.72C14.76,95.07,13.92,96.04,12.97,96.87L12.97,96.87z",
"M109.22,82.01c0-1.32,1.07-2.38,2.38-2.38s2.38,1.07,2.38,2.38v9.98c0,1.32-1.07,2.38-2.38,2.38s-2.38-1.07-2.38-2.38V82.01L109.22,82.01z",
"M20.01,106.56c-0.98,0.87-2.48,0.78-3.35-0.2c-0.87-0.98-0.78-2.48,0.2-3.35c2.95-2.6,5.1-5.96,6.34-10.17c1.28-4.34,1.6-9.61,0.85-15.92c-1.38-6.78-1.63-13.04-0.82-18.69c0.84-5.91,2.84-11.15,5.89-15.63c0.74-1.08,2.22-1.36,3.3-0.62c1.08,0.74,1.36,2.22,0.62,3.3c-2.64,3.87-4.37,8.44-5.11,13.62c-0.73,5.13-0.5,10.84,0.77,17.07c0.03,0.12,0.06,0.24,0.07,0.36c0.84,6.97,0.45,12.88-1.01,17.85C26.26,99.28,23.63,103.36,20.01,106.56L20.01,106.56z",
"M44.18,34.97c-1.14,0.66-2.59,0.27-3.25-0.87c-0.66-1.14-0.27-2.59,0.87-3.25c2.66-1.54,5.5-2.76,8.43-3.65c8.04-2.44,16.77-2.37,24.71,0.41c7.98,2.8,15.15,8.32,20.03,16.77c1.63,2.81,3,5.96,4.06,9.45c1.51,4.98,2.54,10.54,3.07,16.65c0.52,6.01,0.55,12.61,0.09,19.79c0,0.07-0.01,0.13-0.02,0.2l-1.66,16.38c-0.13,1.3-1.29,2.26-2.6,2.13c-1.3-0.13-2.26-1.29-2.13-2.6l1.66-16.4l0-0.01c0.44-6.91,0.41-13.29-0.09-19.1c-0.5-5.82-1.46-11.05-2.86-15.66c-0.94-3.11-2.17-5.92-3.63-8.45c-4.27-7.4-10.53-12.23-17.48-14.67c-6.99-2.45-14.68-2.51-21.77-0.36C49.04,32.53,46.55,33.6,44.18,34.97L44.18,34.97z",
"M38.95,98.15c-0.23,1.29-1.46,2.16-2.75,1.93c-1.29-0.23-2.16-1.46-1.93-2.75c0.55-3.08,0.86-6.53,0.97-10.29c0.11-3.81,0.02-7.98-0.24-12.44c-0.05-0.96-0.14-2.15-0.22-3.31c-0.54-7.59-0.97-13.71,3.47-21.6c0.98-1.74,2.15-3.36,3.55-4.84c1.4-1.48,3.01-2.82,4.84-3.99c0.12-0.08,0.24-0.14,0.37-0.19c2.71-1.3,5.4-2.31,8.09-2.97c2.77-0.68,5.52-0.98,8.23-0.83c1.31,0.07,2.32,1.18,2.25,2.49c-0.07,1.31-1.18,2.32-2.49,2.25c-2.25-0.12-4.54,0.13-6.87,0.7c-2.32,0.57-4.7,1.46-7.12,2.62c-1.47,0.95-2.75,2.01-3.84,3.17c-1.12,1.19-2.07,2.49-2.86,3.91c-3.74,6.66-3.36,12.14-2.88,18.94c0.07,1,0.14,2.04,0.22,3.38c0.26,4.54,0.35,8.84,0.24,12.83C39.85,91.22,39.53,94.9,38.95,98.15L38.95,98.15z",
"M72.44,44.51c-1.12-0.68-1.47-2.15-0.79-3.26c0.68-1.12,2.14-1.47,3.26-0.79c0.73,0.45,1.44,0.93,2.13,1.45c0.68,0.51,1.35,1.07,2.02,1.68c9.06,8.23,12.13,21.46,12.33,35.3c0.19,13.48-2.34,27.54-4.66,37.91c-0.28,1.28-1.55,2.09-2.83,1.8c-1.28-0.28-2.09-1.55-1.8-2.83c2.26-10.12,4.74-23.81,4.55-36.83c-0.18-12.66-2.88-24.65-10.79-31.84c-0.55-0.5-1.12-0.97-1.69-1.4C73.6,45.25,73.02,44.86,72.44,44.51L72.44,44.51z",
"M43.15,119.69c-0.76,1.07-2.24,1.33-3.31,0.57c-1.07-0.76-1.33-2.24-0.57-3.31c1.68-2.37,3.1-4.97,4.26-7.79c1.16-2.84,2.06-5.93,2.68-9.27c1.16-6.23,0.61-14.17,0.08-21.67c-0.18-2.53-0.35-5-0.46-7.54c-0.16-3.71-0.23-7.35,0.46-10.66c0.75-3.61,2.37-6.74,5.62-9.02c0.73-0.51,1.52-0.97,2.37-1.36c0.85-0.39,1.77-0.74,2.76-1.02c0.74-0.21,1.47-0.38,2.18-0.5c4.87-0.83,8.73,0.43,11.71,3.03c2.83,2.47,4.75,6.11,5.93,10.24c0.35,1.24,0.64,2.53,0.87,3.85c0.12,0.72,0.23,1.45,0.31,2.18c0.08,0.72,0.15,1.46,0.2,2.22c0.5,7.54,0.17,16.95-0.85,26.16c-0.98,8.83-2.6,17.53-4.75,24.3c-0.4,1.25-1.73,1.94-2.98,1.55c-1.25-0.4-1.94-1.73-1.55-2.98c2.04-6.43,3.59-14.81,4.54-23.38c0.99-8.95,1.31-18.06,0.83-25.34c-0.04-0.63-0.1-1.29-0.18-1.97c-0.07-0.64-0.17-1.28-0.28-1.91c-0.2-1.14-0.45-2.26-0.75-3.35c-0.94-3.31-2.4-6.15-4.48-7.96c-1.92-1.67-4.47-2.47-7.77-1.91c-0.53,0.09-1.09,0.22-1.68,0.39c-0.77,0.22-1.46,0.47-2.07,0.76c-0.62,0.29-1.17,0.6-1.64,0.93c-2.09,1.46-3.16,3.59-3.68,6.09c-0.58,2.79-0.51,6.1-0.37,9.49c0.1,2.25,0.28,4.81,0.46,7.43c0.54,7.78,1.12,16.01-0.16,22.85c-0.68,3.65-1.67,7.04-2.96,10.2C46.64,114.11,45.04,117.02,43.15,119.69L43.15,119.69z",
"M59.44,62.15c-0.24-1.29,0.62-2.53,1.91-2.76c1.29-0.24,2.53,0.62,2.76,1.91c1.21,6.52,1.79,13.11,1.81,19.73c0.02,6.59-0.52,13.21-1.54,19.84c-0.2,1.29-1.41,2.18-2.71,1.98c-1.29-0.2-2.18-1.41-1.98-2.71c0.99-6.38,1.51-12.76,1.49-19.11C61.16,74.7,60.6,68.4,59.44,62.15L59.44,62.15z",
"M56.72,108.31c0.28-1.28,1.55-2.09,2.83-1.8c1.28,0.28,2.09,1.55,1.8,2.83l-2.08,9.37c-0.28,1.28-1.55,2.09-2.83,1.8c-1.28-0.28-2.09-1.55-1.8-2.83L56.72,108.31L56.72,108.31z",
];
interface SecureAppProps {
className?: string;
}
interface OrbitNodeConfig {
id: string;
direction: "left" | "right" | "center";
icon: IconType;
offset: { x: number; y: number };
connector: string;
}
// Center-based coordinates: (0,0) is center, nodes positioned at fixed pixel offsets
const ORBIT_CONFIG: OrbitNodeConfig[] = [
{
id: "top-left",
direction: "left",
icon: MdEmail,
offset: { x: -106, y: -76 },
connector: "M -106 -76 L -50 -76 Q -35 -76 -25 -50 T 0 0",
},
{
id: "top-right",
direction: "right",
icon: SiAppwrite,
offset: { x: 106, y: -76 },
connector: "M 106 -76 L 50 -76 Q 35 -76 25 -50 T 0 0",
},
{
id: "mid-right",
direction: "right",
icon: FaApple,
offset: { x: 106, y: 0 },
connector: "M 106 0 L 0 0",
},
{
id: "bottom-right",
direction: "right",
icon: SiMongodb,
offset: { x: 106, y: 76 },
connector: "M 106 76 L 50 76 Q 35 76 25 50 T 0 0",
},
{
id: "bottom-left",
direction: "left",
icon: SiClerk,
offset: { x: -106, y: 76 },
connector: "M -106 76 L -50 76 Q -35 76 -25 50 T 0 0",
},
{
id: "mid-left",
direction: "left",
icon: RiFirebaseFill,
offset: { x: -106, y: 0 },
connector: "M -106 0 L 0 0",
},
];
const RINGS = [
{
scale: (240 / 512) * 100,
className: "border border-neutral-200/20 dark:border-white/5",
},
{
scale: (340 / 512) * 100,
className: "border border-neutral-300/30 dark:border-white/10",
},
{
scale: (440 / 512) * 100,
className: "border border-neutral-400/40 dark:border-neutral-400/15",
},
{
scale: (540 / 512) * 100,
className: "border border-neutral-500/30 dark:border-neutral-500/10",
},
];
const DASHED_RING = {
scale: (208 / 512) * 100,
className:
"border border-neutral-400/40 dark:border-neutral-400/20 border-dashed",
};
const CORE_RING = {
scale: (72 / 512) * 100,
className:
"border border-neutral-300/50 dark:border-neutral-300/30 bg-white/80 dark:bg-black/80",
};
const DIRECTION_SHIFT: Record<OrbitNodeConfig["direction"], number> = {
left: -12,
right: 12,
center: 0,
};
const FINGERPRINT_VARIANTS = {
idle: {
stroke: "transparent",
fill: "rgba(115,115,115,0.15)",
opacity: 0.4,
},
active: {
stroke: "transparent",
fill: "#000000", // Black for light mode, will be overridden in dark mode
opacity: 1,
},
activeDark: {
stroke: "transparent",
fill: "#ffffff", // White for dark mode
opacity: 1,
},
};
const BEAM_DURATION_MS = 900;
const NODE_NUDGE_DURATION = 190;
type OrbitPhase = "scanning" | "beam" | "hold";
export const SecureApp = memo(({ className }: SecureAppProps) => {
const [fingerprintStep, setFingerprintStep] = useState(0);
const [scanIteration, setScanIteration] = useState(0);
const [beamCycle, setBeamCycle] = useState(0);
const [beamActive, setBeamActive] = useState(false);
const [nodesShifted, setNodesShifted] = useState(false);
const [phase, setPhase] = useState<OrbitPhase>("scanning");
const cancelRef = useRef(false);
const timeoutsRef = useRef<number[]>([]);
const clearAllTimeouts = useCallback(() => {
timeoutsRef.current.forEach((timeoutId) => {
clearTimeout(timeoutId);
});
timeoutsRef.current = [];
}, []);
const sleep = useCallback((ms: number) => {
return new Promise<void>((resolve) => {
const timeoutId = window.setTimeout(() => {
timeoutsRef.current = timeoutsRef.current.filter(
(id) => id !== timeoutId
);
resolve();
}, ms);
timeoutsRef.current.push(timeoutId);
});
}, []);
const orbitNodes = useMemo(() => ORBIT_CONFIG, []);
const runSequence = useCallback(async () => {
setPhase("scanning");
setFingerprintStep(0);
if (cancelRef.current) return;
await sleep(220);
const totalPaths = fingerprintPaths.length;
for (let i = 0; i < totalPaths; i++) {
if (cancelRef.current) return;
setFingerprintStep(i + 1);
await sleep(95);
}
setFingerprintStep(totalPaths);
if (cancelRef.current) return;
await sleep(200);
if (cancelRef.current) return;
setPhase("beam");
setBeamActive(true);
setBeamCycle((iteration) => iteration + 1);
await sleep(Math.floor(BEAM_DURATION_MS * 0.6));
if (cancelRef.current) return;
setNodesShifted(true);
await sleep(NODE_NUDGE_DURATION);
if (cancelRef.current) return;
setNodesShifted(false);
const remainingBeam = Math.max(
0,
Math.floor(BEAM_DURATION_MS * 0.4) - NODE_NUDGE_DURATION
);
if (remainingBeam > 0) {
await sleep(remainingBeam);
if (cancelRef.current) return;
}
setBeamActive(false);
setPhase("hold");
await sleep(480);
if (cancelRef.current) return;
setScanIteration((iteration) => iteration + 1);
}, [sleep]);
useEffect(() => {
cancelRef.current = false;
const loop = async () => {
while (!cancelRef.current) {
await runSequence();
}
};
loop();
return () => {
cancelRef.current = true;
clearAllTimeouts();
};
}, [clearAllTimeouts, runSequence]);
const fingerprintPathsMemo = useMemo(() => fingerprintPaths, []);
const totalFingerprintPaths = fingerprintPathsMemo.length;
const isScanningPhase =
phase === "scanning" && fingerprintStep < totalFingerprintPaths;
return (
<div>
<div
className={cn(
"relative flex items-center mx-auto justify-center w-full max-w-[500px] h-[300px] md:h-[400px] rounded-[28px]",
className
)}
>
<div className="relative w-full h-full rounded-[24px]">
{/* SVG Connectors - sized to match node positions */}
<svg
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10 pointer-events-none"
width="212"
height="152"
viewBox="-106 -76 212 152"
>
<defs>
<linearGradient id="connectorGradientLeft" x1="-106" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0%" stopColor="#6B7280" stopOpacity="0.6" />
<stop offset="100%" stopColor="#9CA3AF" stopOpacity="0.2" />
</linearGradient>
<linearGradient id="connectorGradientRight" x1="106" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0%" stopColor="#6B7280" stopOpacity="0.6" />
<stop offset="100%" stopColor="#9CA3AF" stopOpacity="0.2" />
</linearGradient>
<linearGradient id="beamGradientLight" x1="106" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0%" stopColor="#000000" stopOpacity="0" />
<stop offset="100%" stopColor="#000000" stopOpacity="1" />
</linearGradient>
<linearGradient id="beamGradientDark" x1="106" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0%" stopColor="#ffffff" stopOpacity="0" />
<stop offset="100%" stopColor="#ffffff" stopOpacity="1" />
</linearGradient>
</defs>
{orbitNodes.map((node) => (
<path
key={node.id}
d={node.connector}
fill="none"
stroke="#6B7280"
strokeOpacity={0.5}
strokeWidth={1}
strokeLinecap="round"
strokeLinejoin="round"
/>
))}
{beamActive &&
orbitNodes.map((node) => (
<g key={`${node.id}-beam-${beamCycle}`}>
<motion.path
d={node.connector}
fill="none"
stroke="url(#beamGradientLight)"
strokeWidth={1}
strokeLinecap="round"
initial={{ pathLength: 0.08, pathOffset: 1, opacity: 0 }}
animate={{
pathLength: 0.1,
pathOffset: 0.1,
opacity: [0, 0.9, 0],
}}
transition={{
duration: BEAM_DURATION_MS / 1000,
ease: "easeInOut",
}}
className="dark:hidden"
/>
<motion.path
d={node.connector}
fill="none"
stroke="url(#beamGradientDark)"
strokeWidth={1}
strokeLinecap="round"
initial={{ pathLength: 0.08, pathOffset: 1, opacity: 0 }}
animate={{
pathLength: 0.1,
pathOffset: 0.1,
opacity: [0, 0.9, 0],
}}
transition={{
duration: BEAM_DURATION_MS / 1000,
ease: "easeInOut",
}}
className="hidden dark:block"
/>
</g>
))}
</svg>
{/* Center fingerprint button */}
<div className="pointer-events-none absolute left-1/2 top-1/2 z-10 flex h-12 w-12 md:h-20 md:w-20 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-neutral-300 dark:border-neutral-700 bg-gradient-to-br from-neutral-200 via-neutral-300 to-neutral-400 dark:from-neutral-800 dark:via-neutral-900 dark:to-black">
{/* Animated border overlay */}
<motion.div
className="absolute inset-0 rounded-full border-[2px] border-neutral-400/70 dark:border-neutral-400/30 bg-neutral-200/20 dark:bg-neutral-100/10 pointer-events-none"
initial={{ opacity: 0, scale: 1 }}
animate={{
opacity: nodesShifted ? 1 : 0,
scale: nodesShifted ? [1, 1.15, 1.08] : 1,
}}
transition={{
scale: {
duration: 0.4,
ease: [0.34, 1.56, 0.64, 1],
},
opacity: {
duration: 0.2,
ease: "easeOut",
},
}}
/>
<div className="relative h-9 w-9 md:h-16 md:w-16">
{isScanningPhase ? (
<motion.div
key={`scan-halo-${scanIteration}`}
className="absolute inset-0 rounded-full border border-black/20 dark:border-white/20"
initial={{ opacity: 0.35, scale: 0.92 }}
animate={{
opacity: [0.4, 0.1, 0.4],
scale: [0.92, 1.05, 0.92],
}}
transition={{
duration: 1.8,
ease: "easeInOut",
repeat: Infinity,
}}
/>
) : (
<div className="absolute inset-0 rounded-full border border-black/18 dark:border-white/18 opacity-40" />
)}
<motion.svg
viewBox="0 0 128 128"
className="absolute inset-0"
strokeWidth={1}
fill="none"
style={{ transform: "scale(0.8)", transformOrigin: "center" }}
>
{fingerprintPathsMemo.map((d, index) => (
<g key={d}>
{/* Light mode fingerprint */}
<motion.path
d={d}
variants={FINGERPRINT_VARIANTS}
initial="idle"
animate={fingerprintStep > index ? "active" : "idle"}
transition={{ duration: 0.32, ease: "easeOut" }}
strokeLinecap="round"
strokeLinejoin="round"
className="dark:hidden"
/>
{/* Dark mode fingerprint */}
<motion.path
d={d}
variants={FINGERPRINT_VARIANTS}
initial="idle"
animate={fingerprintStep > index ? "activeDark" : "idle"}
transition={{ duration: 0.32, ease: "easeOut" }}
strokeLinecap="round"
strokeLinejoin="round"
className="hidden dark:block"
/>
</g>
))}
</motion.svg>
{isScanningPhase ? (
<motion.div
key={`scan-bar-${scanIteration}`}
className="absolute inset-0 rounded-full bg-[radial-gradient(circle,_rgba(0,0,0,0.28)_0%,_rgba(255,255,255,0)_70%)] dark:bg-[radial-gradient(circle,_rgba(255,255,255,0.28)_0%,_rgba(0,0,0,0)_70%)]"
initial={{ opacity: 0.15, scale: 0.85 }}
animate={{ opacity: [0.2, 0.5, 0.2], scale: [0.85, 1, 0.85] }}
transition={{
duration: 1.2,
repeat: Infinity,
ease: "easeInOut",
}}
/>
) : (
<div className="absolute inset-0 rounded-full bg-[radial-gradient(circle,_rgba(0,0,0,0.22)_0%,_rgba(255,255,255,0.18)_55%,_rgba(255,255,255,0)_85%)] dark:bg-[radial-gradient(circle,_rgba(255,255,255,0.22)_0%,_rgba(0,0,0,0.18)_55%,_rgba(0,0,0,0)_85%)]" />
)}
</div>
</div>
{orbitNodes.map((node) => (
<motion.div
key={node.id}
className="pointer-events-none absolute z-10 backdrop-blur-2xl flex md:h-14 w-11 h-11 md:w-14 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-neutral-300/75 dark:border-neutral-600/75 bg-gradient-to-br from-neutral-200/85 via-neutral-300/90 to-neutral-400/95 dark:from-neutral-800/85 dark:via-neutral-900/90 dark:to-black/95 "
animate={{
x: nodesShifted ? DIRECTION_SHIFT[node.direction] : 0,
}}
transition={{
type: "spring",
stiffness: 220,
damping: 16,
}}
style={{
left: `calc(50% + ${node.offset.x}px)`,
top: `calc(50% + ${node.offset.y}px)`,
}}
>
<node.icon className="md:h-6 md:w-6 w-5 h-5 text-black dark:text-white" />
</motion.div>
))}
</div>
</div>
</div>
);
});
SecureApp.displayName = "SecureApp";
export default SecureApp;
Usage
import { SecureApp } from "@/components/ui/secure-app";
export default function MyComponent() {
return (
<div className="">
<SecureApp />
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Optional additional CSS classes |
Real-Time Editor
An optimized, animated text editor component with smooth selection animations, toolbar with animated cursor, text formatting (bold/italic/underline), color changes, and alignment controls.
Secure Vault
An animated secure vault component with sequential circuit connection animations, lock opening effect, and vault door opening animation, perfect for showcasing secure storage or data protection systems.
