83 lines
3.4 KiB
TypeScript
83 lines
3.4 KiB
TypeScript
import { motion } from "framer-motion";
|
|
|
|
export interface SkillDetail {
|
|
name: string;
|
|
description: string;
|
|
}
|
|
|
|
export interface SkillCategory {
|
|
category: string;
|
|
skills: SkillDetail[];
|
|
}
|
|
|
|
interface SkillCardProps {
|
|
category: SkillCategory;
|
|
isExpanded: boolean;
|
|
onToggle: () => void;
|
|
}
|
|
|
|
export default function SkillCard({ category, isExpanded, onToggle }: SkillCardProps) {
|
|
return (
|
|
<motion.div
|
|
layout
|
|
onClick={onToggle}
|
|
style={{
|
|
background: isExpanded ? "rgba(255, 255, 255, 0.12)" : "rgba(255, 255, 255, 0.07)",
|
|
backdropFilter: "blur(10px)",
|
|
border: isExpanded ? "1px solid rgba(255, 255, 255, 0.3)" : "1px solid rgba(255, 255, 255, 0.15)",
|
|
borderRadius: "12px",
|
|
padding: "24px",
|
|
cursor: "pointer",
|
|
gridColumn: isExpanded ? "1 / -1" : "auto",
|
|
zIndex: isExpanded ? 10 : 1
|
|
}}
|
|
whileHover={!isExpanded ? { scale: 1.02, backgroundColor: "rgba(255, 255, 255, 0.12)" } : {}}
|
|
transition={{ duration: 0.3, type: "spring" }}
|
|
>
|
|
<motion.h3 layout="position" style={{ color: "white", marginTop: 0, marginBottom: "15px", fontSize: "1.2rem" }}>
|
|
{category.category} {isExpanded ? <span style={{ fontSize: "0.8em", opacity: 0.7 }}>(Click to collapse)</span> : null}
|
|
</motion.h3>
|
|
|
|
<motion.div layout="position" style={{ display: "flex", flexWrap: "wrap", gap: "10px", marginBottom: isExpanded ? "20px" : "0" }}>
|
|
{category.skills.map((skill) => (
|
|
<span
|
|
key={skill.name}
|
|
style={{
|
|
background: "rgba(255, 255, 255, 0.15)",
|
|
color: "rgba(255, 255, 255, 0.9)",
|
|
padding: "6px 12px",
|
|
borderRadius: "20px",
|
|
fontSize: "0.85rem",
|
|
fontWeight: 500,
|
|
border: "1px solid rgba(255, 255, 255, 0.1)"
|
|
}}
|
|
>
|
|
{skill.name}
|
|
</span>
|
|
))}
|
|
</motion.div>
|
|
|
|
{isExpanded && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 10 }}
|
|
transition={{ duration: 0.3 }}
|
|
style={{ borderTop: "1px solid rgba(255,255,255,0.2)", paddingTop: "20px" }}
|
|
>
|
|
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: "15px" }}>
|
|
{category.skills.map((skill) => (
|
|
<div key={skill.name} style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
|
|
<strong style={{ color: "#fff", fontSize: "1rem" }}>{skill.name}</strong>
|
|
<p style={{ margin: 0, color: "rgba(255,255,255,0.7)", fontSize: "0.9rem" }}>
|
|
{skill.description}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</motion.div>
|
|
);
|
|
}
|