Fix hover preview to show single bounding rectangle instead of per-square borders

This commit is contained in:
Neeldhara Misra 2025-07-22 10:39:01 +05:30
parent e10c5d2b3d
commit 0cdcfe3a2e
2 changed files with 26 additions and 20 deletions

View file

@ -207,21 +207,6 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
const isRightmostCol = col === 7; const isRightmostCol = col === 7;
const isBottomRight = row === 7 && col === 7; const isBottomRight = row === 7 && col === 7;
// Get bounding box for hover preview
const boundingBox = hoveredSquare ? getBoundingBox(getAffectedSquares(hoveredSquare.row, hoveredSquare.col)) : null;
// Check if this square is on the outer perimeter of the bounding box
const isOnPerimeter = boundingBox && (
// Top edge (only if not also bottom edge)
(row === boundingBox.minRow && col >= boundingBox.minCol && col <= boundingBox.maxCol && boundingBox.minRow !== boundingBox.maxRow) ||
// Bottom edge (only if not also top edge)
(row === boundingBox.maxRow && col >= boundingBox.minCol && col <= boundingBox.maxCol && boundingBox.minRow !== boundingBox.maxRow) ||
// Left edge (only if not also right edge)
(col === boundingBox.minCol && row >= boundingBox.minRow && row <= boundingBox.maxRow && boundingBox.minCol !== boundingBox.maxCol) ||
// Right edge (only if not also left edge)
(col === boundingBox.maxCol && row >= boundingBox.minRow && row <= boundingBox.maxRow && boundingBox.minCol !== boundingBox.maxCol)
);
return ( return (
<div <div
key={`${row}-${col}`} key={`${row}-${col}`}
@ -242,7 +227,6 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
w-12 h-12 border border-gray-300 flex items-center justify-center cursor-pointer w-12 h-12 border border-gray-300 flex items-center justify-center cursor-pointer
transition-all duration-200 hover:scale-105 transition-all duration-200 hover:scale-105
${isBlack ? 'bg-gray-800' : 'bg-gray-100'} ${isBlack ? 'bg-gray-800' : 'bg-gray-100'}
${isOnPerimeter ? 'border-2 border-red-500' : ''}
`} `}
title={isBottomRight ? `Hover for 3s to switch mode (current: ${bottomRightMode})` : undefined} title={isBottomRight ? `Hover for 3s to switch mode (current: ${bottomRightMode})` : undefined}
/> />
@ -309,6 +293,30 @@ const ChessboardRepaintPuzzle: React.FC<ChessboardRepaintPuzzleProps> = ({ showS
row.map((square, colIndex) => renderSquare(rowIndex, colIndex)) row.map((square, colIndex) => renderSquare(rowIndex, colIndex))
)} )}
</div> </div>
{/* Bounding rectangle overlay */}
{hoveredSquare && (() => {
const boundingBox = getBoundingBox(getAffectedSquares(hoveredSquare.row, hoveredSquare.col));
if (!boundingBox) return null;
const squareSize = 48; // w-12 = 48px
const left = boundingBox.minCol * squareSize;
const top = boundingBox.minRow * squareSize;
const width = (boundingBox.maxCol - boundingBox.minCol + 1) * squareSize;
const height = (boundingBox.maxRow - boundingBox.minRow + 1) * squareSize;
return (
<div
className="absolute pointer-events-none border-2 border-red-500 bg-red-500 bg-opacity-10"
style={{
left: `${left}px`,
top: `${top}px`,
width: `${width}px`,
height: `${height}px`,
}}
/>
);
})()}
</div> </div>
</div> </div>

View file

@ -17,12 +17,10 @@ const Layout = ({ children }: LayoutProps) => {
<footer className="bg-surface border-t border-outline py-8 px-4 mt-auto"> <footer className="bg-surface border-t border-outline py-8 px-4 mt-auto">
<div className="max-w-6xl mx-auto text-center"> <div className="max-w-6xl mx-auto text-center">
<p className="text-muted-foreground"> <p className="text-muted-foreground">
© 2024 Interactives. Educational tools for enhanced learning experiences. © 2025 Interactives. Interactives for enhanced learning experiences and pure joy.
</p> </p>
<div className="mt-4 flex justify-center gap-6 text-sm text-muted-foreground"> <div className="mt-4 flex justify-center gap-6 text-sm text-muted-foreground">
<span>Made with for education</span> <span>Made with and help from friends and LLMs. More detailed acks coming soon!</span>
<span></span>
<span>Explore Learn Discover</span>
</div> </div>
</div> </div>
</footer> </footer>