feat : add rabbit animation form

This commit is contained in:
ali josheghani
2024-05-30 16:16:18 +03:30
parent 278bfca3c8
commit 9cdc8f8782
4 changed files with 203 additions and 1 deletions

30
package-lock.json generated
View File

@@ -12,6 +12,7 @@
"@tsparticles/react": "^3.0.0",
"@tsparticles/slim": "^3.4.0",
"country-flag-icons": "^1.5.11",
"framer-motion": "^11.2.9",
"nprogress": "^0.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -2847,6 +2848,30 @@
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/framer-motion": {
"version": "11.2.9",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.9.tgz",
"integrity": "sha512-gfxNSkp4dC3vpy2hGNQK3K9bNOKwfasqOhrqvmZzYxCPSJ9Tpv/9JlCkeCMgFdKefgPr8+JiouGjVmaDzu750w==",
"dependencies": {
"tslib": "^2.4.0"
},
"peerDependencies": {
"@emotion/is-prop-valid": "*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"peerDependenciesMeta": {
"@emotion/is-prop-valid": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -4326,6 +4351,11 @@
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@@ -14,6 +14,7 @@
"@tsparticles/react": "^3.0.0",
"@tsparticles/slim": "^3.4.0",
"country-flag-icons": "^1.5.11",
"framer-motion": "^11.2.9",
"nprogress": "^0.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

View File

@@ -0,0 +1,162 @@
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
const Rabbit = ({
focusInputText,
focusInputPassword,
}: {
focusInputText?: boolean;
focusInputPassword?: boolean;
}) => {
const [text, setText] = useState<boolean>(false);
const [password, setPassword] = useState<boolean>(false);
useEffect(() => {
if (focusInputText) {
setText(true);
} else {
setText(false);
}
}, [focusInputText]);
useEffect(() => {
if (focusInputPassword) {
setPassword(true);
} else {
setPassword(false);
}
}, [focusInputPassword]);
return (
<motion.div className="w-full absolute -top-[20%] md:-top-[18%]">
<svg
height="100px"
width="100px"
className="mx-auto relative -top-[20%] md:-top-[18%]"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512"
xmlSpace="preserve"
fill="#000000"
>
<g id="SVGRepo_bgCarrier" strokeWidth={0} />
<g
id="SVGRepo_tracerCarrier"
strokeLinecap="round"
strokeLinejoin="round"
/>
<g id="SVGRepo_iconCarrier">
<motion.path
style={{
fill: "#F5B989",
}}
d="M395.643,284.33c-23.878-43.349-57.989-77.224-93.589-92.94c-6.473-2.857-10.647-9.265-10.647-16.339 V68.877C291.407,30.899,322.298,0,360.271,0c37.979,0,68.877,30.899,68.877,68.877v206.834 C429.147,294.222,404.503,300.411,395.643,284.33z"
animate={{
rotate: text ? 30 : password ? 60 : 0,
x: text ? 35 : password ? -60 : 0,
y: text ? 35 : password ? 60 : 0,
}}
/>
<motion.path
style={{
fill: "#F9C896",
}}
d="M82.853,275.711V68.877C82.853,30.899,113.751,0,151.73,0c37.973,0,68.865,30.899,68.865,68.877 v106.174c0,7.074-4.176,13.482-10.647,16.339c-35.6,15.716-69.712,49.59-93.59,92.94C107.484,300.442,82.853,294.185,82.853,275.711 z"
animate={{
rotate: text ? -30 : password ? -60 : 0,
x: text ? -35 : password ? 60 : 0,
y: text ? 35 : password ? 60 : 0,
}}
/>
<path
style={{
fill: "#FED7A4",
}}
d="M256,512c-102.918,0-203.4-29.18-203.4-132.562c0-95.755,90.381-233.939,203.4-233.939 c114.422,0,203.4,139.748,203.4,233.939C459.4,482.796,358.965,512,256,512z"
/>
<g>
<path
style={{
fill: "#F9C896",
}}
d="M256,145.499V512c102.963,0,203.4-29.203,203.4-132.562C459.4,285.247,370.422,145.499,256,145.499z "
/>
<path
style={{
fill: "#F9C896",
}}
d="M256,512c6.083,0,12.033-0.102,17.861-0.296v-79.279c0-9.864-7.997-17.861-17.861-17.861 c-9.864,0-17.861,7.997-17.861,17.861v79.279C243.968,511.896,249.917,512,256,512z"
/>
</g>
<g>
<path
style={{
fill: "#F5B989",
}}
d="M256,414.563V512c6.083,0,12.033-0.102,17.861-0.296v-79.279 C273.861,422.559,265.864,414.563,256,414.563z"
/>
<path
style={{
fill: "#F5B989",
}}
d="M243.079,444.753l-40.169-42.101c-16.013-16.779-4.101-44.686,19.126-44.686h67.933 c23.198,0,35.159,27.885,19.125,44.687l-40.168,42.1C261.886,452.126,250.111,452.122,243.079,444.753z"
/>
</g>
<path
style={{
fill: "#F0AA7B",
}}
d="M289.967,357.966h-33.966v92.315c4.702,0,9.404-1.842,12.923-5.528l40.168-42.1 C325.126,385.851,313.164,357.966,289.967,357.966z"
/>
{!password && (
<>
<motion.circle
style={{
fill: "#784738",
}}
cx={165.829}
cy={304.962}
r={23.627}
animate={{ scale: text ? 1.5 : 1 }}
/>
<motion.circle
style={{
fill: "#633B2E",
}}
cx={346.173}
cy={305.117}
r={23.627}
animate={{ scale: text ? 1.5 : 1 }}
/>
</>
)}
{password && (
<>
<motion.line
x1={142.202}
y1={304.962}
x2={189.456}
y2={304.962}
stroke="#784738"
strokeWidth="5"
animate={{ scaleX: password ? 1.5 : 1 }}
/>
<motion.line
x1={322.546}
y1={305.117}
x2={369.8}
y2={305.117}
stroke="#633B2E"
strokeWidth="5"
animate={{ scaleX: password ? 1.5 : 1 }}
/>
</>
)}
</g>
</svg>
</motion.div>
);
};
export default Rabbit;

11
src/types/props.d.ts vendored
View File

@@ -50,7 +50,7 @@ export interface NavData {
}
// begin ListTutorial.tsx
import { Component, SetStateAction } from "react";
import { Component, InputHTMLAttributes, SetStateAction } from "react";
export type TutorialList = { id: number; name: string }[];
@@ -85,3 +85,12 @@ interface ProductBoxProps {
btnText: string;
variant: number;
}
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label: string;
id?: string;
type: string;
name?: string;
placeholder?: string;
extra?: string;
}