Skip to content

Commit 0c44778

Browse files
committed
Fix tile positioning - match grid cell calculation exactly
1 parent 86cee49 commit 0c44778

1 file changed

Lines changed: 53 additions & 54 deletions

File tree

src/App.tsx

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -288,63 +288,62 @@ const App: React.FC = () => {
288288
</div>
289289

290290
<div
291-
className="bg-[#bbada0] p-4 rounded-lg relative touch-none overflow-hidden"
292-
style={{ width: '100%', aspectRatio: '1/1' }}
291+
className="bg-[#bbada0] p-4 rounded-lg relative touch-none"
293292
onTouchStart={handleTouchStart}
294293
onTouchEnd={handleTouchEnd}
295294
>
296-
{/* Background grid cells */}
297-
<div className="grid grid-cols-4 gap-4 absolute inset-4">
298-
{Array(GRID_SIZE * GRID_SIZE).fill(0).map((_, idx) => (
299-
<div key={`bg-${idx}`} className="bg-[#cdc1b4] rounded-md" />
300-
))}
301-
</div>
302-
303-
{/* Animated tiles */}
304-
<div className="absolute inset-4 pointer-events-none">
305-
<AnimatePresence>
306-
{tiles.map((tile) => {
307-
// Each cell is 25% of container width
308-
// Gap between cells is 16px (gap-4)
309-
// Position = (index * (cell_width + gap))
310-
const cellPercent = 25; // 100% / 4 cells
311-
const gapPx = 16;
312-
const xPos = `calc(${tile.col * cellPercent}% + ${tile.col * gapPx}px)`;
313-
const yPos = `calc(${tile.row * cellPercent}% + ${tile.row * gapPx}px)`;
314-
const tileSize = `calc(${cellPercent}% - ${gapPx}px)`;
315-
316-
return (
317-
<motion.div
318-
key={tile.id}
319-
initial={tile.isNew ? {
320-
scale: 0,
321-
opacity: 0,
322-
left: xPos,
323-
top: yPos,
324-
} : false}
325-
animate={{
326-
scale: 1,
327-
opacity: 1,
328-
left: xPos,
329-
top: yPos,
330-
}}
331-
exit={{ scale: 0, opacity: 0 }}
332-
transition={{
333-
type: "spring",
334-
stiffness: 260,
335-
damping: 26,
336-
}}
337-
className={`absolute flex items-center justify-center text-3xl font-bold rounded-md ${getTileColor(tile.value)}`}
338-
style={{
339-
width: tileSize,
340-
height: tileSize,
341-
}}
342-
>
343-
{tile.value}
344-
</motion.div>
345-
);
346-
})}
347-
</AnimatePresence>
295+
{/* Container for both grid and tiles */}
296+
<div className="relative" style={{ width: '100%', paddingBottom: '100%' }}>
297+
{/* Background grid cells */}
298+
<div className="absolute inset-0 grid grid-cols-4 gap-4">
299+
{Array(GRID_SIZE * GRID_SIZE).fill(0).map((_, idx) => (
300+
<div key={`bg-${idx}`} className="bg-[#cdc1b4] rounded-md" />
301+
))}
302+
</div>
303+
304+
{/* Animated tiles */}
305+
<div className="absolute inset-0 pointer-events-none">
306+
<AnimatePresence>
307+
{tiles.map((tile) => {
308+
// Grid has 4 columns with gap-4 (16px)
309+
// Total width = 4 cells + 3 gaps
310+
// Each cell width = (100% - 3*16px) / 4
311+
const gap = 16;
312+
const cellWidth = `calc((100% - ${3 * gap}px) / 4)`;
313+
const xPos = `calc((${cellWidth} + ${gap}px) * ${tile.col})`;
314+
const yPos = `calc((${cellWidth} + ${gap}px) * ${tile.row})`;
315+
316+
return (
317+
<motion.div
318+
key={tile.id}
319+
initial={tile.isNew ? {
320+
scale: 0,
321+
opacity: 0,
322+
} : false}
323+
animate={{
324+
scale: 1,
325+
opacity: 1,
326+
}}
327+
exit={{ scale: 0, opacity: 0 }}
328+
transition={{
329+
type: "spring",
330+
stiffness: 260,
331+
damping: 26,
332+
}}
333+
className={`absolute flex items-center justify-center text-3xl font-bold rounded-md ${getTileColor(tile.value)}`}
334+
style={{
335+
left: xPos,
336+
top: yPos,
337+
width: cellWidth,
338+
height: cellWidth,
339+
}}
340+
>
341+
{tile.value}
342+
</motion.div>
343+
);
344+
})}
345+
</AnimatePresence>
346+
</div>
348347
</div>
349348

350349
{gameOver && (

0 commit comments

Comments
 (0)