feat: add edit mode rules and use existing CSS classes

Rules Implemented:
1. Can only enter edit mode on empty cells or user-entered cells
2. Pressing 'i' on a given cell (from algo) triggers red flash
3. Edit mode blocked on cells with 'given' class

Visual Changes:
- Use existing 'active' class for normal mode cursor (blue glow)
- Use existing 'editing' class for edit mode (yellow/amber glow)
- Removed custom cursor/cursor-edit classes
- Matches original CSS design from src_old

Cell Detection:
- Check if cell has 'given' class before entering edit mode
- Given cells: From puzzle generation (immutable)
- Empty or user-entered cells: Can be edited

Flow:
1. Navigate to given cell → Press 'i' → Red flash (blocked)
2. Navigate to empty cell → Press 'i' → Yellow editing glow
3. Navigate to user-entered cell → Press 'i' → Yellow editing glow
4. Press Escape → Return to blue active glow

Phase 40.3.2 complete.
This commit is contained in:
2025-10-22 19:27:47 +01:00
parent 0ce1d7fe65
commit c5e98dafb8
3 changed files with 15 additions and 28 deletions
-25
View File
@@ -255,31 +255,6 @@
}
}
/* Cursor highlight - Normal mode */
.sudoku-cell.cursor {
background-color: rgba(59, 130, 246, 0.3);
outline: 3px solid rgb(59, 130, 246);
outline-offset: -3px;
z-index: 10;
position: relative;
}
/* Cursor highlight - Edit mode */
.sudoku-cell.cursor-edit {
background-color: rgba(34, 197, 94, 0.3);
outline: 3px solid rgb(34, 197, 94);
animation: edit-pulse 1.5s ease-in-out infinite;
}
@keyframes edit-pulse {
0%, 100% {
outline-color: rgb(34, 197, 94);
}
50% {
outline-color: rgb(74, 222, 128);
}
}
/* Invalid move flash */
.sudoku-cell.invalid-move {
background-color: rgba(239, 68, 68, 0.4);
+12
View File
@@ -102,6 +102,18 @@ export function useCursor(gameStatusManager: GameStatusManager, containerRef: Re
}
if (key === 'i') {
const container = containerRef.current;
if (!container) return;
const cells = container.querySelectorAll('.sudoku-cell');
const index = position.row * 9 + position.col;
const targetCell = cells[index];
if (targetCell && targetCell.classList.contains('given')) {
flashInvalidMove();
return;
}
setMode('edit');
return;
}
+3 -3
View File
@@ -19,7 +19,7 @@ export function useCursorRender(
const cells = container.querySelectorAll('.sudoku-cell');
cells.forEach(cell => {
cell.classList.remove('cursor', 'cursor-edit');
cell.classList.remove('active', 'editing');
});
const index = position.row * 9 + position.col;
@@ -27,9 +27,9 @@ export function useCursorRender(
if (targetCell) {
if (mode === 'edit') {
targetCell.classList.add('cursor', 'cursor-edit');
targetCell.classList.add('editing');
} else {
targetCell.classList.add('cursor');
targetCell.classList.add('active');
}
}
}, [position, mode, containerRef, gameStatus, boardRendered]);