contact
This commit is contained in:
@@ -1,9 +1,60 @@
|
||||
import React from 'react'
|
||||
import React from "react";
|
||||
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 "../../css/GridContainer.css";
|
||||
import ContactTile from "../subComponents/Contact/ContactTile";
|
||||
|
||||
const Contact = () => {
|
||||
return (
|
||||
<div>Contact</div>
|
||||
)
|
||||
}
|
||||
const social = (url) => () => {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
const [hoverAnimation, setHoverAnimation] = useState("animate__headShake");
|
||||
|
||||
export default Contact
|
||||
const handleMouseEnter = (setAnimation) => {
|
||||
setAnimation(hoverAnimation); // Trigger hover animation
|
||||
};
|
||||
|
||||
const handleAnimationEnd = (setAnimation) => {
|
||||
setAnimation(""); // Clear animation to prevent re-triggering
|
||||
};
|
||||
return (
|
||||
<div className="gridContainer">
|
||||
<LangSelect />
|
||||
<Mail />
|
||||
<Switch />
|
||||
<Navigation
|
||||
/* initialAnimation="animate__bounceInDown"
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onAnimationEnd={handleAnimationEnd} */
|
||||
/>
|
||||
<ContactTile
|
||||
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 />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Contact;
|
||||
|
||||
98
src/components/subComponents/Contact/ContactTile.jsx
Normal file
98
src/components/subComponents/Contact/ContactTile.jsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React, { useState } from "react";
|
||||
import "../../../css/ContactTile.css";
|
||||
import { useTheme } from "../../../Context/ThemeContext";
|
||||
import { useLang } from "../../../Context/LangContext";
|
||||
|
||||
const ContactTileTiltFlip = ({
|
||||
initialAnimation,
|
||||
onMouseEnter,
|
||||
onAnimationEnd,
|
||||
}) => {
|
||||
const [animation, setAnimation] = useState(initialAnimation);
|
||||
const { colormode } = useTheme();
|
||||
const { language } = useLang();
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
const [tiltStyle, setTiltStyle] = useState({});
|
||||
|
||||
const handleMouseMove = (e) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left - rect.width / 2;
|
||||
const y = e.clientY - rect.top - rect.height / 2;
|
||||
const tiltX = (y / rect.height) * 40; // Harter Tilt
|
||||
const tiltY = -(x / rect.width) * 40;
|
||||
|
||||
setTiltStyle({
|
||||
transform: `rotateX(${tiltX}deg) rotateY(${tiltY}deg)`,
|
||||
});
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setTiltStyle({ transform: "rotateX(0deg) rotateY(0deg)" });
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
setIsFlipped(!isFlipped);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`container contactTile ${colormode} animate__animated ${animation}`}
|
||||
/* onMouseEnter={() => onMouseEnter(setAnimation)}
|
||||
*/ onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||
>
|
||||
<div
|
||||
className={`card ${isFlipped ? "flipped" : ""}`}
|
||||
onClick={handleClick}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
style={{
|
||||
transform: `${tiltStyle.transform || "rotateX(0deg) rotateY(0deg)"} ${
|
||||
isFlipped ? "rotateY(180deg)" : ""
|
||||
}`,
|
||||
}}
|
||||
>
|
||||
<div className="card-inner">
|
||||
<div className={`card-front ${colormode}`}>
|
||||
<h2>Yousif Paulus</h2>
|
||||
<p>React | Node.js | TypeScript</p>
|
||||
<p>
|
||||
{language === "en-GB"
|
||||
? "Full-Stack Developer"
|
||||
: "Full-Stack Entwickler"}
|
||||
</p>
|
||||
</div>
|
||||
<div className={`card-back ${colormode}`}>
|
||||
<p>
|
||||
📧 {/* Email: */}{" "}
|
||||
<a href="mailto:yousif.paulus@hotmail.de">
|
||||
yousif.paulus@hotmail.de
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
📞{" "}
|
||||
{/* {language === "en-GB" ? "Phone:" : "Tel:"} */}
|
||||
<a href="tel:+4915150717623">
|
||||
{language === "en-GB"
|
||||
? "+49 151 50717623"
|
||||
: "0151 50717623"}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
🌐 {/* Portfolio: */}{" "}
|
||||
<a href="http://www.yousifpaulus.dev">www.yousifpaulus.dev</a>
|
||||
</p>
|
||||
{/* <p>
|
||||
💬{" "}
|
||||
{language === "en-GB"
|
||||
? "Let’s Build Something Great."
|
||||
: "Tel: +49 151 50717623"}
|
||||
</p> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContactTileTiltFlip;
|
||||
163
src/css/ContactTile.css
Normal file
163
src/css/ContactTile.css
Normal file
@@ -0,0 +1,163 @@
|
||||
.contactTile {
|
||||
grid-area: 1 / 1 / 8 / 9;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.container.contactTile {
|
||||
perspective: 1500px; /* Für 3D-Effekt */
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 340px; /* Visitenkartenformat */
|
||||
height: 200px;
|
||||
transform-style: preserve-3d;
|
||||
cursor: pointer;
|
||||
transition: transform 0.5s ease-out; /* Smooth Flip Transition */
|
||||
}
|
||||
|
||||
.card.flipped {
|
||||
transform: rotateY(180deg); /* Rückseite anzeigen */
|
||||
}
|
||||
|
||||
.card-inner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.card-front.dark h2 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.card-front,
|
||||
.card-back {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backface-visibility: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(145deg, #d9d9d9, #f2f2f2); /* Helles Silber */
|
||||
box-shadow: inset 0 4px 8px rgba(255, 255, 255, 0.5),
|
||||
inset 0 -4px 8px rgba(0, 0, 0, 0.1), 0 6px 10px rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden; /* Für Glanzeffekt-Beschneidung */
|
||||
}
|
||||
|
||||
/* Rückseite - dunkler Silber-Look */
|
||||
.card-back {
|
||||
background: linear-gradient(145deg, #999999, #b3b3b3);
|
||||
transform: rotateY(180deg);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.card-back p {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0rem 3.5rem;
|
||||
}
|
||||
|
||||
.card-back p a {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Glanzeffekt nur innerhalb der Karte */
|
||||
.card-front::before
|
||||
/*, .card-back::before */ {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 150%;
|
||||
height: 150%;
|
||||
background: radial-gradient(
|
||||
circle at 50% 50%,
|
||||
rgba(255, 255, 255, 0.4),
|
||||
rgba(255, 255, 255, 0) 70%
|
||||
);
|
||||
transform: translate(-25%, -25%) rotate(30deg);
|
||||
animation: subtle-glow 3s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
filter: blur(4px);
|
||||
mix-blend-mode: screen; /* Lichtdurchlässigkeit */
|
||||
}
|
||||
|
||||
/* Subtile Animation des Glanzes */
|
||||
@keyframes subtle-glow {
|
||||
0% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.1);
|
||||
}
|
||||
50% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.3);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Light Mode Styles */
|
||||
.card-front.light,
|
||||
.card-back.light {
|
||||
background: linear-gradient(
|
||||
145deg,
|
||||
#fdfdfd,
|
||||
#e6e6e6
|
||||
); /* Heller, weicher Silber-Look */
|
||||
box-shadow: inset 0 4px 8px rgba(255, 255, 255, 0.6),
|
||||
inset 0 -4px 8px rgba(0, 0, 0, 0.1), 0 6px 10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Vorderseite Light Mode */
|
||||
.card-front.light {
|
||||
border: 1px solid #ddd; /* Leichte Kontur für hellen Look */
|
||||
}
|
||||
|
||||
/* Rückseite Light Mode */
|
||||
.card-back.light {
|
||||
border: 1px solid #ccc; /* Etwas dunklere Kontur für Kontrast */
|
||||
transform: rotateY(180deg);
|
||||
color: #333; /* Dunkler Text für bessere Lesbarkeit */
|
||||
}
|
||||
|
||||
/* Glanzeffekt für Light Mode */
|
||||
.card-front.light::before,
|
||||
.card-back.light::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 150%;
|
||||
height: 150%;
|
||||
background: radial-gradient(
|
||||
circle at 50% 50%,
|
||||
rgba(255, 255, 255, 0.5),
|
||||
rgba(255, 255, 255, 0) 70%
|
||||
);
|
||||
transform: translate(-25%, -25%) rotate(30deg);
|
||||
animation: subtle-glow-light 3s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
filter: blur(3px);
|
||||
mix-blend-mode: overlay; /* Leicht transparenter Glanz */
|
||||
}
|
||||
|
||||
/* Glanz-Animation für Light Mode */
|
||||
@keyframes subtle-glow-light {
|
||||
0% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.05);
|
||||
}
|
||||
50% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.2);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-25%, -25%) rotate(30deg) scale(1.05);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user