fix(mobile): the drawer no longer pushes the page sideways
Release / Build and publish image (push) Failing after 10m8s

The task drawer was `width: 100vw`. A viewport unit includes the scrollbar
gutter and a percentage does not, so the drawer came out a few pixels wider
than the page it was pinned to and the whole document could be shoved
sideways. It is `100%` now, and at phone width it is stated as four insets
instead — a box defined by the viewport's own edges cannot be a rounding
error wider than it.

The scrolling body gets `min-width: 0` and `overflow-x: hidden` too, so a
pasted URL or a long unbroken word in a comment cannot stretch the flex
column and take the page with it.

Writing the test for that found another one: creating a project from the
sidebar navigated to it and left the drawer covering the screen. Every link
in there closes it on the way out; the form did not, because it calls
`goto` directly. Now it does the same thing for the same reason.

The phone test checks the document cannot be scrolled horizontally, both
with the drawer shut and with it open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-17 23:24:49 +02:00
co-authored by Claude Opus 5
parent 6d27d730d2
commit 494640c1a8
3 changed files with 37 additions and 7 deletions
+14 -4
View File
@@ -836,10 +836,20 @@ test('projektsiden er brugbar på en telefon', async ({ page }) => {
expect(box.height, 'overskriften er brudt op i én bogstavkolonne').toBeLessThan(120); expect(box.height, 'overskriften er brudt op i én bogstavkolonne').toBeLessThan(120);
// And nothing sticks out past the right edge of the page. // And nothing sticks out past the right edge of the page.
const overflow = await page.evaluate( const sideways = () =>
() => document.documentElement.scrollWidth - document.documentElement.clientWidth page.evaluate(
); () => document.documentElement.scrollWidth - document.documentElement.clientWidth
expect(overflow, 'siden kan scrolles vandret').toBeLessThanOrEqual(1); );
expect(await sideways(), 'siden kan scrolles vandret').toBeLessThanOrEqual(1);
// The task drawer, too. It was `width: 100vw`, which includes the scrollbar
// gutter where a percentage does not, so the drawer came out wider than the
// page and the whole document could be pushed sideways.
await page.getByLabel('Ny opgave').fill('mal væggen');
await page.getByLabel('Ny opgave').press('Enter');
await page.getByText('mal væggen', { exact: true }).click();
await expect(page.getByRole('complementary', { name: 'Opgave' })).toBeVisible();
expect(await sideways(), 'opgaveruden skubber siden sidelæns').toBeLessThanOrEqual(1);
expect(trouble).toEqual([]); expect(trouble).toEqual([]);
}); });
+7 -1
View File
@@ -18,7 +18,13 @@
newName = ''; newName = '';
adding = false; adding = false;
const project = await app.createProject(name); const project = await app.createProject(name);
if (project) goto(`/projekt/${project.id}`); if (!project) return;
// Closes the drawer as well as navigating. On a phone the sidebar is an
// overlay, and creating a project moved the page underneath it while leaving
// it covering the screen — every link in here closes it, and this makes the
// same move for the same reason.
onnavigate?.();
goto(`/projekt/${project.id}`);
} }
async function signOut() { async function signOut() {
+16 -2
View File
@@ -575,7 +575,12 @@
.drawer { .drawer {
position: fixed; position: fixed;
inset: 0 0 0 auto; inset: 0 0 0 auto;
width: min(480px, 100vw); /* `100%` rather than `100vw`. For a fixed element a percentage resolves
against the initial containing block, which excludes the scrollbar gutter
— `100vw` does not, so the drawer was a few pixels wider than the page and
the whole document could be pushed sideways. */
width: min(480px, 100%);
max-width: 100%;
z-index: 80; z-index: 80;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -625,7 +630,12 @@
.scroll { .scroll {
flex: 1; flex: 1;
min-width: 0;
overflow-y: auto; overflow-y: auto;
/* Nothing inside may widen the drawer. A pasted URL in a comment or a long
unbroken word would otherwise stretch the flex column and take the page
with it. */
overflow-x: hidden;
overscroll-behavior: contain; overscroll-behavior: contain;
padding: var(--s4) var(--s4) var(--s8); padding: var(--s4) var(--s4) var(--s8);
display: flex; display: flex;
@@ -883,8 +893,12 @@
} }
@media (max-width: 560px) { @media (max-width: 560px) {
/* Full width, stated as four insets rather than a width: the box is then
defined by the viewport's edges and cannot be a rounding error wider than
the thing it is pinned to. */
.drawer { .drawer {
width: 100vw; inset: 0;
width: auto;
border-left: 0; border-left: 0;
} }
} }