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.
This commit is contained in:
parent
b26390bffc
commit
20e4d54a05
9 changed files with 824 additions and 59 deletions
44
app/components/badge.tsx
Normal file
44
app/components/badge.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<span
|
||||||
|
className={`${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${className}`}
|
||||||
|
style={{
|
||||||
|
transform: 'translateZ(0)',
|
||||||
|
willChange: 'transform'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
45
app/components/button.tsx
Normal file
45
app/components/button.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { ReactNode, ButtonHTMLAttributes } from 'react';
|
||||||
|
|
||||||
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
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 (
|
||||||
|
<button
|
||||||
|
className={`${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${className}`}
|
||||||
|
style={{
|
||||||
|
transform: 'translateZ(0)',
|
||||||
|
willChange: 'transform'
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
82
app/components/card.tsx
Normal file
82
app/components/card.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<div
|
||||||
|
className={`${baseClasses} ${variantClasses[variant]} ${hoverClasses} ${className}`}
|
||||||
|
style={{
|
||||||
|
transform: 'translateZ(0)',
|
||||||
|
willChange: 'transform',
|
||||||
|
...style
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CardHeaderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardHeader({ children, className = '' }: CardHeaderProps) {
|
||||||
|
return (
|
||||||
|
<div className={`p-6 pb-4 ${className}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CardContentProps {
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardContent({ children, className = '' }: CardContentProps) {
|
||||||
|
return (
|
||||||
|
<div className={`p-6 pt-0 ${className}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CardFooterProps {
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardFooter({ children, className = '' }: CardFooterProps) {
|
||||||
|
return (
|
||||||
|
<div className={`p-6 pt-4 ${className}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
4
app/components/index.ts
Normal file
4
app/components/index.ts
Normal file
|
|
@ -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';
|
||||||
56
app/components/section.tsx
Normal file
56
app/components/section.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<section
|
||||||
|
className={`${baseClasses} ${variantClasses[variant]} ${className}`}
|
||||||
|
style={{
|
||||||
|
transform: 'translateZ(0)',
|
||||||
|
willChange: 'transform'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
{(title || subtitle) && (
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
{title && (
|
||||||
|
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold text-white mb-4 tracking-tight">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
|
{subtitle && (
|
||||||
|
<p className="text-lg md:text-xl text-gray-400 max-w-3xl mx-auto leading-relaxed">
|
||||||
|
{subtitle}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="relative">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
115
app/footbar.tsx
115
app/footbar.tsx
|
|
@ -1,8 +1,117 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { Button, Badge } from "./components";
|
||||||
|
|
||||||
export default function FootBar() {
|
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 (
|
return (
|
||||||
<footer className="bg-gray-800 text-white py-4">
|
<footer className="relative bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 border-t border-gray-800/50">
|
||||||
<div className="container mx-auto text-center">
|
{/* Background Pattern */}
|
||||||
<p>© {new Date().getFullYear()} My Portfolio. All rights reserved.</p>
|
<div className="absolute inset-0 opacity-5">
|
||||||
|
<div className="absolute inset-0" style={{
|
||||||
|
backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`,
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative container mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
|
{/* Brand Section */}
|
||||||
|
<div className="lg:col-span-2">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center text-white font-bold text-lg">
|
||||||
|
MK
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-bold text-white">Mike Karl</h3>
|
||||||
|
<p className="text-gray-400 text-sm">Fullstack Developer</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 mb-6 max-w-md leading-relaxed">
|
||||||
|
Passionate developer creating modern web applications with cutting-edge technologies.
|
||||||
|
Always learning, always building.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">React</Badge>
|
||||||
|
<Badge variant="info">TypeScript</Badge>
|
||||||
|
<Badge variant="info">Rust</Badge>
|
||||||
|
<Badge variant="success">Next.js</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Links */}
|
||||||
|
<div>
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-4">Quick Links</h4>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{quickLinks.map((link) => (
|
||||||
|
<li key={link.href}>
|
||||||
|
<Link
|
||||||
|
href={link.href}
|
||||||
|
className="text-gray-300 hover:text-white transition-colors duration-300 hover:translate-x-1 inline-block"
|
||||||
|
>
|
||||||
|
{link.name}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Social Links */}
|
||||||
|
<div>
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-4">Connect</h4>
|
||||||
|
<div className="space-y-3">
|
||||||
|
{socialLinks.map((social) => (
|
||||||
|
<a
|
||||||
|
key={social.name}
|
||||||
|
href={social.href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center gap-3 text-gray-300 hover:text-white transition-all duration-300 hover:translate-x-1 group"
|
||||||
|
>
|
||||||
|
<div className="w-8 h-8 bg-gray-800/50 rounded-lg flex items-center justify-center group-hover:bg-blue-500/20 transition-colors duration-300">
|
||||||
|
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d={social.icon} />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span>{social.name}</span>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom Section */}
|
||||||
|
<div className="mt-12 pt-8 border-t border-gray-800/50">
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
|
||||||
|
<div className="text-gray-400 text-sm">
|
||||||
|
<p>© {currentYear} Mike Karl. All rights reserved.</p>
|
||||||
|
<p className="mt-1">Built with Next.js and Tailwind CSS</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<Button
|
||||||
|
variant="glass"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||||
|
>
|
||||||
|
Back to Top
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: #fff;
|
--background: #0a0a0a;
|
||||||
--foreground: #000;
|
--foreground: #e0e0e0;
|
||||||
|
--surface: #111111;
|
||||||
|
--surface-elevated: #1a1a1a;
|
||||||
|
--border: #333333;
|
||||||
|
--accent: #3b82f6;
|
||||||
|
--accent-hover: #2563eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
|
|
@ -12,15 +17,87 @@
|
||||||
--font-mono: var(--font-geist-mono);
|
--font-mono: var(--font-geist-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
* {
|
||||||
:root {
|
box-sizing: border-box;
|
||||||
--background: #0a0a0a;
|
|
||||||
--foreground: #e0e0e0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--background);
|
background: linear-gradient(135deg, #0a0a0a 0%, #111111 50%, #0a0a0a 100%);
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
font-family: monospace;
|
font-family: var(--font-geist-sans), system-ui, -apple-system, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
min-height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.1) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 80% 20%, rgba(147, 51, 234, 0.1) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 40% 40%, rgba(236, 72, 153, 0.05) 0%, transparent 50%);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhanced scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #111111;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #333333;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3D Effects */
|
||||||
|
.glass-effect {
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
-webkit-backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.neon-glow {
|
||||||
|
box-shadow:
|
||||||
|
0 0 20px rgba(59, 130, 246, 0.3),
|
||||||
|
0 0 40px rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-glow {
|
||||||
|
text-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation utilities */
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% { transform: translateY(0px); }
|
||||||
|
50% { transform: translateY(-10px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-glow {
|
||||||
|
0%, 100% { box-shadow: 0 0 20px rgba(59, 130, 246, 0.3); }
|
||||||
|
50% { box-shadow: 0 0 30px rgba(59, 130, 246, 0.6); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.float {
|
||||||
|
animation: float 6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-glow {
|
||||||
|
animation: pulse-glow 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
app/navbar.tsx
100
app/navbar.tsx
|
|
@ -1,20 +1,94 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "./components";
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ href: "/", label: "Home" },
|
||||||
|
{ href: "/cv", label: "Lebenslauf" },
|
||||||
|
{ href: "/portfolio", label: "Portfolio" },
|
||||||
|
{ href: "/contact", label: "Kontakt" }
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="flex items-center justify-between py-4 px-6 text-lg text-white bg-gray-800">
|
<nav className="fixed top-0 left-0 right-0 z-50 bg-gray-900/80 backdrop-blur-md border-b border-gray-800/30 shadow-xl">
|
||||||
<h1 className="hover:font-semibold"><Link href="/">Logo</Link></h1>
|
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<ul className="flex gap-6">
|
<div className="flex items-center justify-between h-16">
|
||||||
<li className="hover:font-semibold">
|
{/* Logo */}
|
||||||
<Link href="/cv">Lebenslauf</Link>
|
<Link
|
||||||
</li>
|
href="/"
|
||||||
<li className="hover:font-semibold">
|
className="text-2xl font-bold text-white hover:text-blue-400 transition-colors duration-300 flex items-center gap-2"
|
||||||
<Link href="/portfolio">Portfolio</Link>
|
>
|
||||||
</li>
|
<div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center text-white font-bold text-sm">
|
||||||
<li className="hover:font-semibold">
|
MK
|
||||||
<Link href="/contact">Kontakt</Link>
|
</div>
|
||||||
</li>
|
<span className="hidden sm:block">Mike Karl</span>
|
||||||
</ul>
|
</Link>
|
||||||
|
|
||||||
|
{/* Desktop Navigation */}
|
||||||
|
<div className="hidden md:flex items-center space-x-1">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className="px-4 py-2 rounded-lg text-gray-300 hover:text-white hover:bg-gray-800/50 transition-all duration-300 hover:scale-105 relative group"
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-blue-500 group-hover:w-full transition-all duration-300"></span>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<Button variant="glass" size="sm" className="ml-4">
|
||||||
|
Get in Touch
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||||
|
className="md:hidden p-2 rounded-lg text-gray-300 hover:text-white hover:bg-gray-800/50 transition-all duration-300"
|
||||||
|
aria-label="Toggle mobile menu"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-6 h-6"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
{isMobileMenuOpen ? (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
|
) : (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu */}
|
||||||
|
<div className={`md:hidden transition-all duration-300 overflow-hidden ${isMobileMenuOpen ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
|
||||||
|
}`}>
|
||||||
|
<div className="py-4 space-y-2 border-t border-gray-800/50">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className="block px-4 py-3 rounded-lg text-gray-300 hover:text-white hover:bg-gray-800/50 transition-all duration-300"
|
||||||
|
onClick={() => setIsMobileMenuOpen(false)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<div className="pt-4">
|
||||||
|
<Button variant="glass" size="sm" className="w-full">
|
||||||
|
Get in Touch
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
342
app/page.tsx
342
app/page.tsx
|
|
@ -1,40 +1,314 @@
|
||||||
import PageSection from "./page-section";
|
import { Section, Card, CardHeader, CardContent, CardFooter, Button, Badge } from "./components";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main className="pt-16">
|
||||||
<PageSection title="Hero Section" content="Fullstack / Web / Systementwickler" />
|
{/* Hero Section */}
|
||||||
<PageSection title="Lebenslauf">
|
<Section variant="hero" title="Mike Karl" subtitle="Fullstack Developer / Web Developer / System Developer">
|
||||||
<ul className="list-disc list-inside text-lg text-gray-700">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
<li>Gym Zwiesel</li>
|
<Card variant="glass" className="float">
|
||||||
<li>Uni Passau</li>
|
<CardHeader>
|
||||||
<li>Berufsschule</li>
|
<h3 className="text-xl font-semibold text-white mb-2">About Me</h3>
|
||||||
</ul>
|
</CardHeader>
|
||||||
</PageSection>
|
<CardContent>
|
||||||
<PageSection title="Hobbies" content="Motorradfahren, Astrofotografie" />
|
<p className="text-gray-300 leading-relaxed">
|
||||||
<PageSection title="Skills">
|
Passionate developer with expertise in full-stack development,
|
||||||
<ul className="list-disc list-inside text-lg text-gray-700">
|
system programming, and modern web technologies.
|
||||||
<li>Programmiersprachen: Web, System, Funktional, Desktop</li>
|
</p>
|
||||||
<li>Fisi: Virtualisierung, Networking</li>
|
</CardContent>
|
||||||
<li>Soft Skills: Teamarbeit, Kommunikation</li>
|
<CardFooter>
|
||||||
</ul>
|
<Button variant="glass" size="sm">Learn More</Button>
|
||||||
</PageSection>
|
</CardFooter>
|
||||||
<PageSection title="Privates">
|
</Card>
|
||||||
<ul className="list-disc list-inside text-lg text-gray-700">
|
|
||||||
<li>E33, LiS, etc.</li>
|
<Card variant="elevated" className="float" style={{ animationDelay: '1s' }}>
|
||||||
<li>Glücklich Vergeben ❤️</li>
|
<CardHeader>
|
||||||
</ul>
|
<h3 className="text-xl font-semibold text-white mb-2">Current Focus</h3>
|
||||||
</PageSection>
|
</CardHeader>
|
||||||
<PageSection title="Portfolio">
|
<CardContent>
|
||||||
<ul className="list-disc list-inside text-lg text-gray-700">
|
<div className="flex flex-wrap gap-2 mb-4">
|
||||||
<li>Raytracing in a Weekend</li>
|
<Badge variant="info">React</Badge>
|
||||||
<li>Interpreter Book</li>
|
<Badge variant="info">TypeScript</Badge>
|
||||||
<li>6502 Emu</li>
|
<Badge variant="info">Rust</Badge>
|
||||||
<li>Brainfuck RS</li>
|
<Badge variant="success">Next.js</Badge>
|
||||||
<li>Weitere (Rust Crate Suite, RUDP, Teamspeak, Discord)</li>
|
</div>
|
||||||
</ul>
|
<p className="text-gray-300 text-sm">
|
||||||
</PageSection>
|
Building modern web applications with cutting-edge technologies.
|
||||||
<PageSection title="Kontakt" content="Email: example@example.com - LinkedIn: [Your LinkedIn Profile] - GitHub: [Your GitHub Profile]" />
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="outlined" className="float" style={{ animationDelay: '2s' }}>
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-2">Quick Stats</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-400">Experience</span>
|
||||||
|
<span className="text-white font-medium">5+ years</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-400">Projects</span>
|
||||||
|
<span className="text-white font-medium">50+</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-400">Languages</span>
|
||||||
|
<span className="text-white font-medium">10+</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
{/* Education Section */}
|
||||||
|
<Section title="Education" subtitle="My academic journey and professional development">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<Card variant="default">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Gymnasium Zwiesel</h3>
|
||||||
|
<p className="text-gray-400 text-sm">High School Education</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300">
|
||||||
|
Foundation in mathematics, sciences, and critical thinking skills.
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="default">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">University of Passau</h3>
|
||||||
|
<p className="text-gray-400 text-sm">Higher Education</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300">
|
||||||
|
Advanced studies in computer science and software engineering.
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
{/* Skills Section */}
|
||||||
|
<Section title="Skills & Expertise" subtitle="Technical capabilities and professional skills">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
<Card variant="elevated">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">Programming Languages</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">JavaScript</Badge>
|
||||||
|
<Badge variant="info">TypeScript</Badge>
|
||||||
|
<Badge variant="info">Rust</Badge>
|
||||||
|
<Badge variant="info">Python</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 text-sm">
|
||||||
|
Web, System, Functional, and Desktop development
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="elevated">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">IT Infrastructure</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="success">Virtualization</Badge>
|
||||||
|
<Badge variant="success">Networking</Badge>
|
||||||
|
<Badge variant="success">Cloud</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 text-sm">
|
||||||
|
FISI expertise in virtualization and networking
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="elevated">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">Soft Skills</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="warning">Teamwork</Badge>
|
||||||
|
<Badge variant="warning">Communication</Badge>
|
||||||
|
<Badge variant="warning">Leadership</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 text-sm">
|
||||||
|
Strong interpersonal and collaboration skills
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
{/* Portfolio Section */}
|
||||||
|
<Section title="Featured Projects" subtitle="Some of my notable work and contributions">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<Card variant="glass" className="hover:neon-glow">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Raytracing in a Weekend</h3>
|
||||||
|
<p className="text-gray-400 text-sm">Graphics Programming</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300 mb-4">
|
||||||
|
A complete raytracing implementation built from scratch,
|
||||||
|
demonstrating advanced graphics programming concepts.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">Rust</Badge>
|
||||||
|
<Badge variant="info">Graphics</Badge>
|
||||||
|
<Badge variant="info">Math</Badge>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button variant="outline" size="sm">View Project</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="glass" className="hover:neon-glow">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Interpreter Book</h3>
|
||||||
|
<p className="text-gray-400 text-sm">Language Implementation</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300 mb-4">
|
||||||
|
A comprehensive guide to building programming language interpreters,
|
||||||
|
covering lexing, parsing, and execution.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">Compiler</Badge>
|
||||||
|
<Badge variant="info">Education</Badge>
|
||||||
|
<Badge variant="info">Documentation</Badge>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button variant="outline" size="sm">Read More</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="glass" className="hover:neon-glow">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">6502 Emulator</h3>
|
||||||
|
<p className="text-gray-400 text-sm">System Programming</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300 mb-4">
|
||||||
|
A complete emulator for the 6502 microprocessor,
|
||||||
|
implementing all instructions and addressing modes.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">Emulation</Badge>
|
||||||
|
<Badge variant="info">Low-level</Badge>
|
||||||
|
<Badge variant="info">Hardware</Badge>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button variant="outline" size="sm">Try Demo</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="glass" className="hover:neon-glow">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Brainfuck RS</h3>
|
||||||
|
<p className="text-gray-400 text-sm">Language Implementation</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300 mb-4">
|
||||||
|
A high-performance Brainfuck interpreter written in Rust,
|
||||||
|
showcasing optimization techniques and language design.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Badge variant="info">Rust</Badge>
|
||||||
|
<Badge variant="info">Performance</Badge>
|
||||||
|
<Badge variant="info">Optimization</Badge>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button variant="outline" size="sm">View Code</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
{/* Personal Section */}
|
||||||
|
<Section title="Personal Life" subtitle="Beyond code and technology">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<Card variant="default">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Hobbies & Interests</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||||
|
<span className="text-gray-300">Motorcycle Riding</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-2 h-2 bg-purple-500 rounded-full"></div>
|
||||||
|
<span className="text-gray-300">Astrophotography</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||||
|
<span className="text-gray-300">Photography</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="default">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-lg font-semibold text-white">Personal Status</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-2 h-2 bg-red-500 rounded-full"></div>
|
||||||
|
<span className="text-gray-300">E33, LiS, etc.</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-2 h-2 bg-pink-500 rounded-full pulse-glow"></div>
|
||||||
|
<span className="text-gray-300">Glücklich Vergeben ❤️</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
{/* Contact Section */}
|
||||||
|
<Section title="Get In Touch" subtitle="Let's connect and discuss opportunities">
|
||||||
|
<div className="max-w-2xl mx-auto">
|
||||||
|
<Card variant="glass" className="text-center">
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-gray-300 mb-6 text-lg">
|
||||||
|
I'm always interested in new opportunities and collaborations.
|
||||||
|
Feel free to reach out!
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
|
<Button variant="primary" size="lg">
|
||||||
|
Email: example@example.com
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="lg">
|
||||||
|
LinkedIn Profile
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="lg">
|
||||||
|
GitHub Profile
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue