diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index 2bab4f7..6642265 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -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); // And nothing sticks out past the right edge of the page. - const overflow = await page.evaluate( - () => document.documentElement.scrollWidth - document.documentElement.clientWidth - ); - expect(overflow, 'siden kan scrolles vandret').toBeLessThanOrEqual(1); + const sideways = () => + page.evaluate( + () => document.documentElement.scrollWidth - document.documentElement.clientWidth + ); + 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([]); }); diff --git a/web/src/lib/components/Sidebar.svelte b/web/src/lib/components/Sidebar.svelte index 0b0e54f..7f772f4 100644 --- a/web/src/lib/components/Sidebar.svelte +++ b/web/src/lib/components/Sidebar.svelte @@ -18,7 +18,13 @@ newName = ''; adding = false; 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() { diff --git a/web/src/lib/components/TaskDetail.svelte b/web/src/lib/components/TaskDetail.svelte index aff1d3f..fefa084 100644 --- a/web/src/lib/components/TaskDetail.svelte +++ b/web/src/lib/components/TaskDetail.svelte @@ -575,7 +575,12 @@ .drawer { position: fixed; 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; display: flex; flex-direction: column; @@ -625,7 +630,12 @@ .scroll { flex: 1; + min-width: 0; 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; padding: var(--s4) var(--s4) var(--s8); display: flex; @@ -883,8 +893,12 @@ } @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 { - width: 100vw; + inset: 0; + width: auto; border-left: 0; } }