FN-5664: prevent mission view pull-to-refresh overscroll

Contain Mission Manager scroll overscroll so mobile pull/swipe gestures no longer refresh or snap the dashboard.

- Add overscroll containment to Mission Manager inline/body/sidebar/detail/event scroll containers.
- Preserve iOS momentum scrolling with -webkit-overflow-scrolling where needed.
- Add CSS regression tests asserting overscroll containment and momentum scrolling coverage.

Files changed:
 packages/dashboard/app/components/MissionManager.css    | 10 ++++++++
 packages/dashboard/app/components/__tests__/MissionManager.mobile-css.test.ts    | 27 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

Fusion-Task-Id: FN-5664

Fusion-Task-Lineage: 4c80b116-5c79-4b76-8764-6262ec81aca7
This commit is contained in:
gsxdsm
2026-05-29 07:36:38 -07:00
parent 46531c6b3b
commit 52b6e2bb52
2 changed files with 37 additions and 0 deletions

View File

@@ -45,6 +45,9 @@
height: 100%;
max-height: 100%;
overflow-y: auto;
/* Keep pull-down/overscroll inside the Mission view so iOS pull-to-refresh and Android overscroll cannot reload the dashboard or snap the page to the top. */
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
border-radius: 0;
box-shadow: none;
border: none;
@@ -137,6 +140,7 @@
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
padding: var(--space-lg);
-webkit-overflow-scrolling: touch;
}
@@ -243,6 +247,8 @@
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
padding: var(--space-sm);
}
@@ -252,6 +258,8 @@
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
display: flex;
flex-direction: column;
padding: var(--space-lg);
@@ -1213,6 +1221,8 @@
gap: var(--space-sm);
max-height: min(52vh, 420px);
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
padding-right: 2px;
}

View File

@@ -201,3 +201,30 @@ describe("mobile split reversal CSS", () => {
expect(desktopBlock).toContain("display: none");
});
});
describe("Mission view overscroll containment", () => {
it("adds overscroll-behavior containment to every mission scroll container", () => {
const css = loadAllAppCss();
const inlineRule = css.match(/\.mission-manager--inline\s*\{[^}]*\}/)?.[0] ?? "";
const bodyRule = css.match(/\.mission-manager__body\s*\{[^}]*\}/)?.[0] ?? "";
const sidebarRule = css.match(/\.mission-manager__sidebar-list\s*\{[^}]*\}/)?.[0] ?? "";
const detailRule = css.match(/\.mission-manager__detail-pane\s*\{[^}]*\}/)?.[0] ?? "";
const eventsRule = css.match(/\.mission-events\s*\{[^}]*\}/)?.[0] ?? "";
expect(inlineRule).toContain("overscroll-behavior: contain;");
expect(bodyRule).toContain("overscroll-behavior: contain;");
expect(sidebarRule).toContain("overscroll-behavior: contain;");
expect(detailRule).toContain("overscroll-behavior: contain;");
expect(eventsRule).toContain("overscroll-behavior: contain;");
});
it("keeps webkit momentum scrolling on body and events containers", () => {
const css = loadAllAppCss();
const bodyRule = css.match(/\.mission-manager__body\s*\{[^}]*\}/)?.[0] ?? "";
const eventsRule = css.match(/\.mission-events\s*\{[^}]*\}/)?.[0] ?? "";
expect(bodyRule).toContain("-webkit-overflow-scrolling: touch;");
expect(eventsRule).toContain("-webkit-overflow-scrolling: touch;");
});
});