first commit
This commit is contained in:
66
src/components/islands/SkillCard.tsx
Normal file
66
src/components/islands/SkillCard.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Icon } from '@iconify-icon/react';
|
||||
import { useRef, type MouseEvent } from 'react';
|
||||
|
||||
interface Item {
|
||||
name: string;
|
||||
icon: string;
|
||||
level: 'primary' | 'secondary';
|
||||
}
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
items: Item[];
|
||||
accent?: 'cyan' | 'magenta';
|
||||
}
|
||||
|
||||
export default function SkillCard({ label, items, accent = 'cyan' }: Props) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
function onMove(e: MouseEvent<HTMLDivElement>) {
|
||||
if (!ref.current) return;
|
||||
const rect = ref.current.getBoundingClientRect();
|
||||
const x = (e.clientX - rect.left) / rect.width - 0.5;
|
||||
const y = (e.clientY - rect.top) / rect.height - 0.5;
|
||||
ref.current.style.transform = `perspective(1000px) rotateX(${-y * 6}deg) rotateY(${x * 6}deg) translateZ(0)`;
|
||||
}
|
||||
|
||||
function onLeave() {
|
||||
if (!ref.current) return;
|
||||
ref.current.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';
|
||||
}
|
||||
|
||||
const accentColor = accent === 'cyan' ? 'var(--color-cyan)' : 'var(--color-magenta)';
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
onMouseMove={onMove}
|
||||
onMouseLeave={onLeave}
|
||||
className="card-neon h-full flex flex-col transition-transform duration-300 ease-out will-change-transform"
|
||||
style={{ borderColor: `${accentColor}33` }}
|
||||
>
|
||||
<h3
|
||||
className="font-display uppercase text-xs tracking-[0.2em] mb-5"
|
||||
style={{ color: accentColor, textShadow: `0 0 10px ${accentColor}66` }}
|
||||
>
|
||||
{label}
|
||||
</h3>
|
||||
<div className="grid grid-cols-4 gap-x-3 gap-y-5 flex-1 content-start">
|
||||
{items.map((item) => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="flex flex-col items-center text-center group"
|
||||
title={item.name}
|
||||
>
|
||||
<div className="w-11 h-11 flex items-center justify-center rounded-md bg-[color:var(--color-bg)] border border-[color:var(--color-border)] group-hover:border-[color:var(--color-cyan)] transition-all group-hover:glow-cyan">
|
||||
<Icon icon={item.icon} width="22" height="22" />
|
||||
</div>
|
||||
<span className="mt-1.5 text-[10px] font-mono text-[color:var(--color-text-muted)] group-hover:text-[color:var(--color-text)] transition-colors truncate max-w-full">
|
||||
{item.name}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user