Fix Animations, Sidebar and Footer.
This commit is contained in:
+1
-1
@@ -82,7 +82,7 @@ define(['./workbox-4a2e5f00'], (function (workbox) { 'use strict';
|
|||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.p5tdckiicb"
|
"revision": "0.t3hi6i7ipso"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+11
-13
@@ -23,19 +23,17 @@ function App() {
|
|||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<ScrollProvider>
|
<ScrollProvider>
|
||||||
<div className="flex flex-col min-h-screen bg-background text-foreground relative">
|
<Suspense fallback={null}>
|
||||||
<Layout>
|
<PageTransition>
|
||||||
<ErrorBoundary>
|
<Layout>
|
||||||
<Suspense fallback={null}>
|
<ErrorBoundary>
|
||||||
<PageTransition>
|
<AppRoutes />
|
||||||
<AppRoutes />
|
</ErrorBoundary>
|
||||||
</PageTransition>
|
<CookieBanner />
|
||||||
</Suspense>
|
<DebugOverlay />
|
||||||
</ErrorBoundary>
|
</Layout>
|
||||||
</Layout>
|
</PageTransition>
|
||||||
<CookieBanner />
|
</Suspense>
|
||||||
<DebugOverlay />
|
|
||||||
</div>
|
|
||||||
</ScrollProvider>
|
</ScrollProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function ContactInfo() {
|
|||||||
initial={{ opacity: 0, y: -20 }}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
className="p-6 bg-zinc-800/30 border border-zinc-800 rounded-lg mx-4 mb-4"
|
className="pb-6 px-6 pt-4 bg-zinc-800/30 border border-zinc-800 rounded-lg mx-4 mt-2"
|
||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h3 className="text-sm font-medium text-white tracking-wider uppercase">
|
<h3 className="text-sm font-medium text-white tracking-wider uppercase">
|
||||||
|
|||||||
+66
-58
@@ -8,64 +8,66 @@ const Footer = () => {
|
|||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-zinc-900 pt-16 pb-8 px-4 sm:px-6">
|
<footer className="relative bg-zinc-900 pt-8 pb-4 px-4">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-12 mb-12">
|
<div className="flex flex-col space-y-8">
|
||||||
{/* Contact Section */}
|
{/* Contact Section */}
|
||||||
<div className="space-y-4">
|
<div>
|
||||||
<h3 className="text-white text-lg font-semibold mb-4">
|
<h3 className="text-white text-base font-semibold mb-3">
|
||||||
{t('footer.sections.contact.title')}
|
{t('footer.sections.contact.title')}
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex items-center space-x-2 text-zinc-400 hover:text-white transition-colors">
|
<div className="flex flex-col space-y-2">
|
||||||
<Mail size={18} />
|
|
||||||
<a
|
<a
|
||||||
href={`mailto:${t('footer.sections.contact.email')}`}
|
href={`mailto:${t('footer.sections.contact.email')}`}
|
||||||
className="hover:underline"
|
className="group flex items-center space-x-2 text-zinc-400 hover:text-white transition-colors text-sm"
|
||||||
aria-label={t('footer.sections.contact.aria.emailLink')}
|
aria-label={t('footer.sections.contact.aria.emailLink')}
|
||||||
>
|
>
|
||||||
{t('footer.sections.contact.email')}
|
<Mail className="h-4 w-4 text-zinc-500 group-hover:text-white transition-colors" size={16} />
|
||||||
|
<span>{t('footer.sections.contact.email')}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<div className="flex items-center space-x-2 text-zinc-400 text-sm">
|
||||||
<div className="flex items-center space-x-2 text-zinc-400">
|
<MapPin className="h-4 w-4 text-zinc-500" size={16} />
|
||||||
<MapPin size={18} />
|
<span>{t('footer.sections.contact.location')}</span>
|
||||||
<span aria-label={t('footer.sections.contact.aria.locationText')}>
|
</div>
|
||||||
{t('footer.sections.contact.location')}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation Section */}
|
{/* Navigation Section */}
|
||||||
<div className="space-y-4">
|
<div>
|
||||||
<h3 className="text-white text-lg font-semibold mb-4">
|
<h3 className="text-white text-base font-semibold mb-3">
|
||||||
{t('footer.sections.navigation.title')}
|
{t('footer.sections.navigation.title')}
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-2">
|
<nav className="flex flex-col space-y-2">
|
||||||
<li>
|
<Link
|
||||||
<Link to="/portfolio" className="text-zinc-400 hover:text-white transition-colors">
|
to="/portfolio"
|
||||||
{t('footer.sections.navigation.links.portfolio')}
|
className="text-zinc-400 hover:text-white transition-colors text-sm"
|
||||||
</Link>
|
>
|
||||||
</li>
|
{t('footer.sections.navigation.links.portfolio')}
|
||||||
<li>
|
</Link>
|
||||||
<Link to="/blog" className="text-zinc-400 hover:text-white transition-colors">
|
<Link
|
||||||
{t('footer.sections.navigation.links.blog')}
|
to="/blog"
|
||||||
</Link>
|
className="text-zinc-400 hover:text-white transition-colors text-sm"
|
||||||
</li>
|
>
|
||||||
<li>
|
{t('footer.sections.navigation.links.blog')}
|
||||||
<Link to="/about" className="text-zinc-400 hover:text-white transition-colors">
|
</Link>
|
||||||
{t('footer.sections.navigation.links.about')}
|
<Link
|
||||||
</Link>
|
to="/about"
|
||||||
</li>
|
className="text-zinc-400 hover:text-white transition-colors text-sm"
|
||||||
<li>
|
>
|
||||||
<Link to="/contact" className="text-zinc-400 hover:text-white transition-colors">
|
{t('footer.sections.navigation.links.about')}
|
||||||
{t('footer.sections.navigation.links.contact')}
|
</Link>
|
||||||
</Link>
|
<Link
|
||||||
</li>
|
to="/contact"
|
||||||
</ul>
|
className="text-zinc-400 hover:text-white transition-colors text-sm"
|
||||||
|
>
|
||||||
|
{t('footer.sections.navigation.links.contact')}
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Social Media Section */}
|
{/* Social Media Section */}
|
||||||
<div className="space-y-4">
|
<div>
|
||||||
<h3 className="text-white text-lg font-semibold mb-4">
|
<h3 className="text-white text-base font-semibold mb-3">
|
||||||
{t('footer.sections.social.title')}
|
{t('footer.sections.social.title')}
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
@@ -73,37 +75,43 @@ const Footer = () => {
|
|||||||
href="https://www.linkedin.com/in/damjan-savić-720288127/"
|
href="https://www.linkedin.com/in/damjan-savić-720288127/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-zinc-400 hover:text-white transition-colors"
|
className="group text-zinc-400 hover:text-white transition-colors"
|
||||||
aria-label={t('footer.sections.social.aria.linkedin')}
|
aria-label={t('footer.sections.social.aria.linkedin')}
|
||||||
>
|
>
|
||||||
<Linkedin size={24} />
|
<Linkedin className="transform transition-transform group-hover:scale-110" size={20} />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/damjan1996"
|
href="https://github.com/damjan1996"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-zinc-400 hover:text-white transition-colors"
|
className="group text-zinc-400 hover:text-white transition-colors"
|
||||||
aria-label={t('footer.sections.social.aria.github')}
|
aria-label={t('footer.sections.social.aria.github')}
|
||||||
>
|
>
|
||||||
<Github size={24} />
|
<Github className="transform transition-transform group-hover:scale-110" size={20} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Legal Section */}
|
{/* Legal Section */}
|
||||||
<div className="border-t border-zinc-800 pt-8">
|
<div className="border-t border-zinc-800 pt-4">
|
||||||
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
|
<div className="flex flex-col space-y-4">
|
||||||
<p className="text-zinc-400 text-sm">
|
<p className="text-zinc-400 text-xs text-center">
|
||||||
© {currentYear} Damjan Savić. {t('footer.legal.copyright')}
|
© {currentYear} Damjan Savić. {t('footer.legal.copyright')}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex space-x-6">
|
<div className="flex justify-center space-x-4">
|
||||||
<Link to="/privacy" className="text-zinc-400 hover:text-white text-sm transition-colors">
|
<Link
|
||||||
{t('footer.legal.links.privacy')}
|
to="/privacy"
|
||||||
</Link>
|
className="text-zinc-400 hover:text-white text-xs transition-colors"
|
||||||
<Link to="/terms" className="text-zinc-400 hover:text-white text-sm transition-colors">
|
>
|
||||||
{t('footer.legal.links.terms')}
|
{t('footer.legal.links.privacy')}
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
to="/terms"
|
||||||
|
className="text-zinc-400 hover:text-white text-xs transition-colors"
|
||||||
|
>
|
||||||
|
{t('footer.legal.links.terms')}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+37
-27
@@ -120,7 +120,6 @@ const Layout = ({ children }: LayoutProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// Relativer Container, um z-index-Steuerung zu ermöglichen
|
|
||||||
<div className="min-h-screen bg-zinc-900 flex flex-col relative">
|
<div className="min-h-screen bg-zinc-900 flex flex-col relative">
|
||||||
{/* Navigation – oberste Ebene */}
|
{/* Navigation – oberste Ebene */}
|
||||||
<nav
|
<nav
|
||||||
@@ -182,16 +181,17 @@ const Layout = ({ children }: LayoutProps) => {
|
|||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{isMenuOpen && (
|
{isMenuOpen && (
|
||||||
<>
|
<>
|
||||||
{/* Backdrop: Sichtbar, aber mit pointer-events-none blockiert er keine Interaktionen */}
|
{/* Backdrop mit Click Handler */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
transition={{ duration: 0.2 }}
|
transition={{ duration: 0.2 }}
|
||||||
className="fixed inset-0 bg-black/50 md:hidden z-20 pointer-events-none"
|
className="fixed inset-0 bg-black/50 md:hidden z-20"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Sidebar – oberhalb des Hauptinhalts */}
|
{/* Sidebar */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ x: "100%" }}
|
initial={{ x: "100%" }}
|
||||||
animate={{ x: 0 }}
|
animate={{ x: 0 }}
|
||||||
@@ -199,33 +199,43 @@ const Layout = ({ children }: LayoutProps) => {
|
|||||||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||||
className="fixed right-0 top-0 h-full w-80 bg-zinc-900 shadow-xl md:hidden z-50 border-l border-zinc-800"
|
className="fixed right-0 top-0 h-full w-80 bg-zinc-900 shadow-xl md:hidden z-50 border-l border-zinc-800"
|
||||||
>
|
>
|
||||||
{/* Header-Spacer für die Navigation */}
|
{/* Header mit Close Button */}
|
||||||
<div className="h-16" />
|
<div className="h-16 flex items-center justify-between px-4 border-b border-zinc-800">
|
||||||
|
<motion.button
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="p-2 rounded-lg text-zinc-400 hover:text-white hover:bg-zinc-800/50 transition-colors"
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<X className="h-6 w-6" />
|
||||||
|
</motion.button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Scrollbarer Sidebar-Inhalt */}
|
{/* Scrollbarer Sidebar-Inhalt */}
|
||||||
<div className="h-[calc(100vh_-_4rem)] overflow-y-auto">
|
<div className="h-[calc(100vh_-_4rem)] overflow-y-auto">
|
||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
<div className="flex-1">
|
{/* Contact Info */}
|
||||||
<ContactInfo />
|
<ContactInfo />
|
||||||
<div className="py-4 px-4">
|
|
||||||
{navigationLinks.map(({ path, label, icon }) => (
|
{/* Navigation Links */}
|
||||||
<NavLink
|
<div className="py-4 px-4">
|
||||||
key={path}
|
{navigationLinks.map(({ path, label, icon }) => (
|
||||||
to={path}
|
<NavLink
|
||||||
icon={icon}
|
key={path}
|
||||||
label={label}
|
to={path}
|
||||||
// Alternativ: Hier könnte ein Klick auch das Menü schließen
|
icon={icon}
|
||||||
onClick={() => setIsMenuOpen(false)}
|
label={label}
|
||||||
className="flex items-center w-full mb-1"
|
onClick={() => setIsMenuOpen(false)}
|
||||||
/>
|
className="flex items-center w-full mb-1"
|
||||||
))}
|
/>
|
||||||
</div>
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-zinc-800 p-6 mt-auto">
|
|
||||||
|
{/* Language Switcher */}
|
||||||
|
<div className="px-4 py-3 border-t border-zinc-800">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-sm text-zinc-500">
|
<span className="text-sm text-zinc-500">
|
||||||
Sprache ändern
|
Sprache ändern
|
||||||
</span>
|
</span>
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -236,7 +246,7 @@ const Layout = ({ children }: LayoutProps) => {
|
|||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* Hauptinhalt – hier kann normal gescrollt werden */}
|
{/* Hauptinhalt */}
|
||||||
<main className="flex-1 pt-16 relative z-30">{children}</main>
|
<main className="flex-1 pt-16 relative z-30">{children}</main>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
@@ -245,4 +255,4 @@ const Layout = ({ children }: LayoutProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Layout;
|
export default Layout;
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import SEO from '../../components/SEO';
|
import SEO from '../../components/SEO';
|
||||||
import PageTransition from '../../components/PageTransition';
|
|
||||||
import Hero from './components/Hero';
|
import Hero from './components/Hero';
|
||||||
import Skills from './components/Skills';
|
import Skills from './components/Skills';
|
||||||
import Workflow from './components/Workflow';
|
import Workflow from './components/Workflow';
|
||||||
@@ -17,20 +16,14 @@ const AboutPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTransition>
|
<>
|
||||||
<SEO
|
<SEO
|
||||||
title={t('pages.about.seo.title')}
|
title={t('pages.about.seo.title')}
|
||||||
description={t('pages.about.seo.description')}
|
description={t('pages.about.seo.description')}
|
||||||
schema={generateSchema(t)}
|
schema={generateSchema(t)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="relative min-h-screen bg-zinc-900">
|
<div className="relative min-h-screen">
|
||||||
{/* Decorative Elements */}
|
|
||||||
<div className="fixed inset-0 -z-10 overflow-hidden">
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-zinc-900/50 to-zinc-900" />
|
|
||||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-1/2 bg-gradient-to-b from-zinc-800/20 to-transparent blur-3xl" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="min-h-screen relative">
|
<section className="min-h-screen relative">
|
||||||
<Hero />
|
<Hero />
|
||||||
@@ -43,7 +36,7 @@ const AboutPage = () => {
|
|||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
variants={sectionVariants}
|
variants={sectionVariants}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className="py-24 bg-zinc-900/50"
|
className="py-24 relative"
|
||||||
>
|
>
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -70,7 +63,7 @@ const AboutPage = () => {
|
|||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
variants={sectionVariants}
|
variants={sectionVariants}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className="py-24 bg-zinc-900"
|
className="py-24 relative"
|
||||||
>
|
>
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -93,7 +86,7 @@ const AboutPage = () => {
|
|||||||
{/* Journey Section */}
|
{/* Journey Section */}
|
||||||
<Journey />
|
<Journey />
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const Hero = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Top Navigation */}
|
{/* Top Navigation */}
|
||||||
<div className="absolute top-8 w-full px-8 flex justify-between items-center z-20">
|
<div className="absolute top-4 w-full px-8 flex justify-between items-center z-20">
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<a
|
<a
|
||||||
href="https://www.linkedin.com/in/damjan-savi%C4%87-720288127/"
|
href="https://www.linkedin.com/in/damjan-savi%C4%87-720288127/"
|
||||||
@@ -68,13 +68,13 @@ const Hero = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<div className="flex flex-col items-center justify-center min-h-screen px-4 relative z-10">
|
<div className="flex flex-col items-center justify-start min-h-screen px-4 pt-16 relative z-10">
|
||||||
{/* Profile Image */}
|
{/* Profile Image */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className="w-72 h-72 sm:w-96 sm:h-96 mb-8 rounded-full overflow-hidden border-2 border-zinc-800"
|
className="w-48 h-48 sm:w-64 sm:h-64 mb-6 rounded-full overflow-hidden border-2 border-zinc-800"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="/portrait.jpg"
|
src="/portrait.jpg"
|
||||||
@@ -96,7 +96,7 @@ const Hero = () => {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.3 }}
|
transition={{ duration: 0.5, delay: 0.3 }}
|
||||||
className="text-4xl font-bold mb-12 flex items-center"
|
className="text-4xl font-bold mb-8 flex items-center"
|
||||||
>
|
>
|
||||||
{t('pages.home.hero.name')}<span className="animate-pulse ml-1">|</span>
|
{t('pages.home.hero.name')}<span className="animate-pulse ml-1">|</span>
|
||||||
</motion.h1>
|
</motion.h1>
|
||||||
@@ -106,7 +106,7 @@ const Hero = () => {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.4 }}
|
transition={{ duration: 0.5, delay: 0.4 }}
|
||||||
className="flex flex-col sm:flex-row gap-4 sm:gap-8 text-white text-sm z-20"
|
className="flex flex-col sm:flex-row gap-3 sm:gap-6 text-white text-sm z-20"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={() => scrollToSection('experience')}
|
onClick={() => scrollToSection('experience')}
|
||||||
@@ -136,7 +136,7 @@ const Hero = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Contact Button Bottom */}
|
{/* Contact Button Bottom */}
|
||||||
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-20">
|
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 z-20">
|
||||||
<a
|
<a
|
||||||
href="mailto:info@damjan-savic.com"
|
href="mailto:info@damjan-savic.com"
|
||||||
className="text-white hover:text-zinc-300 transition-colors"
|
className="text-white hover:text-zinc-300 transition-colors"
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import SEO from '../../components/SEO';
|
import SEO from '../../components/SEO';
|
||||||
import PageTransition from '../../components/PageTransition';
|
|
||||||
import PortfolioGrid from './components/PortfolioGrid';
|
import PortfolioGrid from './components/PortfolioGrid';
|
||||||
|
|
||||||
const PortfolioPage = () => {
|
const PortfolioPage = () => {
|
||||||
@@ -17,19 +16,13 @@ const PortfolioPage = () => {
|
|||||||
const sortOptions = Object.entries(t('portfolio.sort', { returnObjects: true }));
|
const sortOptions = Object.entries(t('portfolio.sort', { returnObjects: true }));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTransition>
|
<>
|
||||||
<SEO
|
<SEO
|
||||||
title={t('portfolio.seo.title')}
|
title={t('portfolio.seo.title')}
|
||||||
description={t('portfolio.seo.description')}
|
description={t('portfolio.seo.description')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="relative min-h-screen bg-zinc-900">
|
<div className="relative min-h-screen">
|
||||||
{/* Decorative Elements */}
|
|
||||||
<div className="fixed inset-0 -z-10 overflow-hidden">
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-zinc-900/50 to-zinc-900" />
|
|
||||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-1/2 bg-gradient-to-b from-zinc-800/20 to-transparent blur-3xl" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<motion.section
|
<motion.section
|
||||||
initial="hidden"
|
initial="hidden"
|
||||||
@@ -111,7 +104,7 @@ const PortfolioPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</motion.section>
|
</motion.section>
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user