From 0d8152914a7c78066eb25857038fb1eb0b7be870 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Sun, 5 Apr 2026 17:27:20 +0200 Subject: [PATCH] refactor(games): inline SVG pieces instead of elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace external SVG files loaded via tags with inline React SVG components. The approach was a DOM-level problem — replaced elements sit outside React's tree and interfere with dnd-kit's pointer event pipeline. Inline SVGs are native JSX nodes that participate correctly in event bubbling, matching how react-chessboard's default pieces work. Removes panel/public/pieces/ (12 SVG files) in favor of a single pieces.tsx module with the same cburnett artwork as JSX. Co-Authored-By: Claude Opus 4.6 (1M context) --- panel/public/pieces/bB.svg | 1 - panel/public/pieces/bK.svg | 1 - panel/public/pieces/bN.svg | 1 - panel/public/pieces/bP.svg | 1 - panel/public/pieces/bQ.svg | 1 - panel/public/pieces/bR.svg | 1 - panel/public/pieces/wB.svg | 1 - panel/public/pieces/wK.svg | 1 - panel/public/pieces/wN.svg | 1 - panel/public/pieces/wP.svg | 1 - panel/public/pieces/wQ.svg | 1 - panel/public/pieces/wR.svg | 1 - panel/src/games/chess/ChessGame.tsx | 58 +++-------- panel/src/games/chess/pieces.tsx | 151 ++++++++++++++++++++++++++++ 14 files changed, 165 insertions(+), 56 deletions(-) delete mode 100644 panel/public/pieces/bB.svg delete mode 100644 panel/public/pieces/bK.svg delete mode 100644 panel/public/pieces/bN.svg delete mode 100644 panel/public/pieces/bP.svg delete mode 100644 panel/public/pieces/bQ.svg delete mode 100644 panel/public/pieces/bR.svg delete mode 100644 panel/public/pieces/wB.svg delete mode 100644 panel/public/pieces/wK.svg delete mode 100644 panel/public/pieces/wN.svg delete mode 100644 panel/public/pieces/wP.svg delete mode 100644 panel/public/pieces/wQ.svg delete mode 100644 panel/public/pieces/wR.svg create mode 100644 panel/src/games/chess/pieces.tsx diff --git a/panel/public/pieces/bB.svg b/panel/public/pieces/bB.svg deleted file mode 100644 index fd71645..0000000 --- a/panel/public/pieces/bB.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/bK.svg b/panel/public/pieces/bK.svg deleted file mode 100644 index cc9f4d5..0000000 --- a/panel/public/pieces/bK.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/bN.svg b/panel/public/pieces/bN.svg deleted file mode 100644 index 6a762dd..0000000 --- a/panel/public/pieces/bN.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/bP.svg b/panel/public/pieces/bP.svg deleted file mode 100644 index 23b2bc2..0000000 --- a/panel/public/pieces/bP.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/bQ.svg b/panel/public/pieces/bQ.svg deleted file mode 100644 index cc0dbbb..0000000 --- a/panel/public/pieces/bQ.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/bR.svg b/panel/public/pieces/bR.svg deleted file mode 100644 index 1761af8..0000000 --- a/panel/public/pieces/bR.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wB.svg b/panel/public/pieces/wB.svg deleted file mode 100644 index 3d7deb0..0000000 --- a/panel/public/pieces/wB.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wK.svg b/panel/public/pieces/wK.svg deleted file mode 100644 index 024c96a..0000000 --- a/panel/public/pieces/wK.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wN.svg b/panel/public/pieces/wN.svg deleted file mode 100644 index 0223d25..0000000 --- a/panel/public/pieces/wN.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wP.svg b/panel/public/pieces/wP.svg deleted file mode 100644 index 9949318..0000000 --- a/panel/public/pieces/wP.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wQ.svg b/panel/public/pieces/wQ.svg deleted file mode 100644 index 0d4042a..0000000 --- a/panel/public/pieces/wQ.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/public/pieces/wR.svg b/panel/public/pieces/wR.svg deleted file mode 100644 index 34ea262..0000000 --- a/panel/public/pieces/wR.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/panel/src/games/chess/ChessGame.tsx b/panel/src/games/chess/ChessGame.tsx index bcfa347..9f5eca6 100644 --- a/panel/src/games/chess/ChessGame.tsx +++ b/panel/src/games/chess/ChessGame.tsx @@ -4,36 +4,7 @@ import { Chess } from "chess.js"; import type { Square } from "chess.js"; import type { GameUIProps } from "../registry"; import { Flag, Handshake, X, Check, Clock } from "lucide-react"; -import type { PieceRenderObject } from "react-chessboard"; - -// ── Piece images (cburnett set from Lichess, CC BY-SA) ── - -const PIECE_KEYS = ["wP","wR","wN","wB","wQ","wK","bP","bR","bN","bB","bQ","bK"] as const; - -const chessPieces: PieceRenderObject = Object.fromEntries( - PIECE_KEYS.map(key => [ - key, - (props?: { svgStyle?: React.CSSProperties }) => ( - {key} - ), - ]) -); - -/** Returns the image URL for a piece key like "wQ" or "bN" */ -function pieceImgSrc(color: "white" | "black", type: string): string { - return `/pieces/${color === "white" ? "w" : "b"}${type.toUpperCase()}.svg`; -} +import { chessPieces } from "./pieces"; // ── Types matching server ChessPlayerView / ChessSpectatorView ── @@ -409,20 +380,19 @@ export function ChessGame({ state, myPlayerId, isSpectator, onAction, players }:
Promote to
- {["q", "r", "b", "n"].map(piece => ( - - ))} + {(["q", "r", "b", "n"] as const).map(piece => { + const key = `${myColor === "white" ? "w" : "b"}${piece.toUpperCase()}`; + const PieceSvg = chessPieces[key]; + return ( + + ); + })}
diff --git a/panel/src/games/chess/pieces.tsx b/panel/src/games/chess/pieces.tsx new file mode 100644 index 0000000..4b4c2d1 --- /dev/null +++ b/panel/src/games/chess/pieces.tsx @@ -0,0 +1,151 @@ +/** + * Inline SVG chess pieces (cburnett set from Lichess, CC BY-SA). + * + * These are rendered as native JSX — not tags — so they live in + * the same React/DOM tree as react-chessboard's Piece wrapper and don't + * interfere with dnd-kit's pointer-event pipeline. + */ + +import type { PieceRenderObject } from "react-chessboard"; + +type PieceProps = { svgStyle?: React.CSSProperties }; + +function svg(children: React.ReactNode) { + return (props?: PieceProps) => ( + + {children} + + ); +} + +export const chessPieces: PieceRenderObject = { + // ── White ── + + wP: svg( + + ), + + wR: svg( + + + + + + + + ), + + wN: svg( + + + + + + ), + + wB: svg( + + + + + + + + + ), + + wQ: svg( + + + + + + + ), + + wK: svg( + + + + + + + ), + + // ── Black ── + + bP: svg( + + ), + + bR: svg( + + + + + + + ), + + bN: svg( + + + + + + + ), + + bB: svg( + + + + + + + + + ), + + bQ: svg( + + + + + + + + + + + + + + ), + + bK: svg( + + + + + + + + + ), +};