Initial commit
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user