From 373087664fa08bfd51df47ed303737e4da7baf30 Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Fri, 4 Sep 2026 16:25:49 +0000 Subject: [PATCH] fix(components): keep mobile session scrollbar above rows Model: gpt-5.6 --- .../components/mobile/mobile-home-screen.tsx | 7 +- .../mobile-session-list-scroll-layer.test.tsx | 71 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 packages/components/tests/mobile-session-list-scroll-layer.test.tsx diff --git a/packages/components/src/components/mobile/mobile-home-screen.tsx b/packages/components/src/components/mobile/mobile-home-screen.tsx index 9597bf767..f1656bd53 100644 --- a/packages/components/src/components/mobile/mobile-home-screen.tsx +++ b/packages/components/src/components/mobile/mobile-home-screen.tsx @@ -1617,8 +1617,13 @@ export function MobileHomeScreen({
diff --git a/packages/components/tests/mobile-session-list-scroll-layer.test.tsx b/packages/components/tests/mobile-session-list-scroll-layer.test.tsx new file mode 100644 index 000000000..43978073c --- /dev/null +++ b/packages/components/tests/mobile-session-list-scroll-layer.test.tsx @@ -0,0 +1,71 @@ +// @vitest-environment jsdom + +import React, { type ReactNode } from 'react'; +import { flushSync } from 'react-dom'; +import { createRoot, type Root } from 'react-dom/client'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { MobileHomeScreen } from '../src/components/mobile/mobile-home-screen'; +import { initI18n } from '../src/i18n'; + +describe('mobile session list scrollbar layer', () => { + let root: Root | undefined; + let container: HTMLDivElement | undefined; + + beforeEach(async () => { + await initI18n('en'); + Object.defineProperty(window, 'matchMedia', { + configurable: true, + value: vi.fn().mockImplementation((query: string) => ({ + matches: false, + media: query, + onchange: null, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + addListener: vi.fn(), + removeListener: vi.fn(), + dispatchEvent: vi.fn(), + })), + }); + }); + + afterEach(() => { + if (root) { + flushSync(() => root?.unmount()); + } + root = undefined; + container?.remove(); + container = undefined; + vi.restoreAllMocks(); + }); + + function render(node: ReactNode) { + container = document.createElement('div'); + document.body.appendChild(container); + root = createRoot(container); + flushSync(() => root?.render(node)); + } + + function expectScrollbarStackingBoundary() { + const scrollRegion = container?.querySelector('[data-mobile-session-list-scroll-region]'); + expect(scrollRegion).not.toBeNull(); + expect(scrollRegion?.classList).toContain('relative'); + expect(scrollRegion?.classList).toContain('z-0'); + expect(scrollRegion?.classList).toContain('overflow-y-auto'); + } + + it('keeps the workspace conversation rows inside the scroll container stacking context', () => { + render( + + ); + + expectScrollbarStackingBoundary(); + }); +});