66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import type { ModdedGame } from "@/data/content";
|
|
import ModList from "@/components/ModList";
|
|
import "../styles/mods.css";
|
|
|
|
type Props = {
|
|
game: ModdedGame;
|
|
visible?: boolean;
|
|
/** Collapsed by default on the smaller layout, where the full list is a long scroll. */
|
|
defaultOpen?: boolean;
|
|
};
|
|
|
|
/** One game and everything built for it: header, then the game's mod list. */
|
|
export default function ModGameSection({ game, visible = true, defaultOpen = true }: Props) {
|
|
const [open, setOpen] = useState(defaultOpen);
|
|
const [hovered, setHovered] = useState(false);
|
|
|
|
const count = game.mods.length;
|
|
|
|
return (
|
|
<section
|
|
className="mod-game"
|
|
style={{
|
|
opacity: visible ? 1 : 0,
|
|
transform: visible ? "none" : "translateY(12px)",
|
|
borderColor: hovered ? "var(--border-strong)" : "var(--border)",
|
|
}}
|
|
>
|
|
<button
|
|
className="mod-game-head"
|
|
onClick={() => setOpen((v) => !v)}
|
|
onMouseEnter={() => setHovered(true)}
|
|
onMouseLeave={() => setHovered(false)}
|
|
aria-expanded={open}
|
|
>
|
|
<span
|
|
className="mod-game-chevron"
|
|
style={{ transform: open ? "rotate(90deg)" : "rotate(0deg)" }}
|
|
aria-hidden="true"
|
|
>
|
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor">
|
|
<path d="M3 1l4 4-4 4" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</span>
|
|
|
|
<span className="mod-game-heading">
|
|
<span className="mod-game-title" style={{ color: hovered ? "var(--accent)" : "var(--fg)" }}>
|
|
{game.title}
|
|
</span>
|
|
{game.platform && <span className="mod-game-platform">{game.platform}</span>}
|
|
</span>
|
|
|
|
<span className="mod-game-count">
|
|
{count} {count === 1 ? "mod" : "mods"}
|
|
</span>
|
|
</button>
|
|
|
|
{game.description && <p className="mod-game-description">{game.description}</p>}
|
|
|
|
{open && <ModList mods={game.mods} visible={visible} />}
|
|
</section>
|
|
);
|
|
}
|