From 20e4d54a0577337c2f21c7079e2838c459c14c0d Mon Sep 17 00:00:00 2001 From: Mike Karl Date: Tue, 21 Oct 2025 10:14:40 +0200 Subject: [PATCH] Enhance layout and styling with new Navbar and FootBar components; restructure Home page to include sections for About, Education, Skills, Projects, Personal Life, and Contact, while updating global styles for improved aesthetics. --- app/components/badge.tsx | 44 +++++ app/components/button.tsx | 45 +++++ app/components/card.tsx | 82 +++++++++ app/components/index.ts | 4 + app/components/section.tsx | 56 ++++++ app/footbar.tsx | 115 ++++++++++++- app/globals.css | 95 ++++++++++- app/navbar.tsx | 100 +++++++++-- app/page.tsx | 342 +++++++++++++++++++++++++++++++++---- 9 files changed, 824 insertions(+), 59 deletions(-) create mode 100644 app/components/badge.tsx create mode 100644 app/components/button.tsx create mode 100644 app/components/card.tsx create mode 100644 app/components/index.ts create mode 100644 app/components/section.tsx diff --git a/app/components/badge.tsx b/app/components/badge.tsx new file mode 100644 index 0000000..8368191 --- /dev/null +++ b/app/components/badge.tsx @@ -0,0 +1,44 @@ +import { ReactNode } from 'react'; + +interface BadgeProps { + children: ReactNode; + variant?: 'default' | 'success' | 'warning' | 'error' | 'info' | 'glass'; + size?: 'sm' | 'md' | 'lg'; + className?: string; +} + +export default function Badge({ + children, + variant = 'default', + size = 'md', + className = '' +}: BadgeProps) { + const baseClasses = "inline-flex items-center font-medium rounded-full transition-all duration-300 ease-out"; + + const sizeClasses = { + sm: "px-2 py-1 text-xs", + md: "px-3 py-1.5 text-sm", + lg: "px-4 py-2 text-base" + }; + + const variantClasses = { + default: "bg-gray-700/50 text-gray-300 border border-gray-600/50", + success: "bg-green-500/20 text-green-400 border border-green-500/30", + warning: "bg-yellow-500/20 text-yellow-400 border border-yellow-500/30", + error: "bg-red-500/20 text-red-400 border border-red-500/30", + info: "bg-blue-500/20 text-blue-400 border border-blue-500/30", + glass: "bg-white/10 text-white border border-white/20 backdrop-blur-sm" + }; + + return ( + + {children} + + ); +} diff --git a/app/components/button.tsx b/app/components/button.tsx new file mode 100644 index 0000000..5567573 --- /dev/null +++ b/app/components/button.tsx @@ -0,0 +1,45 @@ +import { ReactNode, ButtonHTMLAttributes } from 'react'; + +interface ButtonProps extends ButtonHTMLAttributes { + children: ReactNode; + variant?: 'primary' | 'secondary' | 'ghost' | 'outline' | 'glass'; + size?: 'sm' | 'md' | 'lg'; + className?: string; +} + +export default function Button({ + children, + variant = 'primary', + size = 'md', + className = '', + ...props +}: ButtonProps) { + const baseClasses = "inline-flex items-center justify-center font-medium rounded-lg transition-all duration-300 ease-out focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900 disabled:opacity-50 disabled:cursor-not-allowed"; + + const sizeClasses = { + sm: "px-3 py-1.5 text-sm", + md: "px-4 py-2 text-base", + lg: "px-6 py-3 text-lg" + }; + + const variantClasses = { + primary: "bg-blue-600 hover:bg-blue-700 text-white shadow-lg hover:shadow-xl hover:shadow-blue-500/25 hover:scale-105 focus:ring-blue-500", + secondary: "bg-gray-700 hover:bg-gray-600 text-white shadow-lg hover:shadow-xl hover:shadow-gray-500/25 hover:scale-105 focus:ring-gray-500", + ghost: "bg-transparent hover:bg-gray-800/50 text-gray-300 hover:text-white hover:scale-105 focus:ring-gray-500", + outline: "border-2 border-gray-600 hover:border-blue-500 bg-transparent text-gray-300 hover:text-white hover:bg-blue-500/10 hover:scale-105 focus:ring-blue-500", + glass: "bg-white/10 hover:bg-white/20 text-white border border-white/20 hover:border-white/30 backdrop-blur-sm hover:scale-105 focus:ring-white/50" + }; + + return ( + + ); +} diff --git a/app/components/card.tsx b/app/components/card.tsx new file mode 100644 index 0000000..ab57a04 --- /dev/null +++ b/app/components/card.tsx @@ -0,0 +1,82 @@ +import { ReactNode } from 'react'; + +interface CardProps { + children: ReactNode; + className?: string; + variant?: 'default' | 'elevated' | 'glass' | 'outlined'; + hover?: boolean; + style?: React.CSSProperties; +} + +export default function Card({ + children, + className = '', + variant = 'default', + hover = true, + style +}: CardProps) { + const baseClasses = "rounded-xl transition-all duration-300 ease-out"; + + const variantClasses = { + default: "bg-gray-900/50 border border-gray-800/50 backdrop-blur-sm", + elevated: "bg-gray-900/60 border border-gray-700/50 backdrop-blur-sm shadow-2xl", + glass: "bg-white/5 border border-white/10 backdrop-blur-md", + outlined: "bg-transparent border-2 border-gray-700/50" + }; + + const hoverClasses = hover + ? "hover:scale-[1.02] hover:shadow-2xl hover:shadow-blue-500/10 hover:border-blue-500/30" + : ""; + + return ( +
+ {children} +
+ ); +} + +interface CardHeaderProps { + children: ReactNode; + className?: string; +} + +export function CardHeader({ children, className = '' }: CardHeaderProps) { + return ( +
+ {children} +
+ ); +} + +interface CardContentProps { + children: ReactNode; + className?: string; +} + +export function CardContent({ children, className = '' }: CardContentProps) { + return ( +
+ {children} +
+ ); +} + +interface CardFooterProps { + children: ReactNode; + className?: string; +} + +export function CardFooter({ children, className = '' }: CardFooterProps) { + return ( +
+ {children} +
+ ); +} diff --git a/app/components/index.ts b/app/components/index.ts new file mode 100644 index 0000000..5c2f5b2 --- /dev/null +++ b/app/components/index.ts @@ -0,0 +1,4 @@ +export { default as Card, CardHeader, CardContent, CardFooter } from './card'; +export { default as Button } from './button'; +export { default as Badge } from './badge'; +export { default as Section } from './section'; diff --git a/app/components/section.tsx b/app/components/section.tsx new file mode 100644 index 0000000..695093e --- /dev/null +++ b/app/components/section.tsx @@ -0,0 +1,56 @@ +import { ReactNode } from 'react'; + +interface SectionProps { + children: ReactNode; + title?: string; + subtitle?: string; + className?: string; + variant?: 'default' | 'hero' | 'feature' | 'minimal'; +} + +export default function Section({ + children, + title, + subtitle, + className = '', + variant = 'default' +}: SectionProps) { + const baseClasses = "relative py-16 lg:py-24"; + + const variantClasses = { + default: "bg-gray-900/30", + hero: "bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900", + feature: "bg-gray-800/20", + minimal: "bg-transparent" + }; + + return ( +
+
+ {(title || subtitle) && ( +
+ {title && ( +

+ {title} +

+ )} + {subtitle && ( +

+ {subtitle} +

+ )} +
+ )} +
+ {children} +
+
+
+ ); +} diff --git a/app/footbar.tsx b/app/footbar.tsx index 8c1e045..d28224e 100644 --- a/app/footbar.tsx +++ b/app/footbar.tsx @@ -1,8 +1,117 @@ +"use client"; + +import Link from "next/link"; +import { Button, Badge } from "./components"; + export default function FootBar() { + const currentYear = new Date().getFullYear(); + + const socialLinks = [ + { name: "GitHub", href: "https://github.com", icon: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }, + { name: "LinkedIn", href: "https://linkedin.com", icon: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" }, + { name: "Email", href: "mailto:example@example.com", icon: "M24 5.457v13.909c0 .904-.732 1.636-1.636 1.636h-3.819V11.73L12 16.64l-6.545-4.91v9.273H1.636A1.636 1.636 0 0 1 0 19.366V5.457c0-.904.732-1.636 1.636-1.636h3.819l6.545 4.91 6.545-4.91h3.819c.904 0 1.636.732 1.636 1.636z" } + ]; + + const quickLinks = [ + { name: "Home", href: "/" }, + { name: "Lebenslauf", href: "/cv" }, + { name: "Portfolio", href: "/portfolio" }, + { name: "Contact", href: "/contact" } + ]; + return ( -