feat: introduce the compact vehicle HUD

This commit is contained in:
2026-09-02 15:44:50 +03:00
parent 8deb56ed0c
commit c4f1a38a78
12 changed files with 668 additions and 192 deletions

View File

@@ -8,6 +8,7 @@ const stylesheetFiles = [
'src/styles/base.css',
'src/styles/layout.css',
'src/styles/components.css',
'src/styles/world.css',
'src/styles/print.css',
];
@@ -151,6 +152,51 @@ test('uses a stable tablet rhythm and a single readable mobile column with usabl
await capture(page, testInfo, 'information-layer-mobile.png');
});
test('keeps the compact HUD in one safe lower row without covering the road corridor', async ({ page }) => {
for (const viewport of [
{ width: 320, height: 800 },
{ width: 1440, height: 900 },
]) {
await page.setViewportSize(viewport);
await loadInformationLayer(page);
const geometry = await page.evaluate(() => {
const controls = document.querySelector<HTMLElement>('.drive-controls');
const hud = document.querySelector<HTMLElement>('.journey-hud');
if (!controls || !hud) throw new Error('Missing vehicle HUD');
const controlRect = controls.getBoundingClientRect();
const hudRect = hud.getBoundingClientRect();
return {
aligned: Math.abs(controlRect.bottom - hudRect.bottom) <= 1,
separate: controlRect.right <= hudRect.left,
controlsTargetSize: [...controls.querySelectorAll<HTMLElement>('button')]
.every((button) => button.getBoundingClientRect().height >= 44),
centerClear: controlRect.right < window.innerWidth * 0.42 && hudRect.left > window.innerWidth * 0.58,
};
});
expect(geometry.aligned).toBe(true);
expect(geometry.separate).toBe(true);
expect(geometry.controlsTargetSize).toBe(true);
if (viewport.width >= 768) expect(geometry.centerClear).toBe(true);
}
});
test('moves drive controls into document flow in short landscape', async ({ page }) => {
await page.setViewportSize({ width: 800, height: 390 });
await loadInformationLayer(page);
const geometry = await page.evaluate(() => {
const controls = document.querySelector<HTMLElement>('.drive-controls');
const contact = document.querySelector<HTMLElement>('#contact');
if (!controls || !contact) throw new Error('Missing short-landscape controls');
const controlsRect = controls.getBoundingClientRect();
const contactRect = contact.getBoundingClientRect();
return {
position: getComputedStyle(controls).position,
afterContact: controlsRect.top >= contactRect.bottom,
};
});
expect(geometry).toEqual({ position: 'relative', afterContact: true });
});
test('keeps actual standalone project and contact destinations at least 44 by 44px on mobile', async ({ page }) => {
await page.setViewportSize({ width: 320, height: 800 });
await loadInformationLayer(page);