Files
personal_website/src/pages/Resources.tsx
T

111 lines
4.2 KiB
TypeScript

import { motion } from 'framer-motion';
import { ExternalLink, Book, Wrench, Code, Server } from 'lucide-react';
const resourceCategories = [
{
title: 'Documentation',
icon: Book,
resources: [
{ name: 'MDN Web Docs', url: 'https://developer.mozilla.org', description: 'Web development reference' },
{ name: 'React Documentation', url: 'https://react.dev', description: 'Official React docs' },
{ name: 'TypeScript Handbook', url: 'https://www.typescriptlang.org/docs/', description: 'TypeScript guide' },
],
},
{
title: 'Development Tools',
icon: Wrench,
resources: [
{ name: 'Neovim', url: 'https://neovim.io', description: 'Hyperextensible Vim-based text editor' },
{ name: 'GitHub', url: 'https://github.com', description: 'Version control & collaboration' },
{ name: 'Gitea', url: 'https://gitea.io', description: 'Self-hosted Git service' },
{ name: 'Figma', url: 'https://figma.com', description: 'Design & prototyping' },
],
},
{
title: 'Frameworks & Libraries',
icon: Code,
resources: [
{ name: 'Tailwind CSS', url: 'https://tailwindcss.com', description: 'Utility-first CSS framework' },
{ name: 'Framer Motion', url: 'https://www.framer.com/motion/', description: 'Animation library for React' },
{ name: 'Vite', url: 'https://vitejs.dev', description: 'Fast build tool' },
],
},
{
title: 'Self-Hosting & Infrastructure',
icon: Server,
resources: [
{ name: 'Proxmox', url: 'https://www.proxmox.com', description: 'Virtualization platform' },
{ name: 'Docker', url: 'https://docker.com', description: 'Container platform' },
{ name: 'Caddy', url: 'https://caddyserver.com', description: 'Web server with automatic HTTPS' },
],
},
];
const Resources = () => {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
className="space-y-6"
>
<h1 className="font-minecraft text-3xl md:text-4xl text-primary text-glow-strong">
Resources
</h1>
<p className="font-pixel text-foreground/80">
Tools, documentation, and resources I recommend:
</p>
<div className="space-y-6">
{resourceCategories.map((category, categoryIndex) => {
const Icon = category.icon;
return (
<motion.div
key={category.title}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: categoryIndex * 0.1 }}
className="space-y-3"
>
<div className="flex items-center gap-2">
<Icon className="w-5 h-5 text-primary" />
<h2 className="font-minecraft text-xl text-primary text-glow">
{category.title}
</h2>
</div>
<div className="grid gap-2 pl-7">
{category.resources.map((resource, index) => (
<motion.a
key={resource.name}
href={resource.url}
target="_blank"
rel="noopener noreferrer"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: categoryIndex * 0.1 + index * 0.05 }}
className="group flex items-center justify-between p-3 border border-primary/20 hover:border-primary/60 transition-all duration-300 hover:bg-primary/5"
>
<div className="flex flex-col">
<span className="font-minecraft text-sm text-primary">
{resource.name}
</span>
<span className="font-pixel text-xs text-foreground/60">
{resource.description}
</span>
</div>
<ExternalLink className="w-4 h-4 text-primary opacity-0 group-hover:opacity-100 transition-opacity" />
</motion.a>
))}
</div>
</motion.div>
);
})}
</div>
</motion.div>
);
};
export default Resources;