Implementierung - SEO - 01.08.2025

This commit is contained in:
2025-08-05 15:55:01 +02:00
parent 4a4388be64
commit 7dad0a5812
31 changed files with 2839 additions and 178 deletions
+17 -17
View File
@@ -16,17 +16,17 @@ const Footer = () => {
<h3 className="text-white text-base font-semibold mb-3">
{t('footer.sections.contact.title')}
</h3>
<div className="flex flex-col space-y-2">
<div className="space-y-2">
<a
href={`mailto:${t('footer.sections.contact.email')}`}
className="group flex items-center space-x-2 text-zinc-400 hover:text-white transition-colors text-sm"
className="group flex items-center gap-2 text-zinc-400 hover:text-white transition-colors text-sm !p-0 !min-h-0 !min-w-0 w-fit"
aria-label={t('footer.sections.contact.aria.emailLink')}
>
<Mail className="h-4 w-4 text-zinc-500 group-hover:text-white transition-colors" size={16} />
<Mail className="h-4 w-4 text-zinc-500 group-hover:text-white transition-colors flex-shrink-0" size={16} />
<span>{t('footer.sections.contact.email')}</span>
</a>
<div className="flex items-center space-x-2 text-zinc-400 text-sm">
<MapPin className="h-4 w-4 text-zinc-500" size={16} />
<div className="flex items-center gap-2 text-zinc-400 text-sm w-fit">
<MapPin className="h-4 w-4 text-zinc-500 flex-shrink-0" size={16} />
<span>{t('footer.sections.contact.location')}</span>
</div>
</div>
@@ -34,31 +34,31 @@ const Footer = () => {
{/* Navigation Section */}
<div>
<h3 className="text-white text-base font-semibold mb-3">
<h3 className="text-white text-base font-semibold mb-3 text-left">
{t('footer.sections.navigation.title')}
</h3>
<nav className="flex flex-col space-y-2">
<Link
to="/portfolio"
className="text-zinc-400 hover:text-white transition-colors text-sm"
className="text-zinc-400 hover:text-white transition-colors text-sm w-fit !p-0 !min-h-0 !min-w-0"
>
{t('footer.sections.navigation.links.portfolio')}
</Link>
<Link
to="/blog"
className="text-zinc-400 hover:text-white transition-colors text-sm"
className="text-zinc-400 hover:text-white transition-colors text-sm w-fit !p-0 !min-h-0 !min-w-0"
>
{t('footer.sections.navigation.links.blog')}
</Link>
<Link
to="/about"
className="text-zinc-400 hover:text-white transition-colors text-sm"
className="text-zinc-400 hover:text-white transition-colors text-sm w-fit !p-0 !min-h-0 !min-w-0"
>
{t('footer.sections.navigation.links.about')}
</Link>
<Link
to="/contact"
className="text-zinc-400 hover:text-white transition-colors text-sm"
className="text-zinc-400 hover:text-white transition-colors text-sm w-fit !p-0 !min-h-0 !min-w-0"
>
{t('footer.sections.navigation.links.contact')}
</Link>
@@ -67,7 +67,7 @@ const Footer = () => {
{/* Social Media Section */}
<div>
<h3 className="text-white text-base font-semibold mb-3">
<h3 className="text-white text-base font-semibold mb-3 text-left">
{t('footer.sections.social.title')}
</h3>
<div className="flex space-x-4">
@@ -75,7 +75,7 @@ const Footer = () => {
href="https://www.linkedin.com/in/damjan-savić-720288127/"
target="_blank"
rel="noopener noreferrer"
className="group text-zinc-400 hover:text-white transition-colors"
className="group text-zinc-400 hover:text-white transition-colors !p-0 !min-h-0 !min-w-0"
aria-label={t('footer.sections.social.aria.linkedin')}
>
<Linkedin className="transform transition-transform group-hover:scale-110" size={20} />
@@ -84,7 +84,7 @@ const Footer = () => {
href="https://github.com/damjan1996"
target="_blank"
rel="noopener noreferrer"
className="group text-zinc-400 hover:text-white transition-colors"
className="group text-zinc-400 hover:text-white transition-colors !p-0 !min-h-0 !min-w-0"
aria-label={t('footer.sections.social.aria.github')}
>
<Github className="transform transition-transform group-hover:scale-110" size={20} />
@@ -95,19 +95,19 @@ const Footer = () => {
{/* Legal Section */}
<div className="border-t border-zinc-700/30 pt-4">
<div className="flex flex-col space-y-4">
<p className="text-zinc-400 text-xs text-center">
<p className="text-zinc-400 text-xs text-left">
&copy; {currentYear} Damjan Savić. {t('footer.legal.copyright')}
</p>
<div className="flex justify-center space-x-4">
<div className="flex space-x-4">
<Link
to="/privacy"
className="text-zinc-400 hover:text-white text-xs transition-colors"
className="text-zinc-400 hover:text-white text-xs transition-colors !p-0 !min-h-0 !min-w-0"
>
{t('footer.legal.links.privacy')}
</Link>
<Link
to="/terms"
className="text-zinc-400 hover:text-white text-xs transition-colors"
className="text-zinc-400 hover:text-white text-xs transition-colors !p-0 !min-h-0 !min-w-0"
>
{t('footer.legal.links.terms')}
</Link>
+16 -6
View File
@@ -1,5 +1,5 @@
// C:\Development\Damjan Savic\Portfolio\src\components\LanguageSwitcher.tsx
import React, { useRef, useState } from 'react';
import React, { useRef, useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Globe } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
@@ -7,6 +7,7 @@ import { motion, AnimatePresence } from 'framer-motion';
const LanguageSwitcher: React.FC = () => {
const { i18n } = useTranslation();
const [isOpen, setIsOpen] = useState(false);
const [isMobile, setIsMobile] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const languages = [
@@ -29,9 +30,18 @@ const LanguageSwitcher: React.FC = () => {
}
};
React.useEffect(() => {
useEffect(() => {
// Check if mobile on mount and resize
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener('resize', checkMobile);
document.addEventListener('mousedown', handleClickOutside);
return () => {
window.removeEventListener('resize', checkMobile);
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
@@ -56,13 +66,13 @@ const LanguageSwitcher: React.FC = () => {
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, y: -10 }}
initial={{ opacity: 0, y: isMobile ? 10 : -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
exit={{ opacity: 0, y: isMobile ? 10 : -10 }}
transition={{ duration: 0.2 }}
className="absolute top-full right-0 mt-2 w-48 rounded-lg overflow-hidden
className={`absolute ${isMobile ? 'bottom-full mb-2' : 'top-full mt-2'} right-0 w-48 rounded-lg overflow-hidden
border border-zinc-800 bg-zinc-900/95 backdrop-blur-sm
shadow-lg"
shadow-lg`}
role="listbox"
aria-label="Languages"
onKeyDown={handleKeyDown}
+9 -1
View File
@@ -210,7 +210,15 @@ const Layout = ({ children }: LayoutProps) => {
initial={{ x: "100%" }}
animate={{ x: 0 }}
exit={{ x: "100%" }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
transition={{
type: "tween",
duration: 0.3,
ease: [0.4, 0, 0.2, 1]
}}
style={{
willChange: 'transform',
transform: 'translateZ(0)'
}}
className="fixed right-0 top-0 h-full w-80 bg-zinc-900/95 backdrop-blur-md shadow-xl md:hidden z-50 border-l border-zinc-800"
>
{/* Sidebar Header mit Close-Button */}