feat: localize content to German across various components and add profile image
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
import React, { useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
import { useNavigation } from '../hooks/useNavigation';
|
||||
import { useScrollToSection } from '../../../shared/hooks/useScrollToSection';
|
||||
import Button from '../../../shared/components/Button';
|
||||
import { useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { Menu, X } from "lucide-react";
|
||||
import { useNavigation } from "../hooks/useNavigation";
|
||||
import { useScrollToSection } from "../../../shared/hooks/useScrollToSection";
|
||||
import Button from "../../../shared/components/Button";
|
||||
|
||||
const navItems = [
|
||||
{ id: 'home', label: 'Über mich' },
|
||||
{ id: 'skills', label: 'Fähigkeiten' },
|
||||
{ id: 'projects', label: 'Projekte' },
|
||||
{ id: 'experience', label: 'Erfahrung' },
|
||||
{ id: 'contact', label: 'Kontakt' },
|
||||
{ id: "home", label: "Über mich" },
|
||||
{ id: "skills", label: "Fähigkeiten" },
|
||||
{ id: "projects", label: "Projekte" },
|
||||
{ id: "experience", label: "Erfahrung" },
|
||||
{ id: "contact", label: "Kontakt" },
|
||||
];
|
||||
|
||||
export const Navigation: React.FC = () => {
|
||||
@@ -27,81 +27,98 @@ export const Navigation: React.FC = () => {
|
||||
<motion.nav
|
||||
initial={{ y: -120 }}
|
||||
animate={{ y: 0 }}
|
||||
transition={{ duration: 0.45, ease: 'easeOut' }}
|
||||
className={`fixed top-0 w-full z-50 transition-all duration-300 ${
|
||||
transition={{ duration: 0.45, ease: "easeOut" }}
|
||||
className={`fixed top-0 w-full z-50 ${
|
||||
isScrolled
|
||||
? 'bg-black/90 backdrop-blur-xl border-b border-green-500/20 shadow-lg shadow-emerald-500/5'
|
||||
: 'bg-transparent'
|
||||
? "bg-black/90 backdrop-blur-xl border-b border-green-500/20 shadow-lg shadow-emerald-500/5"
|
||||
: "bg-transparent"
|
||||
}`}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo */}
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className="text-2xl font-bold text-green-500 cursor-pointer"
|
||||
onClick={() => handleNavClick('home')}
|
||||
onClick={() => handleNavClick("home")}
|
||||
>
|
||||
</> Robert Bretz
|
||||
</motion.div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex gap-8">
|
||||
{navItems.map((item) => (
|
||||
<motion.button
|
||||
key={item.id}
|
||||
onClick={() => handleNavClick(item.id)}
|
||||
className={`text-sm font-medium transition-colors duration-300 pb-2 border-b-2 ${
|
||||
whileHover={activeSection !== item.id ? { color: '#ffffff' } : {}}
|
||||
className={`text-sm font-medium pb-2 border-b-2 ${
|
||||
activeSection === item.id
|
||||
? 'text-green-500 border-green-500'
|
||||
: 'text-gray-300 border-transparent hover:text-white'
|
||||
? "text-green-500 border-green-500"
|
||||
: "text-gray-300 border-transparent"
|
||||
}`}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
{item.label}
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Desktop CTA + Mobile Toggle */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="hidden md:block">
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className="hidden md:block"
|
||||
>
|
||||
<Button variant="primary" size="sm">
|
||||
Anfrage
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<button
|
||||
{/* Mobile Menu Toggle */}
|
||||
<motion.button
|
||||
type="button"
|
||||
aria-label="Open mobile menu"
|
||||
className="md:hidden p-2 rounded-full border border-green-500/20 bg-green-500/10 text-green-400 hover:text-white hover:border-green-500 transition-all"
|
||||
className="md:hidden p-2 rounded-full border border-green-500/20 bg-green-500/10 text-green-400"
|
||||
onClick={() => setIsOpen((prev) => !prev)}
|
||||
whileHover={{ scale: 1.1, borderColor: "#22c55e", color: "#ffffff" }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
>
|
||||
{isOpen ? <X size={22} /> : <Menu size={22} />}
|
||||
</button>
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
className="md:hidden bg-black/95 border-t border-green-500/20"
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: "auto" }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
transition={{ duration: 0.3, ease: "easeInOut" }}
|
||||
className="md:hidden bg-black/95 border-t border-green-500/20 overflow-hidden"
|
||||
>
|
||||
<div className="px-6 py-6 space-y-4">
|
||||
{navItems.map((item) => (
|
||||
<button
|
||||
<div className="px-6 py-6 space-y-2">
|
||||
{navItems.map((item, index) => (
|
||||
<motion.button
|
||||
key={item.id}
|
||||
onClick={() => handleNavClick(item.id)}
|
||||
className={`w-full text-left text-lg font-medium px-4 py-3 rounded-xl transition-colors duration-300 ${
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: index * 0.05 }}
|
||||
whileHover={activeSection !== item.id ? { scale: 1.02, x: 4, backgroundColor: 'rgba(255,255,255,0.05)' } : { scale: 1.02, x: 4 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
className={`w-full text-left text-lg font-medium px-4 py-3 rounded-xl ${
|
||||
activeSection === item.id
|
||||
? 'bg-green-500/15 text-green-400'
|
||||
: 'text-gray-300 hover:bg-white/5 hover:text-white'
|
||||
? "bg-green-500/15 text-green-400"
|
||||
: "text-gray-300"
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</button>
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -109,4 +126,4 @@ export const Navigation: React.FC = () => {
|
||||
</AnimatePresence>
|
||||
</motion.nav>
|
||||
);
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user