About view done. all styled and animated. some minor animation fixes overall and codecleaning

This commit is contained in:
yousifpa98
2024-12-21 04:05:54 +01:00
parent f4859124d2
commit 6e257453bf
14 changed files with 467 additions and 132 deletions

View File

@@ -12,8 +12,11 @@ import Location from "./Location";
import "animate.css";
import { useState } from "react";
import TallContent from "./TallContent";
import "../css/GridContainer.css";
const Home = () => {
const [isExpanded, setIsExpanded] = useState(false);
const social = (url) => () => {
window.open(url, "_blank", "noopener,noreferrer");
};
@@ -35,12 +38,39 @@ const Home = () => {
/>
<TechStack
initialAnimation="animate__backInLeft"
onMouseEnter={handleMouseEnter}
/* onMouseEnter={handleMouseEnter} */
onAnimationEnd={handleAnimationEnd}
isExpanded={isExpanded}
onExpandToggle={() => setIsExpanded(!isExpanded)}
/>
<LangSelect />
<Mail />
<Switch />
{isExpanded ? (
""
) : (
<LangSelect
initialAnimation="animate__zoomIn"
/* onMouseEnter={handleMouseEnter} */
onAnimationEnd={handleAnimationEnd}
/>
)}
{isExpanded ? (
""
) : (
<Mail
initialAnimation="animate__zoomIn"
/* onMouseEnter={handleMouseEnter} */
onAnimationEnd={handleAnimationEnd}
/>
)}
{isExpanded ? (
""
) : (
<Switch
initialAnimation="animate__zoomIn"
/* onMouseEnter={handleMouseEnter} */
onAnimationEnd={handleAnimationEnd}
/>
)}
<Navigation
initialAnimation="animate__backInDown"
onMouseEnter={handleMouseEnter}

View File

@@ -1,8 +1,12 @@
import React from "react";
import "../css/LangSelect.css";
import { useState } from "react";
const LangSelect = () => {
return <div className="langSelect container">LangSelect</div>;
const LangSelect = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const [animation, setAnimation] = useState(initialAnimation);
return <div className={`langSelect container animate__animated ${animation}`}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}>LangSelect</div>;
};
export default LangSelect;

View File

@@ -1,8 +1,18 @@
import React from "react";
import "../css/Mail.css";
import { useState } from "react";
const Mail = () => {
return <div className="eMail container">Mail</div>;
const Mail = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const [animation, setAnimation] = useState(initialAnimation);
return (
<div
className={`eMail container animate__animated ${animation}`}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
Mail
</div>
);
};
export default Mail;

View File

@@ -1,8 +1,19 @@
import React from "react";
import "../css/Switch.css";
import { useState } from "react";
import "animate.css";
const Switch = () => {
return <div className="switch container">Switch</div>;
const Switch = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const [animation, setAnimation] = useState(initialAnimation);
return (
<div
className={`switch container animate__animated ${animation}`}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
Switch
</div>
);
};
export default Switch;

View File

@@ -1,4 +1,5 @@
import React, { useState } from "react";
import clsx from "clsx";
import ReactIcon from "../assets/icons/skill-icons/icons/React-Dark.svg?react";
import NodeIcon from "../assets/icons/skill-icons/icons/NodeJS-Dark.svg?react";
import MongoIcon from "../assets/icons/skill-icons/icons/MongoDB.svg?react";
@@ -7,11 +8,24 @@ import NextJsIcon from "../assets/icons/skill-icons/icons/NextJS-Dark.svg?react"
import DockerIcon from "../assets/icons/skill-icons/icons/Docker.svg?react";
import TypeScriptIcon from "../assets/icons/skill-icons/icons/TypeScript.svg?react";
import ExpressIcon from "../assets/icons/skill-icons/icons/ExpressJS-Dark.svg?react";
import KubernetesIcon from "../assets/icons/skill-icons/icons/Kubernetes.svg?react";
import GitIcon from "../assets/icons/skill-icons/icons/Git.svg?react";
import TailwindIcon from "../assets/icons/skill-icons/icons/TailwindCSS-Dark.svg?react";
import PostgreSQL from "../assets/icons/skill-icons/icons/PostgreSQL-Dark.svg?react";
import NestjsIcon from "../assets/icons/skill-icons/icons/NestJS-Dark.svg?react";
import Linux from "../assets/icons/skill-icons/icons/Linux-Dark.svg?react";
import "../css/TechStack.css";
import { Link } from "react-router-dom";
import "animate.css";
const TechStack = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const TechStack = ({
initialAnimation,
onMouseEnter,
onAnimationEnd,
isExpanded,
onExpandToggle, // Receive the handler as a prop
}) => {
const techStack = [
{ name: "React", component: ReactIcon, className: "reactIcon", id: 1 },
{ name: "Node.js", component: NodeIcon, className: "nodeIcon", id: 2 },
@@ -36,30 +50,86 @@ const TechStack = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
className: "expressIcon",
id: 8,
},
{
name: "Kubernetes",
component: KubernetesIcon,
className: "kubernetesIcon",
id: 9,
needExpand: true,
},
{
name: "Git",
component: GitIcon,
className: "gitIcon",
id: 10,
needExpand: true,
},
{
name: "Tailwind CSS",
component: TailwindIcon,
className: "tailwindIcon",
id: 11,
needExpand: true,
},
{
name: "PostgreSQL",
component: PostgreSQL,
className: "postgresqlIcon",
id: 12,
needExpand: true,
},
{
name: "NestJS",
component: NestjsIcon,
className: "nestjsIcon",
id: 13,
needExpand: true,
},
{
name: "Linux",
component: Linux,
className: "linuxIcon",
id: 14,
needExpand: true,
},
];
/* Animations */
const [animation, setAnimation] = useState(initialAnimation);
return (
<div
className={`techStackContainer container animate__animated ${animation}`}
className={clsx(
"techStackContainer",
"container",
"animate__animated",
animation,
{ expanded: isExpanded } // Conditional class
)}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
<h2>Tech Stack</h2>
<div className="techStack">
{techStack.map((tech) => {
const IconComponent = tech.component;
return (
<div key={tech.id} className="techStackItem">
<IconComponent className={`techIcon ${tech.className}`} />
</div>
);
})}
{techStack
.filter((tech) => isExpanded || !tech.needExpand) // Filter based on isExpanded
.map((tech) => {
const IconComponent = tech.component;
return (
<div key={tech.id} className="techStackItem">
<IconComponent className={`techIcon ${tech.className}`} />
</div>
);
})}
</div>
<Link to={"/"} className="techStackShowMore">
Show More
<Link
to="#"
className="techStackShowMore"
onClick={(e) => {
e.preventDefault(); // Prevent default link behavior
onExpandToggle(); // Toggle the expanded state
}}
>
{isExpanded ? "Show Less" : "Show More"} {/* Toggle link text */}
</Link>
</div>
);

View File

@@ -1,9 +1,72 @@
import React from 'react'
import React from "react";
import Hero from "../Hero";
import "../../css/Home.css";
import LangSelect from "../LangSelect";
import Mail from "../Mail";
import Switch from "../Switch";
import Navigation from "../Navigation";
import LinkedInIcon from "../../assets/icons/socials/linkedin.svg?react";
import GitHubIcon from "../../assets/icons/socials/square-github.svg?react";
import Location from "../Location";
import "animate.css";
import { useState } from "react";
import TallContentAbout from "../subComponents/About/TallContentAbout";
import "../../css/GridContainer.css";
import Specialties from "../subComponents/About/Specialties";
const About = () => {
return (
<div>About</div>
)
}
const social = (url) => () => {
window.open(url, "_blank", "noopener,noreferrer");
};
const [hoverAnimation, setHoverAnimation] = useState("animate__headShake");
export default About
const handleMouseEnter = (setAnimation) => {
setAnimation(hoverAnimation); // Trigger hover animation
};
const handleAnimationEnd = (setAnimation) => {
setAnimation(""); // Clear animation to prevent re-triggering
};
return (
<div className="gridContainer">
<Hero
initialAnimation="animate__bounceIn"
onMouseEnter={handleMouseEnter}
onAnimationEnd={handleAnimationEnd}
/>
<LangSelect />
<Mail />
<Switch />
<Navigation
/* initialAnimation="animate__bounceInDown"
onMouseEnter={handleMouseEnter}
onAnimationEnd={handleAnimationEnd} */
/>
<div
className="linkedIn container"
onClick={social("https://www.linkedin.com/in/yousifpaulus/")}
>
<LinkedInIcon className="linkedInIcon" />
</div>
<div
className="github container"
onClick={social("https://github.com/yousifpa98")}
>
<GitHubIcon className="githubIcon" />
</div>
<Location />
<TallContentAbout
initialAnimation="animate__bounceInDown"
onMouseEnter={handleMouseEnter}
onAnimationEnd={handleAnimationEnd}
/>
<Specialties
initialAnimation="animate__backInLeft"
onMouseEnter={handleMouseEnter}
onAnimationEnd={handleAnimationEnd}
/>
</div>
);
};
export default About;

