Spaces:
Runtime error
Runtime error
File size: 3,457 Bytes
e4d7d50 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /**
* ChessBoard component — live chess board with piece animations
* Design: Quantitative Finance Dark — cream/brown squares, high-contrast pieces
*
* FIX: Black pieces now use #FFD700 (gold) instead of #1a1a2e (invisible on dark squares)
* FIX: Square colors changed to classic chess cream (#F0D9B5) and brown (#B58863)
* FIX: Larger font size and stronger shadows for visibility
*/
import { useEffect, useState } from "react";
import { PIECES, type GameState } from "@/lib/simulation";
interface ChessBoardProps {
state: GameState;
}
export default function ChessBoard({ state }: ChessBoardProps) {
const [lastMove, setLastMove] = useState<{ from: string; to: string } | null>(null);
const [prevMoves, setPrevMoves] = useState<string[]>([]);
useEffect(() => {
if (state.moves.length > prevMoves.length) {
setPrevMoves(state.moves);
}
}, [state.moves]);
const files = "abcdefgh";
const ranks = "87654321";
const getSquareClass = (rank: number, file: number) => {
const isLight = (rank + file) % 2 === 0;
return isLight ? "chess-square-light" : "chess-square-dark";
};
return (
<div className="flex flex-col gap-1">
{/* Rank labels + board */}
<div className="flex gap-1">
{/* Rank labels */}
<div className="flex flex-col justify-around w-4">
{ranks.split("").map((r) => (
<span key={r} className="text-center font-mono leading-none" style={{ fontSize: "10px", fontWeight: 600, color: "#c8c8c8" }}>
{r}
</span>
))}
</div>
{/* Board */}
<div className="chess-board flex-1 aspect-square">
{state.board.map((row, rankIdx) =>
row.map((piece, fileIdx) => {
const squareClass = getSquareClass(rankIdx, fileIdx);
return (
<div
key={`${rankIdx}-${fileIdx}`}
className={`${squareClass} flex items-center justify-center relative`}
style={{ aspectRatio: "1" }}
>
{piece && (
<span
className="chess-piece select-none"
style={{
fontSize: "clamp(16px, 3vw, 32px)",
// White pieces: bright white; Black pieces: vivid gold — both visible on any square
color: piece === piece.toUpperCase() ? "#ffffff" : "#FFD700",
textShadow: piece === piece.toUpperCase()
? "0 1px 3px rgba(0,0,0,0.9), 0 0 8px rgba(180,210,255,0.7)"
: "0 1px 3px rgba(0,0,0,0.9), 0 0 10px rgba(255,215,0,0.8)",
filter: piece === piece.toUpperCase()
? "drop-shadow(0 0 4px rgba(180,210,255,0.6))"
: "drop-shadow(0 0 5px rgba(255,215,0,0.9))",
}}
>
{PIECES[piece] ?? piece}
</span>
)}
</div>
);
})
)}
</div>
</div>
{/* File labels */}
<div className="flex ml-5">
{files.split("").map((f) => (
<span key={f} className="flex-1 text-center font-mono" style={{ fontSize: "10px", fontWeight: 600, color: "#c8c8c8" }}>
{f}
</span>
))}
</div>
</div>
);
}
|