Files
hwilliams-dev/components/ModCard.tsx

87 lines
2.5 KiB
TypeScript

"use client";
import { useState } from "react";
import type { Mod } from "@/data/content";
import "../styles/mods.css";
type Props = {
mod: Mod;
visible?: boolean;
};
/** One mod: the list item card inside a game's mod list. */
export default function ModCard({ mod, visible = true }: Props) {
const [hovered, setHovered] = useState(false);
return (
<a
className="mod-card"
href={mod.link}
target="_blank"
rel="noreferrer noopener"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
background: hovered ? "var(--surface-hover)" : "var(--surface)",
border: `1px solid ${hovered ? "var(--accent)" : "var(--border)"}`,
transform: visible ? (hovered ? "translateY(-2px)" : "none") : "translateY(8px)",
opacity: visible ? 1 : 0,
boxShadow: hovered ? "var(--shadow-md)" : "none",
}}
>
<div className="mod-card-head">
<span
className="mod-card-title"
style={{ color: hovered ? "var(--accent)" : "var(--fg)" }}
>
{mod.title}
</span>
{mod.version && <span className="mod-card-version">v{mod.version}</span>}
</div>
<p className="mod-card-description">{mod.description}</p>
<div className="mod-card-foot">
{mod.tags && mod.tags.length > 0 && (
<div className="mod-card-tags">
{mod.tags.map((tag) => (
<span key={tag} className="mod-tag">
{tag}
</span>
))}
</div>
)}
<span
className="mod-card-link"
style={{
borderColor: hovered ? "var(--accent)" : "var(--border)",
color: hovered ? "var(--accent)" : "var(--fg-secondary)",
}}
>
{mod.linkLabel ?? "Repository"}
<svg
width="11"
height="11"
viewBox="0 0 14 14"
fill="none"
stroke="currentColor"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path d="M5 1h8v8" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M13 1L6 8" strokeWidth="1.5" strokeLinecap="round" />
<path
d="M11 9v4H1V3h4"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</span>
</div>
</a>
);
}