View File

@@ -0,0 +1,24 @@
import React from "react";
import "../../../css/Specialties.css";
import { useState } from "react";
const Specialties = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const [animation, setAnimation] = useState(initialAnimation);
return (
<div
className={`specialties container animate__animated ${animation}`}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
<p className="specialtyText">
Im a fullstack developer who loves creating web applications that are
functional and easy to use. My go-to tools are React, Node.js, and
TypeScript, and I enjoy working on both the front-end and back-end. I
focus on clean, practical solutions that work in the real world and
approach every project with curiosity and attention to detail.
</p>
</div>
);
};
export default Specialties;

View File

@@ -0,0 +1,71 @@
import React from "react";
import { useState } from "react";
import "../../../css/TallContentAbout.css";
const TallContentAbout = ({
initialAnimation,
onMouseEnter,
onAnimationEnd,
}) => {
const [animation, setAnimation] = useState(initialAnimation);
return (
<div
className={`container tallContentAbout animate__animated ${animation}`}
onMouseEnter={() => onMouseEnter(setAnimation)}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
<div className="funFacts">
<h2>Some Fun-Facts about me:</h2>
<ul className="funFactList">
<li>
<p>
2300+ Chess.com blitz rating and a lifelong love for strategy.
</p>
</li>
<li>
<p>
Big fan of tycoon simulation gamesI could spend hours building
and managing virtual worlds.
</p>
</li>
<li>
<p>
I love Asian food, especially Japanese cuisine, and enjoy trying
new recipes.
</p>
</li>
<li>
<p>Football is my passion (and no, I wont call it soccer).</p>
</li>
<li>
<p>
I have a guilty pleasure for sitcoms like The Big Bang Theory and
cant resist a good Taylor Swift track.
</p>
</li>
{/* <li>
<p>Hiking is one of my favorite ways to relax and recharge.</p>
</li> */}
<li>
<p>I enjoy baking, especially experimenting with new desserts.</p>
</li>
<li>
<p>
Ive been drawing and painting since I was young, and its still
one of my favorite creative outlets.
</p>
</li>
</ul>
</div>
{/* <p className="persText">
Outside of tech, I enjoy spending time outdoors, baking, and diving into
new hobbies. I like to keep things balanced—challenging my mind with
strategy games or chess and unwinding with great food, music, and some
classic sitcoms.
</p> */}
</div>
);
};
export default TallContentAbout;

