This commit is contained in:
parent
f45ca70b21
commit
03711da9ef
15
package-lock.json
generated
15
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"hamburger-react": "^2.5.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-image-gallery": "^1.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scroll-motion": "^0.3.0",
|
||||
@ -1984,6 +1985,14 @@
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
|
||||
"integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-image-gallery": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-image-gallery/-/react-image-gallery-1.3.0.tgz",
|
||||
@ -3713,6 +3722,12 @@
|
||||
"scheduler": "^0.23.0"
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
|
||||
"integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-image-gallery": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-image-gallery/-/react-image-gallery-1.3.0.tgz",
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
"hamburger-react": "^2.5.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-image-gallery": "^1.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scroll-motion": "^0.3.0",
|
||||
|
||||
@ -6,7 +6,9 @@ import Contact from "./pages/Contact";
|
||||
import Footer from "./components/Footer";
|
||||
import Header from "./components/Header";
|
||||
import ExperianceDetail from "./pages/ExperienceDetail";
|
||||
import FullPage from "./pages/FullPage";
|
||||
import { RecoilRoot } from "recoil";
|
||||
import ScrollToAnchor from "./components/ScrollToAnchor";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@ -14,10 +16,11 @@ function App() {
|
||||
<RecoilRoot>
|
||||
<main className=" min-h-screen">
|
||||
<Header />
|
||||
<ScrollToAnchor />
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/experience" element={<Experience />} />
|
||||
<Route path="/contact" element={<Contact />} />
|
||||
<Route path="/" element={<FullPage />} />
|
||||
{/* <Route path="/experience" element={<Experience />} />
|
||||
<Route path="/contact" element={<Contact />} />*/}
|
||||
<Route path="/experience/:id" element={<ExperianceDetail />} />
|
||||
</Routes>
|
||||
<Footer />
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { Turn as Hamburger } from "hamburger-react";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Divide as Hamburger } from "hamburger-react";
|
||||
|
||||
function Header() {
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
|
||||
const menuTimeout = 400;
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
document.body.style.overflow = isOpen ? "hidden" : "unset";
|
||||
}, [isOpen]);
|
||||
|
||||
const menu = [
|
||||
{ link: "/", title: ".me()" },
|
||||
{ link: "/experience", title: ".experience()" },
|
||||
{ link: "/contact", title: ".contact()" },
|
||||
{ link: "/#about", title: ".me()" },
|
||||
{ link: "/#experience", title: ".experience()" },
|
||||
{ link: "/#contact", title: ".contact()" },
|
||||
];
|
||||
|
||||
const menuUI = menu.map((item) => {
|
||||
@ -21,38 +26,70 @@ function Header() {
|
||||
className += " text-white/40";
|
||||
}
|
||||
return (
|
||||
<li key={item.link}>
|
||||
<Link className={className} to={item.link}>
|
||||
<li className="my-10 text-xl md:my-0 md:text-base" key={item.link}>
|
||||
<Link
|
||||
className={className}
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
to={item.link}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
const headerClasses = ["sticky", "top-0", "z-40", "backdrop-blur-sm", "h-16"];
|
||||
const logoClasses = ["hover:drop-shadow-light"];
|
||||
const overlayMenu = [
|
||||
"bg-black/90",
|
||||
"z-50",
|
||||
"fixed",
|
||||
"left-0",
|
||||
"right-0",
|
||||
"top-16",
|
||||
"h-screen",
|
||||
"backdrop-blur-sm",
|
||||
"p-2",
|
||||
];
|
||||
if (isOpen) {
|
||||
headerClasses.push("bg-black/90");
|
||||
logoClasses.push("drop-shadow-yellow");
|
||||
} else {
|
||||
headerClasses.push("bg-bgColor/90");
|
||||
logoClasses.push("drop-shadow-doublelight");
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 backdrop-blur-sm bg-bgColor/90 ">
|
||||
<div className="container mx-auto">
|
||||
<nav className="flex items-center mx-4 py-4">
|
||||
<div className="flex-none text-4xl font-black">
|
||||
<Link
|
||||
className=" drop-shadow-doublelight hover:drop-shadow-light"
|
||||
to="/"
|
||||
>
|
||||
<>
|
||||
{isOpen && (
|
||||
<div className={overlayMenu.join(" ")}>
|
||||
<div className=" h-[calc(100vh-20rem)] flex flex-col justify-center">
|
||||
<ul>{menuUI}</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<header className={headerClasses.join(" ")}>
|
||||
<div className="container mx-auto h-full">
|
||||
<nav className="flex items-center h-full px-2">
|
||||
<div className="flex-none text-4xl font-black ">
|
||||
<Link className={logoClasses.join(" ")} to="/#start">
|
||||
MS.
|
||||
</Link>
|
||||
</div>
|
||||
{/* <div className="hamburger">
|
||||
<Hamburger color="#e5e5ff" toggled={isOpen} toggle={setOpen} />
|
||||
</div> */}
|
||||
|
||||
<div className="grow"></div>
|
||||
<div className="flex-none ">
|
||||
<div className="flex-none hidden md:block ">
|
||||
<ul className="flex flex-row gap-4 text-lg">{menuUI}</ul>
|
||||
</div>
|
||||
<div className="flex-none block md:hidden">
|
||||
<Hamburger toggled={isOpen} toggle={setOpen} duration={0.9} />
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{isOpen && hamburgerMenu}
|
||||
</div>
|
||||
</header>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
28
src/components/ScrollToAnchor.jsx
Normal file
28
src/components/ScrollToAnchor.jsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
function ScrollToAnchor() {
|
||||
const location = useLocation();
|
||||
const lastHash = useRef("");
|
||||
|
||||
// listen to location change using useEffect with location as dependency
|
||||
// https://jasonwatmore.com/react-router-v6-listen-to-location-route-change-without-history-listen
|
||||
useEffect(() => {
|
||||
if (location.hash) {
|
||||
lastHash.current = location.hash.slice(1); // safe hash for further use after navigation
|
||||
}
|
||||
|
||||
if (lastHash.current && document.getElementById(lastHash.current)) {
|
||||
setTimeout(() => {
|
||||
document
|
||||
.getElementById(lastHash.current)
|
||||
?.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
lastHash.current = "";
|
||||
}, 100);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default ScrollToAnchor;
|
||||
@ -1,12 +1,12 @@
|
||||
function Tags({ listOfTags }) {
|
||||
const tagList = listOfTags.map((itemTag, keyTag) => {
|
||||
return (
|
||||
<div className={`bg-indigo-500/40 py-2 px-4 rounded-full `} key={keyTag}>
|
||||
<div className={`bg-gray-600 py-1 px-1 rounded-xl `} key={keyTag}>
|
||||
{itemTag}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return <div className="text-xs flex gap-4 mt-6 ">{tagList}</div>;
|
||||
return <div className="text-xs flex gap-2 mt-6 ">{tagList}</div>;
|
||||
}
|
||||
|
||||
export default Tags;
|
||||
|
||||
@ -4,5 +4,5 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
body {
|
||||
background-color: #302f39;
|
||||
background-color: #031417;
|
||||
}
|
||||
|
||||
10
src/pages/About.jsx
Normal file
10
src/pages/About.jsx
Normal file
@ -0,0 +1,10 @@
|
||||
function About() {
|
||||
return (
|
||||
<div className="relative">
|
||||
<div id="about" className=" absolute -top-16 "></div>
|
||||
<h1> About</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
@ -1,7 +1,8 @@
|
||||
function Contact() {
|
||||
return (
|
||||
<div className="container content">
|
||||
<h1>Welcome to Contact</h1>
|
||||
<div className="relative">
|
||||
<div id="contact" className=" absolute -top-16 "></div>
|
||||
<h1>Welcome to C#ontact</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -49,8 +49,9 @@ function Experiance() {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="container mx-auto my-10 px-6">
|
||||
<h1>Welcome to Experiance</h1>
|
||||
<div className="relative">
|
||||
<div id="experience" className=" absolute -top-16 "></div>
|
||||
<h1>Welcome to Experience</h1>
|
||||
<div className="py-4">{experianceListUI}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { projectsAtom } from "../store";
|
||||
import ImageGallery from "react-image-gallery";
|
||||
import Tags from "../components/Tags";
|
||||
import { IoChevronBackOutline as BackButton } from "react-icons/io5";
|
||||
|
||||
function ExperianceDetail() {
|
||||
const { id } = useParams();
|
||||
const experianceList = useRecoilValue(projectsAtom);
|
||||
const navigate = useNavigate();
|
||||
|
||||
//shorter variant of Find function with IF-sats
|
||||
const myProject = experianceList.find((item) => item.id === id);
|
||||
@ -35,6 +37,15 @@ function ExperianceDetail() {
|
||||
|
||||
return (
|
||||
<div className="container mx-auto my-10 px-6">
|
||||
<button
|
||||
className="text-4xl"
|
||||
aria-label="Back"
|
||||
onClick={() => {
|
||||
navigate(-1);
|
||||
}}
|
||||
>
|
||||
<BackButton />
|
||||
</button>
|
||||
<div className="flex">
|
||||
<div className="flex-1">
|
||||
<h1>Project: {myProject.title}</h1>
|
||||
@ -43,8 +54,8 @@ function ExperianceDetail() {
|
||||
<Tags listOfTags={myProject.tags} />
|
||||
</div>
|
||||
{linkUI}
|
||||
<div className="py-4 mb-8">{myProject.info}</div>
|
||||
<div className="">
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
<div className="flex-1">
|
||||
<ImageGallery
|
||||
showThumbnails={false}
|
||||
showBullets={true}
|
||||
@ -54,8 +65,11 @@ function ExperianceDetail() {
|
||||
items={projectImg}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">{myProject.info}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
4;
|
||||
|
||||
export default ExperianceDetail;
|
||||
|
||||
17
src/pages/FullPage.jsx
Normal file
17
src/pages/FullPage.jsx
Normal file
@ -0,0 +1,17 @@
|
||||
import About from "./About";
|
||||
import Contact from "./Contact";
|
||||
import Experiance from "./Experience";
|
||||
import Start from "./Start";
|
||||
|
||||
function FullPage() {
|
||||
return (
|
||||
<div className="container mx-auto px-2">
|
||||
<Start />
|
||||
<About />
|
||||
<Experiance />
|
||||
<Contact />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FullPage;
|
||||
18
src/pages/Start.jsx
Normal file
18
src/pages/Start.jsx
Normal file
@ -0,0 +1,18 @@
|
||||
function Start() {
|
||||
return (
|
||||
<div className="relative">
|
||||
<div id="start" className="absolute -top-16 "></div>
|
||||
<div>
|
||||
<h1> Start</h1>
|
||||
</div>
|
||||
<div>
|
||||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos nostrum
|
||||
repudiandae, excepturi, eaque autem tenetur commodi qui praesentium
|
||||
nesciunt atque ullam consectetur cum aliquam corporis quae maxime libero
|
||||
impedit exercitationem?
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Start;
|
||||
@ -4,7 +4,7 @@ const experianceList = [
|
||||
{
|
||||
id: "46bf76ae-8915-4e5d-ae92-4151be80e75a",
|
||||
title: "Netzero web",
|
||||
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
|
||||
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. ",
|
||||
img: [
|
||||
"/img/placeholder.png",
|
||||
"/img/placeholder.png",
|
||||
@ -17,7 +17,7 @@ const experianceList = [
|
||||
{
|
||||
id: "55515a25-deb1-451c-bc7d-006d293f54aa",
|
||||
title: "Lets fly",
|
||||
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
|
||||
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. ",
|
||||
img: [
|
||||
"/img/placeholder.png",
|
||||
"/img/placeholder.png",
|
||||
|
||||
@ -13,6 +13,7 @@ export default {
|
||||
},
|
||||
dropShadow: {
|
||||
light: "0 0 5px theme('colors.indigo.800')",
|
||||
yellow: "0 0 9px theme('colors.lime.400')",
|
||||
doublelight: [
|
||||
"0 0 5px theme('colors.lime.400')",
|
||||
"0 0 15px theme('colors.yellow.400')",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user