Stage 7 polish: UI/UX refinements (shell, board zoom, hint-on-board, history, ...) #8
@@ -0,0 +1,26 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
// Item 5: zooming the board must enlarge the labels too (a magnifying-glass zoom).
|
||||||
|
// cqw is sized against the zoom-scaled board, so the font grows with the cells.
|
||||||
|
test('zoom enlarges the board labels with the board', async ({ page }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.getByRole('button', { name: /guest/i }).click();
|
||||||
|
await page.getByRole('button', { name: /Ann/ }).click();
|
||||||
|
|
||||||
|
const letter = page.locator('[data-cell] .letter').first();
|
||||||
|
await expect(letter).toBeVisible();
|
||||||
|
const base = await letter.evaluate((el) => parseFloat(getComputedStyle(el).fontSize));
|
||||||
|
|
||||||
|
// Double-tap an empty cell to zoom in (two synchronous clicks = a double-tap).
|
||||||
|
await page
|
||||||
|
.locator('[data-cell]:not(.filled)')
|
||||||
|
.nth(20)
|
||||||
|
.evaluate((el: HTMLElement) => {
|
||||||
|
el.click();
|
||||||
|
el.click();
|
||||||
|
});
|
||||||
|
await page.waitForTimeout(400); // let the width transition settle
|
||||||
|
|
||||||
|
const zoomed = await letter.evaluate((el) => parseFloat(getComputedStyle(el).fontSize));
|
||||||
|
expect(zoomed).toBeGreaterThan(base * 1.4);
|
||||||
|
});
|
||||||
@@ -92,8 +92,7 @@
|
|||||||
.popover {
|
.popover {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: calc(100% + 6px);
|
bottom: calc(100% + 6px);
|
||||||
left: 50%;
|
right: 0;
|
||||||
transform: translateX(-50%);
|
|
||||||
z-index: 19;
|
z-index: 19;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
class="cell {premClass[premium[r][c]]}"
|
class="cell {premClass[premium[r][c]]}"
|
||||||
class:filled={!!cell}
|
class:filled={!!cell}
|
||||||
class:pending={!!p && !cell}
|
class:pending={!!p && !cell}
|
||||||
class:hl={!!cell && highlight.has(key(r, c))}
|
class:hl={!!cell && highlight.has(key(r, c)) && !flash}
|
||||||
class:flash={!!cell && flash && highlight.has(key(r, c))}
|
class:flash={!!cell && flash && highlight.has(key(r, c))}
|
||||||
data-cell
|
data-cell
|
||||||
data-row={r}
|
data-row={r}
|
||||||
@@ -115,14 +115,16 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: var(--board-bg);
|
background: var(--board-bg);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
container-type: inline-size;
|
|
||||||
}
|
}
|
||||||
.viewport.zoomed {
|
.viewport.zoomed {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
/* The query container is the (zoom-scaled) board, so cqw labels scale WITH the board
|
||||||
|
— a magnifying-glass zoom. */
|
||||||
.scaler {
|
.scaler {
|
||||||
width: calc(100% * var(--z));
|
width: calc(100% * var(--z));
|
||||||
transition: width 0.25s ease;
|
transition: width 0.25s ease;
|
||||||
|
container-type: inline-size;
|
||||||
}
|
}
|
||||||
.grid {
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -167,7 +169,8 @@
|
|||||||
background: var(--tile-recent);
|
background: var(--tile-recent);
|
||||||
}
|
}
|
||||||
.cell.flash {
|
.cell.flash {
|
||||||
animation: tileflash 1s ease-in-out infinite;
|
/* Two flashes to draw the eye, then settle back to normal so it does not distract. */
|
||||||
|
animation: tileflash 1s ease-in-out 2;
|
||||||
}
|
}
|
||||||
@keyframes tileflash {
|
@keyframes tileflash {
|
||||||
0%,
|
0%,
|
||||||
|
|||||||
Reference in New Issue
Block a user