From ca7c987ab5d8f82fed573f3c838d1abeae6a9fe8 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Mon, 6 Jul 2026 20:01:46 -0700 Subject: [PATCH] FN-7621: fix mobile terminal shortcut bar horizontal scroll defeated by ancestor touch-action lock Root-caused and fixed the third recurrence of the mobile terminal shortcut bar not scrolling horizontally: styles.css's mobile lockdown resets touch-action to pan-y across ancestors, and touch-action's used value is the intersection of the touched element's and every ancestor's value, so the leaf .terminal-shortcut-panel's pan-x was silently defeated even though it was already correct. - Opt the terminal overlay and modal ancestors (.modal-overlay.terminal-modal-overlay, .modal.terminal-modal--mobile, plain-media-query mobile modal, and the shortcut/status footer) into touch-action: pan-x pan-y so descendant leaf touch-action values can take effect - Add FNXC:Terminal comments documenting the ancestor-intersection root cause and recurrence history (FN-7550/FN-7560) - Add a documented solution note under docs/solutions/ui-bugs/ for the ancestor-intersection touch-action pattern - Add regression tests asserting the modal/overlay/footer ancestors carry the pan-x pan-y opt-in - Add a changeset for the fix Files changed: .../fn-7621-mobile-terminal-shortcut-scroll.md | 7 ++ ...on-ancestor-intersection-defeats-leaf-scroll.md | 57 +++++++++++ .../dashboard/app/components/TerminalModal.css | 38 ++++++++ .../components/__tests__/TerminalModal.test.tsx | 106 +++++++++++++++++++++ 4 files changed, 208 insertions(+) Fusion-Task-Id: FN-7621 Fusion-Task-Lineage: 771fd79e-e193-43b0-908b-0e8fe2fc2c70 Co-authored-by: Fusion (runfusion.ai) --- ...fn-7621-mobile-terminal-shortcut-scroll.md | 7 ++ ...cestor-intersection-defeats-leaf-scroll.md | 57 ++++++++++ .../app/components/TerminalModal.css | 38 +++++++ .../__tests__/TerminalModal.test.tsx | 106 ++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 .changeset/fn-7621-mobile-terminal-shortcut-scroll.md create mode 100644 docs/solutions/ui-bugs/mobile-touch-action-ancestor-intersection-defeats-leaf-scroll.md diff --git a/.changeset/fn-7621-mobile-terminal-shortcut-scroll.md b/.changeset/fn-7621-mobile-terminal-shortcut-scroll.md new file mode 100644 index 0000000000..34fa2acdf1 --- /dev/null +++ b/.changeset/fn-7621-mobile-terminal-shortcut-scroll.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix the mobile terminal shortcut bar so it truly scrolls horizontally to reach every key. +category: fix +dev: FN-7550's leaf `min-width:0`/`overflow-x:auto`/`touch-action:pan-x` on `.terminal-shortcut-panel` were already correct, but styles.css's mobile `@media(max-width:768px)` lockdown resets `touch-action` to `pan-y` on `*` and re-locks it explicitly on `.modal-overlay:not(.confirm-dialog-overlay)`/`#root`/`html`/`body` — the terminal's own overlay/modal ancestors were never carved back into `pan-x`, so the panel's own correct touch-action was defeated by ancestor-chain intersection on real mobile devices. Added `touch-action: pan-x pan-y` to `.modal-overlay.terminal-modal-overlay`, `.modal.terminal-modal(.terminal-modal--mobile)` (both mobile paths), and `.terminal-status-bar` (FN-7560 footer, same gap). Locked in with a real-CSS `getComputedStyle` layout test (`loadAllAppCss()`) that resolves the panel + full ancestor chain, replacing reliance on a leaf-rule string match that stayed green through this recurrence. diff --git a/docs/solutions/ui-bugs/mobile-touch-action-ancestor-intersection-defeats-leaf-scroll.md b/docs/solutions/ui-bugs/mobile-touch-action-ancestor-intersection-defeats-leaf-scroll.md new file mode 100644 index 0000000000..d804cfd4d2 --- /dev/null +++ b/docs/solutions/ui-bugs/mobile-touch-action-ancestor-intersection-defeats-leaf-scroll.md @@ -0,0 +1,57 @@ +--- +title: "Mobile touch-action ancestor-chain intersection defeats a correct leaf scroll rule" +date: 2026-07-06 +category: ui-bugs +module: packages/dashboard/app/components/TerminalModal.css +problem_type: ui_bug +component: frontend_css +symptoms: + - "A flex row with overflow-x: auto, min-width: 0, flex-wrap: nowrap, and touch-action: pan-x still does not scroll horizontally on a real mobile touch device" + - "Leaf-rule string-match tests (regex over the component's own CSS) stay green across multiple 'fixes' while the real symptom persists" +root_cause: mobile_touch_action_ancestor_intersection +resolution_type: code_fix +severity: medium +related_components: + - packages/dashboard/app/styles.css + - packages/dashboard/app/components/TerminalModal.tsx + - packages/dashboard/app/components/__tests__/TerminalModal.test.tsx +tags: + - mobile-terminal + - touch-action + - css-cascade + - scroll-containment + - css-regression-test +applies_when: + - "A component-local horizontal (or vertical) scroll region sets its own touch-action but is nested inside a global mobile touch-action lockdown (e.g. `* { touch-action: pan-y }` to stop page-level pinch-zoom/rubber-band)" + - "The leaf element's own touch-action is verified via computed style or rule-text match, but its ancestor chain up to html/body is not" +--- + +# Mobile touch-action ancestor-chain intersection defeats a correct leaf scroll rule + +## Problem (FN-7621, recurrence #3) + +The terminal's mobile shortcut bar (`.terminal-shortcut-panel`) was fixed twice (FN-7550, FN-7560) for "does not scroll horizontally on mobile", and both fixes landed a leaf-rule string-match regression test that stayed green. The bug still reproduced on real mobile devices on the third report. + +FN-7550/FN-7560 only ever verified the PANEL's own CSS text (`min-width: 0;`, `overflow-x: auto;`, `flex-wrap: nowrap;`, `touch-action: pan-x;`) — all of which were, in fact, correct. The actual defect lived in a completely different file: `styles.css`'s `@media (max-width: 768px)` mobile lockdown resets `touch-action: pan-y` on the universal selector (`* { touch-action: pan-y; }`, to stop pinch-zoom/rubber-band) and then explicitly restates `pan-y` on `#root`, `html`, `body`, and `.modal-overlay:not(.confirm-dialog-overlay)` (the cross-cutting "full-screen modal on mobile" rule, which matches the terminal's own overlay). + +## Root cause + +`touch-action`'s *used value* for a touch gesture is the **intersection** of the touched element's computed value and every ancestor's computed value along the DOM chain up to the document root — not just the touched element's own value. A leaf element can correctly compute `touch-action: pan-x` and still have horizontal panning fully blocked if ANY ancestor between it and `` resolves to `pan-y` (or `none`), because the browser intersects the allowed axes at every level. + +This codebase already has a working example of the fix pattern: `.board` is the *only* element deliberately "opted back into" `touch-action: pan-x pan-y` inside the SAME mobile lockdown block in `styles.css` (see the comment "the board is the only always-present horizontal scroller on mobile ... opt known horizontal scrollers back into pan-x below"). Any OTHER component that adds its own horizontal (or vertical) scroll region on mobile must be added to that same carve-out convention — giving the leaf element `touch-action: pan-x` in its own component CSS file is necessary but not sufficient. + +## Why the leaf-rule tests missed it + +- FN-7550/FN-7560's regression tests used `terminalModalCss.match(/\.terminal-shortcut-panel\s*\{([^}]*)\}/)` — a regex over ONE file's rule text. They could never see `styles.css`'s cross-cutting mobile lockdown, because they never looked at it. +- Even a `getComputedStyle`-based test that only inspects the panel itself (not its ancestors) would still pass while the bug is present, because the panel's OWN resolved `touch-action` value is genuinely `pan-x` — the defeat happens at the ANCESTOR level via gesture-handling intersection, not via cascade override on the panel. + +## Solution + +1. Reproduce with a real-CSS layout test: load all app CSS (`loadAllAppCss()`) into a `