47
src/css/GridContainer.css Normal file
View File

@@ -0,0 +1,47 @@
.gridContainer {
display: grid;
grid-template-columns: repeat(11, 1fr);
grid-template-rows: repeat(9, 1fr);
gap: 10px;
width: 50%;
height: 80%;
}
.container {
background-color: #28272a;
padding: 2rem;
border-radius: 0.5rem;
border: 0.5px solid rgb(73, 73, 73);
box-shadow: 0 0 10px -5px rgba(184, 184, 184, 0.2);
}
.container:hover {
cursor: pointer;
animation-duration: 0.5s;
}
.linkedIn {
grid-area: 8 / 5 / 10 / 7;
background-color: #2b6498;
border: 1px solid #0072b1;
}
.linkedInIcon {
fill: white;
}
.githubIcon {
fill: white;
}
.github {
grid-area: 8 / 7 / 10 / 9;
background-color: #373e4c;
}
.linkedIn,
.github {
display: flex;
justify-content: center;
align-items: center;
}

View File

@@ -1,59 +1,5 @@
.gridContainer {
display: grid;
grid-template-columns: repeat(11, 1fr);
grid-template-rows: repeat(9, 1fr);
gap: 10px;
width: 50%;
height: 80%;
}
.container {
background-color: #28272a;
padding: 2rem;
border-radius: 0.5rem;
border: 0.5px solid rgb(73, 73, 73);
box-shadow: 0 0 10px -5px rgba(184, 184, 184, 0.2);
}
.container:hover {
cursor: pointer;
animation-duration: 0.5s;
}
h2 {
color: white;
}
.linkedIn {
grid-area: 8 / 5 / 10 / 7;
background-color: #001d2c;
border: 1px solid #0072b1;
}
.linkedInIcon {
fill: #0072b1;
}
.githubIcon {
fill: black;
}
.github {
grid-area: 8 / 7 / 10 / 9;
background-color: #333;
}
.linkedIn,
.github {
display: flex;
justify-content: center;
align-items: center;
}
.langSelect,
.eMail,
.switch {
animation: zoomIn;
animation-duration: 1s;
}

