From e88e67de4b0e534c6bf2d75580046179676b9bc6 Mon Sep 17 00:00:00 2001 From: Christoph Wagner Date: Sun, 23 Nov 2025 19:28:45 +0100 Subject: [PATCH] fix: resolve promotion dialog bugs and column resizing issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit addresses three critical bugs reported after initial PR: 1. **Promotion dialog not closing after piece selection** - Changed from `style.display` to HTML5 `.showModal()` and `.close()` - Fixed selector from `.promotion-piece .symbol` to `.promotion-piece .piece-icon` - Fixed data attribute from `dataset.type` to `dataset.piece` - Dialog now properly closes after user selects promotion piece 2. **Pawn showing as queen before user selection** - Removed automatic promotion to queen in GameController.js:112-115 - Now emits 'promotion' event WITHOUT pre-promoting - User sees pawn until they select the promotion piece - Promotion happens only after user makes their choice 3. **Column resizing not fully fixed** - Added explicit `max-width: 250px` to `.game-sidebar` and `.captured-pieces` - Added explicit `max-width: 250px` to `.move-history-section` - Added `overflow: hidden` to `.captured-list` and `overflow-x: hidden` to `.move-history` - Added `min-width: 600px` to `.board-section` - Added `width: 100%` to all sidebar components for proper constraint application - Columns now maintain stable widths even with content changes **Files Changed:** - `js/main.js` - Fixed promotion dialog handling - `js/controllers/GameController.js` - Removed auto-promotion - `css/main.css` - Added width constraints and overflow handling **Root Causes:** - Dialog: Mixing HTML5 dialog API with legacy display styles - Promotion: Auto-promoting before showing user dialog - Resizing: Missing explicit max-widths allowed flex items to grow with content 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- css/main.css | 12 ++++++++++++ js/controllers/GameController.js | 9 +++------ js/main.js | 19 +++++++------------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/css/main.css b/css/main.css index 9327ff3..f6fede6 100644 --- a/css/main.css +++ b/css/main.css @@ -103,12 +103,16 @@ body { display: flex; align-items: center; justify-content: center; + min-width: 600px; + width: 100%; } .game-sidebar { display: flex; flex-direction: column; gap: 1.5rem; + width: 100%; + max-width: 250px; } .captured-pieces { @@ -116,6 +120,8 @@ body { padding: 1rem; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + width: 100%; + max-width: 250px; } .captured-pieces h3 { @@ -130,6 +136,8 @@ body { flex-wrap: wrap; gap: 0.5rem; min-height: 60px; + max-width: 100%; + overflow: hidden; } .move-history-section { @@ -138,13 +146,17 @@ body { border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); flex: 1; + width: 100%; + max-width: 250px; } .move-history { max-height: 400px; overflow-y: auto; + overflow-x: hidden; font-family: 'Courier New', monospace; font-size: 0.9rem; + width: 100%; } .game-controls { diff --git a/js/controllers/GameController.js b/js/controllers/GameController.js index 3379bc3..2caf908 100644 --- a/js/controllers/GameController.js +++ b/js/controllers/GameController.js @@ -108,14 +108,11 @@ export class GameController { const moveResult = this.board.movePiece(fromRow, fromCol, toRow, toCol); captured = moveResult.captured; - // Check for promotion + // Check for promotion - emit event WITHOUT auto-promoting if (specialMoveType === 'promotion' || (piece.type === 'pawn' && piece.canPromote())) { - // Default to queen, UI should prompt for choice - const newPiece = SpecialMoves.promote(this.board, piece, 'queen'); - promotedTo = newPiece.type; - - // Emit promotion event for UI to handle + // Emit promotion event for UI to handle - DON'T auto-promote yet this.emit('promotion', { pawn: piece, position: { row: toRow, col: toCol } }); + // promotedTo will be set when the UI calls back with the chosen piece } } diff --git a/js/main.js b/js/main.js index a79ba42..5971537 100644 --- a/js/main.js +++ b/js/main.js @@ -263,7 +263,6 @@ class ChessApp { * @param {Position} position - Pawn position */ showPromotionDialog(pawn, position) { - const overlay = document.getElementById('promotion-overlay'); const dialog = document.getElementById('promotion-dialog'); if (!dialog) { @@ -271,25 +270,22 @@ class ChessApp { return; } - if (overlay) { - overlay.style.display = 'block'; - } - dialog.style.display = 'block'; + // Show dialog using HTML5 dialog element API + dialog.showModal(); // Update symbols for current color const symbols = pawn.color === 'white' ? { queen: '♕', rook: '♖', bishop: '♗', knight: '♘' } : { queen: '♛', rook: '♜', bishop: '♝', knight: '♞' }; - document.querySelectorAll('.promotion-piece .symbol').forEach(el => { - const type = el.parentElement.dataset.type; + document.querySelectorAll('.promotion-piece .piece-icon').forEach(el => { + const type = el.parentElement.dataset.piece; el.textContent = symbols[type]; - el.style.color = pawn.color === 'white' ? '#ffffff' : '#000000'; }); // Handle selection const handleSelection = (e) => { - const pieceType = e.currentTarget.dataset.type; + const pieceType = e.currentTarget.dataset.piece; // Promote pawn import('./engine/SpecialMoves.js').then(({ SpecialMoves }) => { @@ -297,9 +293,8 @@ class ChessApp { this.updateDisplay(); }); - // Hide dialog - overlay.style.display = 'none'; - dialog.style.display = 'none'; + // Close dialog using HTML5 dialog element API + dialog.close(); // Remove listeners document.querySelectorAll('.promotion-piece').forEach(el => {