147 lines
5.3 KiB
TypeScript
147 lines
5.3 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { Layers, Cpu, Database, Server } from "lucide-react";
|
|
import GlassCard from "@/components/ui/GlassCard";
|
|
import { fadeUp, stagger, viewportConfig } from "@/lib/animations";
|
|
import type { Dictionary, Locale } from "@/lib/dictionaries";
|
|
|
|
const skillGroups = [
|
|
{
|
|
icon: Layers,
|
|
category: "Frontend",
|
|
items: ["Next.js", "React", "React Native", "Tailwind CSS"],
|
|
color: "from-blue-400/20 to-blue-500/5",
|
|
border: "group-hover:border-blue-400/40",
|
|
iconBg: "bg-blue-500/10 border-blue-400/20 text-blue-300",
|
|
iconHover: "group-hover:bg-blue-500/20 group-hover:border-blue-400/50",
|
|
},
|
|
{
|
|
icon: Cpu,
|
|
category: "Backend",
|
|
items: ["Java", "Spring Boot", "Node.js", "TypeScript", "C++", "Bash"],
|
|
color: "from-emerald-400/20 to-emerald-500/5",
|
|
border: "group-hover:border-emerald-400/40",
|
|
iconBg: "bg-emerald-500/10 border-emerald-400/20 text-emerald-300",
|
|
iconHover:
|
|
"group-hover:bg-emerald-500/20 group-hover:border-emerald-400/50",
|
|
},
|
|
{
|
|
icon: Database,
|
|
category: "Databases",
|
|
items: ["PostgreSQL", "MySQL"],
|
|
color: "from-amber-400/20 to-amber-500/5",
|
|
border: "group-hover:border-amber-400/40",
|
|
iconBg: "bg-amber-500/10 border-amber-400/20 text-amber-300",
|
|
iconHover: "group-hover:bg-amber-500/20 group-hover:border-amber-400/50",
|
|
},
|
|
{
|
|
icon: Server,
|
|
category: "Infrastructure & DevOps",
|
|
items: ["Linux", "CI/CD", "Docker", "Traefik", "NGINX", "VPS"],
|
|
color: "from-purple-400/20 to-purple-500/5",
|
|
border: "group-hover:border-purple-400/40",
|
|
iconBg: "bg-purple-500/10 border-purple-400/20 text-purple-300",
|
|
iconHover: "group-hover:bg-purple-500/20 group-hover:border-purple-400/50",
|
|
},
|
|
];
|
|
|
|
interface TechStackProps {
|
|
locale: Locale;
|
|
dict: Dictionary;
|
|
}
|
|
|
|
export default function TechStack({ dict }: TechStackProps) {
|
|
return (
|
|
<section className="relative w-full py-24 sm:py-32">
|
|
{/* Subtle grid background */}
|
|
<div className="pointer-events-none absolute inset-0 grid-bg [mask-image:radial-gradient(ellipse_at_center,#000_20%,transparent_70%)] opacity-30" />
|
|
|
|
<div className="relative mx-auto w-full max-w-7xl px-6 lg:px-8">
|
|
{/* Header */}
|
|
<motion.div
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={viewportConfig}
|
|
variants={stagger(0.06)}
|
|
className="mx-auto mb-16 max-w-3xl text-center"
|
|
>
|
|
<motion.span
|
|
variants={fadeUp}
|
|
className="mb-6 inline-flex items-center gap-2 rounded-full border border-purple-400/30 bg-purple-500/10 px-3.5 py-1.5 font-mono text-xs tracking-tight text-purple-300 backdrop-blur-md"
|
|
>
|
|
{dict.techStack.badge}
|
|
</motion.span>
|
|
|
|
<motion.h2
|
|
variants={fadeUp}
|
|
className="font-display text-display-lg font-medium tracking-tight"
|
|
>
|
|
<span className="text-gradient-fade">
|
|
{dict.techStack.title}
|
|
</span>{" "}
|
|
<span className="text-gradient-purple">
|
|
{dict.techStack.titleAccent}
|
|
</span>
|
|
</motion.h2>
|
|
|
|
<motion.p
|
|
variants={fadeUp}
|
|
className="mx-auto mt-6 max-w-xl text-base leading-relaxed text-text-secondary"
|
|
>
|
|
{dict.techStack.subtitle}
|
|
</motion.p>
|
|
</motion.div>
|
|
|
|
{/* Skill cards */}
|
|
<motion.div
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={viewportConfig}
|
|
variants={stagger(0.1)}
|
|
className="grid grid-cols-1 gap-4 md:grid-cols-2"
|
|
>
|
|
{skillGroups.map((group) => (
|
|
<motion.div
|
|
key={group.category}
|
|
variants={fadeUp}
|
|
className="group h-full"
|
|
>
|
|
<GlassCard className={`h-full ${group.border}`}>
|
|
{/* Gradient accent on hover */}
|
|
<div
|
|
className={`absolute inset-0 rounded-2xl bg-gradient-to-br ${group.color} opacity-0 transition-opacity duration-500 group-hover:opacity-100`}
|
|
/>
|
|
|
|
<div className="relative">
|
|
<div className="mb-5 flex items-center gap-3">
|
|
<div
|
|
className={`flex h-10 w-10 items-center justify-center rounded-lg border transition-all duration-500 ${group.iconBg} ${group.iconHover}`}
|
|
>
|
|
<group.icon className="h-5 w-5" strokeWidth={1.5} />
|
|
</div>
|
|
<h3 className="text-base font-medium text-text-primary">
|
|
{group.category}
|
|
</h3>
|
|
</div>
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
{group.items.map((item) => (
|
|
<span
|
|
key={item}
|
|
className="rounded-lg border border-border/60 bg-surface/60 px-3 py-1.5 font-mono text-xs text-text-secondary transition-all duration-300 hover:border-purple-400/40 hover:text-purple-200"
|
|
>
|
|
{item}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</GlassCard>
|
|
</motion.div>
|
|
))}
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|