This commit is contained in:
parent
09cc4cb09b
commit
fe38d6af18
65
package-lock.json
generated
65
package-lock.json
generated
@ -8,11 +8,13 @@
|
|||||||
"name": "portfolio",
|
"name": "portfolio",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.9.7",
|
||||||
"hamburger-react": "^2.5.0",
|
"hamburger-react": "^2.5.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-image-gallery": "^1.3.0",
|
"react-image-gallery": "^1.3.0",
|
||||||
|
"react-intersection-observer": "^9.16.0",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scroll-motion": "^0.3.0",
|
"react-scroll-motion": "^0.3.0",
|
||||||
"recoil": "^0.7.7"
|
"recoil": "^0.7.7"
|
||||||
@ -1757,6 +1759,33 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.9.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.9.7.tgz",
|
||||||
|
"integrity": "sha512-Eo5TYU6sEPPy82GDx32PJm++G+AkBCrzxtEQOWLnpQX896Q3LFrsYhMZ5YO5ct4wL7wyHU6hqlrpYXeexKAevg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.9.6",
|
||||||
|
"motion-utils": "^12.9.4",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
@ -2093,6 +2122,21 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.9.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.9.6.tgz",
|
||||||
|
"integrity": "sha512-IK9pm5zU8BIp3FCoUGF3T7AHVLVOlXxlwco/bIbcnpBtyYb2gDQhdOzUh2KSDJVjYl1MZ9vdq8tnFTTahX2lfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.9.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.9.4.tgz",
|
||||||
|
"integrity": "sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@ -2480,6 +2524,21 @@
|
|||||||
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-intersection-observer": {
|
||||||
|
"version": "9.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.16.0.tgz",
|
||||||
|
"integrity": "sha512-w9nJSEp+DrW9KmQmeWHQyfaP6b03v+TdXynaoA964Wxt7mdR3An11z4NNCQgL4gKSK7y1ver2Fq+JKH6CWEzUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.17.0",
|
"version": "0.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
|
||||||
@ -3002,6 +3061,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
|
||||||
|
|||||||
@ -9,11 +9,13 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.9.7",
|
||||||
"hamburger-react": "^2.5.0",
|
"hamburger-react": "^2.5.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-image-gallery": "^1.3.0",
|
"react-image-gallery": "^1.3.0",
|
||||||
|
"react-intersection-observer": "^9.16.0",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scroll-motion": "^0.3.0",
|
"react-scroll-motion": "^0.3.0",
|
||||||
"recoil": "^0.7.7"
|
"recoil": "^0.7.7"
|
||||||
|
|||||||
@ -2,15 +2,46 @@ import { Link } from "react-router-dom";
|
|||||||
import { useRecoilValue } from "recoil";
|
import { useRecoilValue } from "recoil";
|
||||||
import { projectsAtom } from "../store";
|
import { projectsAtom } from "../store";
|
||||||
import Tags from "../components/Tags";
|
import Tags from "../components/Tags";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { useInView } from "react-intersection-observer";
|
||||||
|
|
||||||
function Experiance() {
|
function Experiance() {
|
||||||
const experianceList = useRecoilValue(projectsAtom);
|
const experianceList = useRecoilValue(projectsAtom);
|
||||||
|
|
||||||
|
const [ref, inView] = useInView({
|
||||||
|
triggerOnce: true,
|
||||||
|
threshold: 0.1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerVariants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemVariants = {
|
||||||
|
hidden: { opacity: 0, y: 20 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.5,
|
||||||
|
ease: "easeOut",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const experianceListUI = experianceList.map((item, key) => {
|
const experianceListUI = experianceList.map((item, key) => {
|
||||||
const even = key % 2;
|
const even = key % 2;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article
|
<motion.article
|
||||||
|
ref={ref}
|
||||||
|
variants={itemVariants}
|
||||||
className={`flex-1 gap-4 mb-12 bg-[#f0f0f3] border shadow-box ${
|
className={`flex-1 gap-4 mb-12 bg-[#f0f0f3] border shadow-box ${
|
||||||
(even === 0 && "rounded-tl-3xl rounded-br-3xl") ||
|
(even === 0 && "rounded-tl-3xl rounded-br-3xl") ||
|
||||||
"rounded-tr-3xl rounded-bl-3xl"
|
"rounded-tr-3xl rounded-bl-3xl"
|
||||||
@ -41,7 +72,7 @@ function Experiance() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</motion.article>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,9 +90,15 @@ function Experiance() {
|
|||||||
>
|
>
|
||||||
Projects and experience<span className="text-highlight">.</span>
|
Projects and experience<span className="text-highlight">.</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div className="py-4 grid grid-cols-1 md:grid-cols-2 gap-8" role="list">
|
<motion.div
|
||||||
|
ref={ref}
|
||||||
|
variants={containerVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate={inView ? "visible" : "hidden"}
|
||||||
|
className="py-4 grid grid-cols-1 md:grid-cols-2 gap-8"
|
||||||
|
>
|
||||||
{experianceListUI}
|
{experianceListUI}
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,32 @@
|
|||||||
|
import { motion, useAnimation } from "framer-motion";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
function Start() {
|
function Start() {
|
||||||
|
const greeting = "Hello, my name is Maria.";
|
||||||
|
const greetingArray = greeting.split("");
|
||||||
|
const role = "I'm a Frontend Engineer";
|
||||||
|
const roleArray = role.split("");
|
||||||
|
|
||||||
|
const controls = useAnimation();
|
||||||
|
const contentControls = useAnimation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Start the second animation after the first line completes
|
||||||
|
const timer1 = setTimeout(() => {
|
||||||
|
controls.start("visible");
|
||||||
|
}, greetingArray.length * 100 + 500); // Total time for first line + 500ms delay
|
||||||
|
|
||||||
|
// Start the content animation after the second line completes
|
||||||
|
const timer2 = setTimeout(() => {
|
||||||
|
contentControls.start("visible");
|
||||||
|
}, (greetingArray.length + roleArray.length) * 100 + 1000); // Total time for both lines + 1000ms delay
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer1);
|
||||||
|
clearTimeout(timer2);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div id="start" className="absolute -top-16 "></div>
|
<div id="start" className="absolute -top-16 "></div>
|
||||||
@ -6,50 +34,92 @@ function Start() {
|
|||||||
<div className=" min-h-screen flex items-center">
|
<div className=" min-h-screen flex items-center">
|
||||||
<div className="">
|
<div className="">
|
||||||
<h1 className="text-titlePhone md:text-title md:leading-tight mb-2 font-ht">
|
<h1 className="text-titlePhone md:text-title md:leading-tight mb-2 font-ht">
|
||||||
Hello, my name is Maria<span className=" text-highlight">.</span>
|
{greetingArray.map((letter, index) => (
|
||||||
|
<motion.span
|
||||||
|
key={index}
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{
|
||||||
|
duration: 0.1,
|
||||||
|
delay: index * 0.1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{letter}
|
||||||
|
</motion.span>
|
||||||
|
))}
|
||||||
|
<span className="text-highlight">.</span>
|
||||||
</h1>
|
</h1>
|
||||||
<h2 className="text-subTPhone md:text-subT font-ht">
|
<h2 className="text-subTPhone md:text-subT font-ht">
|
||||||
I'm a<span className=" text-highlight"> Frontend Engineer</span>
|
{roleArray.map((letter, index) => (
|
||||||
|
<motion.span
|
||||||
|
key={index}
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={controls}
|
||||||
|
variants={{
|
||||||
|
visible: { opacity: 1 }
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 0.1,
|
||||||
|
delay: index * 0.1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{letter}
|
||||||
|
</motion.span>
|
||||||
|
))}
|
||||||
|
<span className="text-highlight">.</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-base md:w-1/2 w-full text-left my-4 font-body">
|
<motion.div
|
||||||
I’m a Stockholm-based web developer with startup experience,
|
initial={{ opacity: 0 }}
|
||||||
building things with JavaScript, React, and Node.js. I’m also into
|
animate={contentControls}
|
||||||
3D design and art, and my mini poodle,{" "}
|
variants={{
|
||||||
<span className="font-black">Oreo</span>{" "}
|
visible: { opacity: 1 }
|
||||||
<img
|
}}
|
||||||
src="/img/oreo-logo.png"
|
transition={{
|
||||||
alt="oreo_logo"
|
duration: 0.8,
|
||||||
className=" inline h-"
|
ease: "easeOut"
|
||||||
/>{" "}
|
}}
|
||||||
, is always in my creative space. Let’s chat!
|
>
|
||||||
{/* Hi, I’m Mariia! I’m a developer who loves building functional,
|
<p className="text-base md:w-1/2 w-full text-left my-4 font-body">
|
||||||
user-friendly web experiences with a creative twist. I’ve been
|
I'm a Stockholm-based web developer with startup experience,
|
||||||
working as a junior frontend engineer in startups, gaining hands-on
|
building things with JavaScript, React, and Node.js. I'm also into
|
||||||
experience. I use JavaScript, React, Node.js, and SQL, and I’m
|
3D design and art, and my mini poodle,{" "}
|
||||||
always exploring 3D design to add a little extra flair. Let’s
|
<span className="font-black">Oreo</span>{" "}
|
||||||
connect and maybe you’ll meet my mini poodle,{" "}
|
|
||||||
<span className="font-black">Oreo</span>{" "}
|
|
||||||
<img
|
|
||||||
src="/img/oreo-logo.png"
|
|
||||||
alt="oreo_logo"
|
|
||||||
className=" inline h-"
|
|
||||||
/>{" "}
|
|
||||||
, who’s always hanging out with me while I work! */}
|
|
||||||
{/* "Hi, I’m Mariia! I’m a frontend developer with experience in startup projects, working with JavaScript, React, Node.js, and SQL. I love combining my technical skills with my passion for art and design, especially through 3D projects. Let’s connect and see what we can create together—also, say hi to my mini poodle, Oreo, who’s always by my side in my creative space!" */}
|
|
||||||
</p>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://www.linkedin.com/in/mariia-shabelnik/"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<img
|
<img
|
||||||
src="/img/icons8-linkedin.svg"
|
src="/img/oreo-logo.png"
|
||||||
|
alt="oreo_logo"
|
||||||
|
className="inline h-"
|
||||||
|
/>{" "}
|
||||||
|
, is always in my creative space. Let's chat!
|
||||||
|
{/* Hi, I'm Mariia! I'm a developer who loves building functional,
|
||||||
|
user-friendly web experiences with a creative twist. I've been
|
||||||
|
working as a junior frontend engineer in startups, gaining hands-on
|
||||||
|
experience. I use JavaScript, React, Node.js, and SQL, and I'm
|
||||||
|
always exploring 3D design to add a little extra flair. Let's
|
||||||
|
connect and maybe you'll meet my mini poodle,{" "}
|
||||||
|
<span className="font-black">Oreo</span>{" "}
|
||||||
|
<img
|
||||||
|
src="/img/oreo-logo.png"
|
||||||
alt="oreo_logo"
|
alt="oreo_logo"
|
||||||
className=" inline h-"
|
className=" inline h-"
|
||||||
/>
|
/>{" "}
|
||||||
LinkedIn
|
, who's always hanging out with me while I work! */}
|
||||||
</a>
|
{/* "Hi, I'm Mariia! I'm a frontend developer with experience in startup projects, working with JavaScript, React, Node.js, and SQL. I love combining my technical skills with my passion for art and design, especially through 3D projects. Let's connect and see what we can create together—also, say hi to my mini poodle, Oreo, who's always by my side in my creative space!" */}
|
||||||
</div>
|
</p>
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href="https://www.linkedin.com/in/mariia-shabelnik/"
|
||||||
|
target="_blank"
|
||||||
|
className="flex items-center gap-2 hover:text-highlight transition-colors duration-300"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/img/icons8-linkedin.svg"
|
||||||
|
alt="LinkedIn icon"
|
||||||
|
className="inline h-6"
|
||||||
|
/>
|
||||||
|
LinkedIn
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user