- Added FadeInSection component to About and Projects pages for animations.
- Updated About page to use `window.scrollTo` for smooth scrolling. - Created Contact page with sections for "Kontakt" and "Impressum." - Integrated Ionicons into Contact page. - Added support for external images in Next.js config. - Added `@ionic/react` and `ionicons` dependencies. - Styled Contact page with custom CSS rules.
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
devIndicators: false,
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'avatars.githubusercontent.com',
|
||||
pathname: '/**',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Generated
+195
@@ -8,7 +8,9 @@
|
||||
"name": "portfolio",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@ionic/react": "^8.5.7",
|
||||
"framer-motion": "^12.6.2",
|
||||
"ionicons": "^8.0.8",
|
||||
"next": "15.2.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
@@ -599,6 +601,50 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.5.7.tgz",
|
||||
"integrity": "sha512-V5ZRYXD1MgAPdjfLyOejILAdTqIzpMY7/v6GSynFPPWoEpfFbGe/tNsimrYm1/D8iouigYLkJjWSeg2rpIpESA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.20.0",
|
||||
"ionicons": "^7.2.2",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core/node_modules/ionicons": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz",
|
||||
"integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/react": {
|
||||
"version": "8.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.5.7.tgz",
|
||||
"integrity": "sha512-AgX4iu6SfuBhNgYr0H+K3oGsp7ESkCsnaqZdHRO2+GtKTmo4akMrFPihGj4LrZB/IaYwcvYQR/bPWHuZGJYsnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "8.5.7",
|
||||
"ionicons": "^7.0.0",
|
||||
"tslib": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.6",
|
||||
"react-dom": ">=16.8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/react/node_modules/ionicons": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz",
|
||||
"integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "15.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.0.tgz",
|
||||
@@ -791,6 +837,110 @@
|
||||
"node": ">=12.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz",
|
||||
"integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz",
|
||||
"integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz",
|
||||
"integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz",
|
||||
"integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz",
|
||||
"integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz",
|
||||
"integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz",
|
||||
"integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.34.9",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
|
||||
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
||||
@@ -805,6 +955,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.20.0.tgz",
|
||||
"integrity": "sha512-WPrTHFngvN081RY+dJPneKQLwnOFD60OMCOQGmmSHfCW0f4ujPMzzhwWU1gcSwXPWXz5O+8cBiiCaxAbJU7kAg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"npm": ">=7.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
@@ -3100,6 +3263,38 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "8.0.8",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.8.tgz",
|
||||
"integrity": "sha512-CRHhDQA5vsNxC7raeEPqddgO90iR2F13VZS7hB0Vx7JrxJMM2060E3ddgYbpMQNJjzeBsgpkNwdBeK5qQ7RbLA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.30.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons/node_modules/@stencil/core": {
|
||||
"version": "4.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.31.0.tgz",
|
||||
"integrity": "sha512-Ei9MFJ6LPD9BMFs+klkHylbVOOYhG10Jv4bvoFf3GMH15kA41rSYkEdr4DiX84ZdErQE2qtFV/2SUyWoXh0AhA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"npm": ">=7.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.34.9",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.34.9",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.34.9",
|
||||
"@rollup/rollup-linux-x64-musl": "4.34.9",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.34.9",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.34.9"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/react": "^8.5.7",
|
||||
"framer-motion": "^12.6.2",
|
||||
"ionicons": "^8.0.8",
|
||||
"next": "15.2.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
|
||||
+53
-7
@@ -1,6 +1,7 @@
|
||||
"use client"
|
||||
import {useRef, useState, useEffect} from "react";
|
||||
import Link from "next/link";
|
||||
import FadeInSection from "@/app/components/FadeInSection";
|
||||
|
||||
export default function About() {
|
||||
const timelineData = [
|
||||
@@ -81,7 +82,7 @@ export default function About() {
|
||||
setCurrentSection(0);
|
||||
setTimelineFinished(false);
|
||||
setTimeout(() => {
|
||||
aboutMeRef.current?.scrollIntoView({behavior: "smooth", block: "start"});
|
||||
window.scrollTo({top: 0, behavior: "smooth"});
|
||||
}, 100);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
@@ -143,7 +144,7 @@ export default function About() {
|
||||
position: "relative", // Hinzugefügt
|
||||
overflowX: "hidden"
|
||||
}}>
|
||||
{/* About Me Section */}
|
||||
<FadeInSection>
|
||||
<section
|
||||
ref={aboutMeRef}
|
||||
style={{
|
||||
@@ -162,10 +163,20 @@ export default function About() {
|
||||
Scroll down to learn more about me!
|
||||
</p>
|
||||
</section>
|
||||
</FadeInSection>
|
||||
{/* Timeline Section */}
|
||||
<section style={{position: "relative", height: "100vh", overflowY: "hidden"}}>
|
||||
{/* Navigation buttons and timeline content here */}
|
||||
<div ref={scrollContainerRef} style={{ display: "flex", overflowX: "auto", scrollSnapType: "x mandatory", width: "100%", height: "100%", scrollBehavior: "smooth", scrollbarWidth: "none", msOverflowStyle: "none" }}>
|
||||
<div ref={scrollContainerRef} style={{
|
||||
display: "flex",
|
||||
overflowX: "auto",
|
||||
scrollSnapType: "x mandatory",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
scrollBehavior: "smooth",
|
||||
scrollbarWidth: "none",
|
||||
msOverflowStyle: "none"
|
||||
}}>
|
||||
{timelineData.map((item, index) => {
|
||||
const adjustedSkills = skills.map((s) => {
|
||||
const stepLevel = s.progression?.[index] ?? 0;
|
||||
@@ -197,10 +208,21 @@ export default function About() {
|
||||
<div
|
||||
key={`${skill.name}-${index}`}
|
||||
className={currentSection === index ? "skill-card animate-skill" : "skill-card"}
|
||||
style={{ textAlign: "center", width: "120px", animationDelay: `${sIndex * 100}ms`, animationFillMode: "both" }}
|
||||
style={{
|
||||
textAlign: "center",
|
||||
width: "120px",
|
||||
animationDelay: `${sIndex * 100}ms`,
|
||||
animationFillMode: "both"
|
||||
}}
|
||||
>
|
||||
<p style={{fontWeight: "bold"}}>{skill.name}</p>
|
||||
<div style={{ padding: "0.5rem 1rem", backgroundColor: "#1a001a", border: "2px solid #3d003d", borderRadius: "10px", color: "#fff" }}>
|
||||
<div style={{
|
||||
padding: "0.5rem 1rem",
|
||||
backgroundColor: "#1a001a",
|
||||
border: "2px solid #3d003d",
|
||||
borderRadius: "10px",
|
||||
color: "#fff"
|
||||
}}>
|
||||
{getSkillLabel(skill.level)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -212,12 +234,36 @@ export default function About() {
|
||||
</div>
|
||||
|
||||
{currentSection > 0 && (
|
||||
<button onClick={() => handleButtonClick(-1)} style={{ position: "absolute", top: "50%", left: "1rem", transform: "translateY(-50%)", zIndex: 10, backgroundColor: "#333", color: "#fff", border: "none", padding: "0.75rem 1rem", cursor: "pointer", borderRadius: "4px" }}>
|
||||
<button onClick={() => handleButtonClick(-1)} style={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "1rem",
|
||||
transform: "translateY(-50%)",
|
||||
zIndex: 10,
|
||||
backgroundColor: "#333",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
padding: "0.75rem 1rem",
|
||||
cursor: "pointer",
|
||||
borderRadius: "4px"
|
||||
}}>
|
||||
←
|
||||
</button>
|
||||
)}
|
||||
{currentSection < timelineData.length - 1 && (
|
||||
<button onClick={() => handleButtonClick(1)} style={{ position: "absolute", top: "50%", right: "1rem", transform: "translateY(-50%)", zIndex: 10, backgroundColor: "#333", color: "#fff", border: "none", padding: "0.75rem 1rem", cursor: "pointer", borderRadius: "4px" }}>
|
||||
<button onClick={() => handleButtonClick(1)} style={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
right: "1rem",
|
||||
transform: "translateY(-50%)",
|
||||
zIndex: 10,
|
||||
backgroundColor: "#333",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
padding: "0.75rem 1rem",
|
||||
cursor: "pointer",
|
||||
borderRadius: "4px"
|
||||
}}>
|
||||
→
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
"use client";
|
||||
|
||||
import React, {useEffect} from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function ContactPage() {
|
||||
useEffect(() => {
|
||||
// Load Ionicons if not already present
|
||||
if (!window.customElements.get("ion-icon")) {
|
||||
const script = document.createElement("script");
|
||||
script.setAttribute("type", "module");
|
||||
script.setAttribute("src", "https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js");
|
||||
document.head.appendChild(script);
|
||||
|
||||
const noModuleScript = document.createElement("script");
|
||||
noModuleScript.setAttribute("nomodule", "");
|
||||
noModuleScript.setAttribute("src", "https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js");
|
||||
document.head.appendChild(noModuleScript);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="css_body">
|
||||
<main>
|
||||
<h1>Kontakt und Impressum</h1>
|
||||
|
||||
<article>
|
||||
<h2>Kontakt</h2>
|
||||
<section className="contact-list">
|
||||
<div className="contact-item">
|
||||
<p className="contact-name">Frederik Spirgi</p>
|
||||
<a className="contact-link" href="https://github.com/IM23a-spirgif" target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
<img className="contact-pic" src="https://avatars.githubusercontent.com/u/143030312?v=4"
|
||||
alt="Frederik Spirgi"/>
|
||||
<span className="icon">
|
||||
Writer & Developer
|
||||
<br/>
|
||||
<ion-icon name="logo-github"></ion-icon>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<h2>Impressum</h2>
|
||||
<section className="impressum">
|
||||
<p className="impressum-item">
|
||||
<strong>Frederik Spirgi</strong><br/>
|
||||
Frederik@spirgi.com<br/>
|
||||
077 533 70 36
|
||||
</p>
|
||||
</section>
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function toggleSidebar() {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
if (!sidebar) return;
|
||||
const isOpen = sidebar.style.transform === "translateX(0%)";
|
||||
sidebar.style.transform = isOpen ? "translateX(-100%)" : "translateX(0%)";
|
||||
}
|
||||
@@ -369,3 +369,114 @@ nav.navbar {
|
||||
}
|
||||
}
|
||||
|
||||
/* === Contact Page === */
|
||||
.contact-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 220px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contact-pic {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.contact-pic:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.contact-name {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
margin-top: 1rem;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.contact-link {
|
||||
text-decoration: none;
|
||||
color: #ddd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 0.5rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.contact-link .icon {
|
||||
font-size: 0.9rem;
|
||||
margin-top: 0.5rem;
|
||||
text-align: center;
|
||||
color: #ccc;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.contact-link:hover .icon {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.impressum {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.impressum-item {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 10px;
|
||||
color: #ffffff;
|
||||
min-width: 240px;
|
||||
text-align: center;
|
||||
box-shadow: 0 0 10px rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
main h1,
|
||||
main h2 {
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
main {
|
||||
animation: fadeIn 0.8s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(15px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contact-pic {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.impressum-item {
|
||||
padding: 1rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import FadeInSection from "@/app/components/FadeInSection";
|
||||
|
||||
const projectData = [
|
||||
{
|
||||
@@ -46,6 +47,7 @@ export default function ProjectsPage() {
|
||||
|
||||
return (
|
||||
<div className="projectContainer">
|
||||
<FadeInSection>
|
||||
<div className={`projectCard ${fade ? "fade-out" : "fade-in"}`}>
|
||||
<h2 className="projectTitle">{project.title}</h2>
|
||||
<Image
|
||||
@@ -62,6 +64,7 @@ export default function ProjectsPage() {
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</FadeInSection>
|
||||
<div className="projectNavigation">
|
||||
<button onClick={() => handleNavigation("prev")} className="arrowButton">
|
||||
←
|
||||
|
||||
Reference in New Issue
Block a user