From 1fe96607a63e92788836f24c74a0a83e571a6dcd Mon Sep 17 00:00:00 2001 From: Karl Fogel Date: Tue, 29 Sep 2026 15:40:53 -0500 Subject: [PATCH 1/2] Use 'none' transform to get correct reference box Before this change, the "scale(1)" transform in the 'prefers-reduced-motion' case caused the Settings popup to become the reference box for dropdown menus inside it, because any non-'none' transform at all causes the associated element to become the reference box for all "position: fixed" descendants. And since those dropdowns used fixed position, positioning themselves relative to the wrong reference box effectively pushed them off the screen -- clipped by the panel and thus, as far as the user can tell, never opening at all. This change makes the window be the reference box again, while still giving users who prefer reduced motion what they want, since the "transition: none" is unchanged. This fixes https://github.com/ether/etherpad/issues/8290 ("Dropdown lists under Settings popup don't expand due to CSS mis-interaction.") --- src/static/skins/colibris/src/components/popup.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/skins/colibris/src/components/popup.css b/src/static/skins/colibris/src/components/popup.css index cc6794a6690..dacb338d794 100644 --- a/src/static/skins/colibris/src/components/popup.css +++ b/src/static/skins/colibris/src/components/popup.css @@ -72,7 +72,7 @@ @media (prefers-reduced-motion) { .popup>.popup-content { - transform: scale(1); + transform: none; transition: none; } .nice-select .list { From 214515851a2b22f98c269a7d2040928df6eb45e1 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 10 Oct 2026 16:55:01 +0100 Subject: [PATCH 2/2] test(settings): dropdowns open under prefers-reduced-motion (#8290) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WnNeNQpAJ5TWNZka4yugCw --- .../frontend-new/specs/pad_settings.spec.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/tests/frontend-new/specs/pad_settings.spec.ts b/src/tests/frontend-new/specs/pad_settings.spec.ts index 070491cef50..a04c7edcbcd 100644 --- a/src/tests/frontend-new/specs/pad_settings.spec.ts +++ b/src/tests/frontend-new/specs/pad_settings.spec.ts @@ -223,6 +223,31 @@ test.describe('creator-owned pad settings', () => { await expect(fontDropdown).not.toHaveClass(/open/); }); + // #8290: under prefers-reduced-motion the popup kept `transform: scale(1)`. + // Any transform makes .popup-content the containing block for the + // position:fixed list above, so the list was laid out relative to the popup + // instead of the viewport and never appeared. The test above runs without + // reduced motion, so it never saw this. + for (const id of ['padsettings-viewfontmenu', 'padsettings-languagemenu']) { + test(`#${id} dropdown opens under prefers-reduced-motion`, async ({page}) => { + await page.emulateMedia({reducedMotion: 'reduce'}); + await page.setViewportSize({width: 900, height: 500}); + await goToNewPad(page); + await showSettings(page); + await page.locator('#settings > .popup-content').evaluate((el) => { + el.scrollTop = el.scrollHeight; + }); + const dropdown = page.locator(`#${id} + .nice-select`); + await expect(dropdown).toBeInViewport(); + await dropdown.click(); + const list = dropdown.locator('.list'); + await expect(list).toBeVisible(); + await expect(list).toBeInViewport(); + await dropdown.locator('.option').first().click(); + await expect(dropdown).not.toHaveClass(/open/); + }); + } + // #7592: ticking "Disable chat" must visibly disable the dependent // "Chat always on screen" / "Show Chat and Users" toggles, not just // make the underlying inputs non-interactive.