button update
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
AnimatePresence,
|
||||
motion,
|
||||
SVGMotionProps,
|
||||
Variants,
|
||||
} from "framer-motion";
|
||||
|
||||
interface VpnButtonProps extends SVGMotionProps<SVGSVGElement> {
|
||||
theme?: "light" | "dark";
|
||||
isOn: boolean;
|
||||
}
|
||||
|
||||
const VpnControlButton = ({
|
||||
theme = "dark",
|
||||
isOn,
|
||||
...props
|
||||
}: VpnButtonProps) => {
|
||||
const isDark = theme === "dark";
|
||||
|
||||
// Константы цветов из твоей последней правки
|
||||
const glassBase = isDark ? "#000" : "oklch(1 0 0)";
|
||||
const glassTop = isDark ? "#fff" : "oklch(0.987 0.002 197.1)";
|
||||
const strokeColor = isDark ? "#000" : "#E9E9E9";
|
||||
const powerOffColor = isDark ? "#161B1D" : "oklch(0.56 0.021 213.5)";
|
||||
|
||||
return (
|
||||
<motion.svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={400}
|
||||
height={350}
|
||||
fill="none"
|
||||
viewBox="0 0 400 350"
|
||||
style={{ cursor: "pointer", ...props.style }}
|
||||
whileTap={{ scale: 0.96 }}
|
||||
{...props}
|
||||
>
|
||||
{/* Внешние тени/корпус */}
|
||||
<path
|
||||
fill="url(#a)"
|
||||
fillOpacity={0.4}
|
||||
d="M330 173c0 71.797-58.203 130-130 130S70 244.797 70 173 128.203 43 200 43s130 58.203 130 130Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#b)"
|
||||
fillOpacity={0.15}
|
||||
d="M330 173c0 71.797-58.203 130-130 130S70 244.797 70 173 128.203 43 200 43s130 58.203 130 130Z"
|
||||
/>
|
||||
|
||||
{/* Основное внешнее кольцо */}
|
||||
<path
|
||||
stroke={strokeColor}
|
||||
strokeOpacity={0.8}
|
||||
strokeWidth={15}
|
||||
d="M200 50.5c67.655 0 122.5 54.845 122.5 122.5S267.655 295.5 200 295.5 77.5 240.655 77.5 173 132.345 50.5 200 50.5Z"
|
||||
/>
|
||||
<path
|
||||
stroke="url(#c)"
|
||||
strokeOpacity={0.3}
|
||||
strokeWidth={15}
|
||||
d="M200 50.5c67.655 0 122.5 54.845 122.5 122.5S267.655 295.5 200 295.5 77.5 240.655 77.5 173 132.345 50.5 200 50.5Z"
|
||||
/>
|
||||
|
||||
<g filter="url(#d)">
|
||||
<circle cx={200} cy={173} r={125} fill="url(#e)" fillOpacity={0.5} />
|
||||
<circle cx={200} cy={173} r={125} fill="url(#f)" fillOpacity={0.5} />
|
||||
<circle
|
||||
cx={200}
|
||||
cy={173}
|
||||
r={122.5}
|
||||
stroke={isDark ? "#333" : "#E6E6E6"}
|
||||
strokeOpacity={0.5}
|
||||
strokeWidth={5}
|
||||
/>
|
||||
<circle
|
||||
cx={200}
|
||||
cy={173}
|
||||
r={122.5}
|
||||
stroke="#000"
|
||||
strokeOpacity={0.7}
|
||||
strokeWidth={5}
|
||||
/>
|
||||
</g>
|
||||
|
||||
<g filter="url(#g)">
|
||||
<circle
|
||||
cx={200}
|
||||
cy={173}
|
||||
r={125}
|
||||
stroke="#fff"
|
||||
strokeOpacity={0.8}
|
||||
strokeWidth={5}
|
||||
/>
|
||||
</g>
|
||||
<g filter="url(#h)">
|
||||
<circle
|
||||
cx={200}
|
||||
cy={173}
|
||||
r={125}
|
||||
stroke="url(#i)"
|
||||
strokeOpacity={0.8}
|
||||
strokeWidth={5}
|
||||
/>
|
||||
</g>
|
||||
|
||||
{/* АНИМИРОВАННАЯ ГРУППА J: ВНЕШНИЙ НЕОН */}
|
||||
<g filter="url(#j)">
|
||||
<AnimatePresence>
|
||||
{isOn && (
|
||||
<>
|
||||
<motion.path
|
||||
d="M 200 48 A 125 125 0 0 1 200 298"
|
||||
stroke="#8200DB"
|
||||
strokeWidth={8}
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
exit={{ pathLength: 0 }}
|
||||
transition={{ duration: 1.2, ease: [0.4, 0, 0.2, 1] }}
|
||||
/>
|
||||
<motion.path
|
||||
d="M 200 298 A 125 125 0 0 1 200 48"
|
||||
stroke="#8200DB"
|
||||
strokeWidth={8}
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
exit={{ pathLength: 0 }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
delay: 0.3,
|
||||
ease: [0.4, 0, 0.2, 1],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</g>
|
||||
|
||||
{/* Внутреннее стекло */}
|
||||
<g fillOpacity={0.4} filter="url(#k)">
|
||||
<path
|
||||
fill="url(#l)"
|
||||
d="M275 171c0 41.421-33.579 75-75 75s-75-33.579-75-75 33.579-75 75-75 75 33.579 75 75Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#m)"
|
||||
d="M275 171c0 41.421-33.579 75-75 75s-75-33.579-75-75 33.579-75 75-75 75 33.579 75 75Z"
|
||||
/>
|
||||
</g>
|
||||
|
||||
{/* Среднее кольцо */}
|
||||
<path
|
||||
stroke={isDark ? "#333" : "#E9E9E9"}
|
||||
strokeOpacity={0.8}
|
||||
strokeWidth={5}
|
||||
d="M200 98.5c40.041 0 72.5 32.459 72.5 72.5s-32.459 72.5-72.5 72.5-72.5-32.459-72.5-72.5 32.459-72.5 72.5-72.5Z"
|
||||
/>
|
||||
|
||||
<g filter="url(#o)">
|
||||
<ellipse
|
||||
cx={199.5}
|
||||
cy={171}
|
||||
stroke="url(#p)"
|
||||
strokeOpacity={0.2}
|
||||
strokeWidth={5}
|
||||
rx={71.5}
|
||||
ry={72}
|
||||
/>
|
||||
</g>
|
||||
|
||||
{/* АНИМИРОВАННАЯ ГРУППА Q: ВНУТРЕННЕЕ КОЛЬЦО */}
|
||||
<g filter="url(#q)">
|
||||
<AnimatePresence>
|
||||
{isOn && (
|
||||
<>
|
||||
<motion.path
|
||||
d="M 200 96 A 75 75 0 0 1 200 246"
|
||||
stroke="#8200DB"
|
||||
strokeOpacity={0.5}
|
||||
strokeWidth={8}
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
exit={{ pathLength: 0 }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
delay: 0.1,
|
||||
ease: [0.4, 0, 0.2, 1],
|
||||
}}
|
||||
/>
|
||||
<motion.path
|
||||
d="M 200 246 A 75 75 0 0 1 200 96"
|
||||
stroke="#8200DB"
|
||||
strokeOpacity={0.5}
|
||||
strokeWidth={8}
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
exit={{ pathLength: 0 }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
delay: 0.4,
|
||||
ease: [0.4, 0, 0.2, 1],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</g>
|
||||
|
||||
{/* Символ Power */}
|
||||
<path
|
||||
stroke="url(#r)"
|
||||
strokeWidth={5}
|
||||
d="M250 173c0 27.614-22.386 50-50 50s-50-22.386-50-50m50.5-46v71"
|
||||
/>
|
||||
<g strokeWidth={5} filter="url(#s)">
|
||||
<motion.path
|
||||
strokeOpacity={0.8}
|
||||
animate={{ stroke: isOn ? "#AD46FF" : powerOffColor }}
|
||||
transition={{ duration: 0.8 }}
|
||||
d="M250 173c0 27.614-22.386 50-50 50s-50-22.386-50-50m50.5-46v71"
|
||||
/>
|
||||
<path
|
||||
stroke="url(#t)"
|
||||
strokeOpacity={0.44}
|
||||
d="M250 173c0 27.614-22.386 50-50 50s-50-22.386-50-50m50.5-46v71"
|
||||
/>
|
||||
</g>
|
||||
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="a"
|
||||
x1={200}
|
||||
x2={200}
|
||||
y1={43}
|
||||
y2={299}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={isDark ? "#000" : "#fff"} />
|
||||
<stop
|
||||
offset={1}
|
||||
stopColor={isDark ? "#000" : "#999"}
|
||||
stopOpacity={0.4}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="b"
|
||||
x1={200}
|
||||
x2={200}
|
||||
y1={16}
|
||||
y2={353.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={isDark ? "#000" : "#fff"} />
|
||||
<stop offset={1} stopColor="#8200DB" stopOpacity={0.3} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="c"
|
||||
x1={205}
|
||||
x2={206.5}
|
||||
y1={26.5}
|
||||
y2={328.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={isDark ? "#000" : "#fff"} />
|
||||
<stop offset={0.978} stopColor="#0A0A0A" stopOpacity={0} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="e"
|
||||
x1={197}
|
||||
x2={197.5}
|
||||
y1={-10.5}
|
||||
y2={463}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={glassTop} />
|
||||
<stop offset={1} stopColor={glassTop} stopOpacity={0} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="f"
|
||||
x1={200}
|
||||
x2={200}
|
||||
y1={48}
|
||||
y2={442.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={glassTop} stopOpacity={0.5} />
|
||||
<stop offset={1} stopColor="#DAB2FF" stopOpacity={0.5} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="i"
|
||||
x1={212}
|
||||
x2={359}
|
||||
y1={198}
|
||||
y2={358}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop offset={0.322} stopColor="#6E11B0" stopOpacity={0.7} />
|
||||
<stop offset={0.851} stopColor={glassTop} stopOpacity={0.3} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="l"
|
||||
x1={200}
|
||||
x2={200}
|
||||
y1={96}
|
||||
y2={243.692}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={glassTop} />
|
||||
<stop
|
||||
offset={1}
|
||||
stopColor={isDark ? "#111" : "#999"}
|
||||
stopOpacity={0.4}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="m"
|
||||
x1={203}
|
||||
x2={195}
|
||||
y1={-20}
|
||||
y2={259.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={glassTop} />
|
||||
<stop offset={1} stopColor="#6E11B0" stopOpacity={0.3} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="r"
|
||||
x1={200}
|
||||
x2={200}
|
||||
y1={35.5}
|
||||
y2={301.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop offset={0.75} stopColor={powerOffColor} stopOpacity={0.7} />
|
||||
<stop offset={1} stopColor="#8200DB" stopOpacity={0.3} />
|
||||
</linearGradient>
|
||||
|
||||
{/* Обновленные фильтры с stdDeviation из твоей Figma */}
|
||||
<filter
|
||||
id="d"
|
||||
width={280}
|
||||
height={280}
|
||||
x={60}
|
||||
y={33}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={7.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="g"
|
||||
width={261}
|
||||
height={261}
|
||||
x={69.5}
|
||||
y={42.5}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={1.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="h"
|
||||
width={269}
|
||||
height={269}
|
||||
x={65.5}
|
||||
y={38.5}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={3.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="j"
|
||||
width={288}
|
||||
height={288}
|
||||
x={56}
|
||||
y={29}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={7.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="q"
|
||||
width={188}
|
||||
height={188}
|
||||
x={106}
|
||||
y={77}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={7.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="s"
|
||||
width={115}
|
||||
height={108.5}
|
||||
x={142.5}
|
||||
y={122}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={2.5} />
|
||||
</filter>
|
||||
<filter
|
||||
id="k"
|
||||
width={150}
|
||||
height={154}
|
||||
x={125}
|
||||
y={96}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feOffset dy={4} />
|
||||
<feGaussianBlur stdDeviation={2} />
|
||||
<feComposite in2="SourceAlpha" operator="arithmetic" k2={-1} k3={1} />
|
||||
<feBlend in2="SourceGraphic" />
|
||||
</filter>
|
||||
<filter
|
||||
id="o"
|
||||
width={158}
|
||||
height={159}
|
||||
x={120.5}
|
||||
y={91.5}
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feGaussianBlur stdDeviation={2.5} />
|
||||
</filter>
|
||||
|
||||
{/* Вспомогательные градиенты для эффектов иконки */}
|
||||
<linearGradient
|
||||
id="p"
|
||||
x1={206.364}
|
||||
x2={291.084}
|
||||
y1={185.4}
|
||||
y2={276.972}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop offset={0.322} stopColor="#6E11B0" stopOpacity={0.7} />
|
||||
<stop offset={0.851} stopColor="#fff" stopOpacity={0.3} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="t"
|
||||
x1={200}
|
||||
x2={203}
|
||||
y1={127}
|
||||
y2={261.5}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#fff" />
|
||||
<stop offset={1} stopOpacity={0.5} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</motion.svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default VpnControlButton;
|
||||
Reference in New Issue
Block a user