View File

@@ -37,4 +37,6 @@
.navLink.active span {
border-bottom: 1px solid white;
font-weight: bold;
transition: font-weight 0.3s ease, border-bottom 0.3s ease;
}

9
src/css/Specialties.css Normal file
View File

@@ -0,0 +1,9 @@
.specialties {
grid-area: 4 / 1 / 8 / 5;
}
.specialtyText {
color: rgb(151, 151, 151);
font-size: 1.2rem;
text-align: justify;
}

View File

@@ -0,0 +1,33 @@
.tallContentAbout {
grid-area: 1 / 5 / 8 / 9;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.funFacts {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
height: 100%;
}
.funFactList {
/* list-style: none; */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.funFactList li p {
color: rgb(151, 151, 151);
}
.persText {
color: white;
font-size: 1.1rem;
}

View File

@@ -1,51 +1,66 @@
.techStackContainer {
grid-area: 4 / 1 / 8 / 5;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
animation-duration: 1s;
}
.techStackContainer h2 {
margin-bottom: 10px;
align-self: flex-start;
}
.techIcon {
width: 4rem;
height: 4rem;
filter: grayscale(0.7);
transition: transform 0.3s ease, filter 0.3s ease;
}
.techIcon:hover {
filter: none;
animation: tada 1s;
cursor: pointer;
}
.techStack {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 1rem;
}
.techStackShowMore {
font-size: 1.2rem;
color: rgb(151, 151, 151);
text-decoration: none;
border-bottom: 1px solid rgb(151, 151, 151);
/* align-self: flex-start; */
}
@keyframes techIconHover {
10% {
transform: scale();
grid-area: 4 / 1 / 8 / 5;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
animation-duration: 1s;
}
}
.techStackContainer.expanded {
grid-area: 4 / 1 / 10 / 5;
min-width: 356.43px;
}
.techStackContainer h2 {
margin-bottom: 10px;
align-self: flex-start;
}
.techIcon {
width: 4rem;
height: 4rem;
filter: grayscale(0.7);
transition: transform 0.3s ease, filter 0.3s ease;
}
.techIcon:hover {
filter: none;
animation: tada 1s;
cursor: pointer;
}
.techStack {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 1rem;
}
.techStackShowMore {
font-size: 1.2rem;
color: rgb(151, 151, 151);
text-decoration: none;
border-bottom: 1px solid rgb(151, 151, 151);
/* align-self: flex-start; */
}
@keyframes techIconHover {
10% {
transform: scale();
}
}
/* Smooth expand/collapse animations */
.techStackContainer {
max-height: 320px; /* Initial max-height */
overflow: hidden;
transition: max-height 1s ease-in-out;
}
.techStackContainer.expanded {
max-height: 600px; /* Expanded max-height */
}