Skip to content

[Bug]: Horizontal trackpad scrolling in the diff panel triggers back/forward navigation #28160

Open

Description

@pantharshit007

Before submitting

  • I searched existing issues and did not find a duplicate of this specific diff-panel bug report.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop — diff panel and back/forward gesture navigation

What happened

When a diff contains a very long line, the diff panel shows a horizontal scrollbar. Using a trackpad to scroll left or right sometimes triggers the application's back/forward navigation instead of scrolling the diff. This unexpectedly navigates away from the current view and interrupts reviewing the changes.

Steps to reproduce

  1. Open a diff containing a line wide enough to require horizontal scrolling.
  2. Place the pointer over the diff panel and interact with it.
  3. Use a trackpad to scroll horizontally left and right.
  4. Repeat the gesture; intermittently, the application navigates backward or forward instead of keeping the interaction within the diff.

Expected behavior

Horizontal scrolling while interacting with the diff panel should scroll its contents without triggering application back/forward navigation. The same protection should apply to other scrollable panels: a content-scrolling gesture should not unexpectedly navigate away, including when the content reaches a scroll boundary.

Actual behavior

The horizontal trackpad gesture sometimes triggers application back/forward navigation while the user is trying to scroll the diff.

Impact

Minor bug or occasional failure — interrupts diff review by unexpectedly changing the current view.

Version or commit

T3 Code (Nightly) 0.1.6-nightly.20261031.3977 (installed desktop app).

Environment

  • App: T3 Code (Nightly), desktop app
  • OS: macOS 26.7.1 (build 25G241)
  • Architecture: Apple Silicon (arm64)
  • Input: Trackpad, horizontal scrolling in the diff panel

Screenshots, recordings, or supporting files

https://r2.aetherui.in/T3%20code%20issue%20recreation%20.mp4

Related issue

#28023 requested a setting to disable swipe back/forward navigation and is closed. This report concerns preventing content-scrolling gestures from triggering navigation while interacting with the diff or another scrollable panel.

Workaround

No workaround provided.

Activity

  1. eddienubes commented on Nov 4, 2026

    @eddienubes

    Oh yeah, this is so annoying.
    Trying to horizontally scroll through a diff (w/o soft-wrap) ends up navigating between threads instead.

  2. hollandjake commented on Nov 5, 2026

    @hollandjake

    very annoying, also affects horizontal scrolling mice. at least it should be a toggle in settings so I have to physically click the forward and back buttons in the UI

  3. jpambrun commented on Nov 6, 2026

    @jpambrun

    Yeah, for me on an MX master 4 anywhere in the application if I just lightly brush the horizontal scroll wheel by accident it triggers a back operation which is super annoying. This happens several times per day.

  4. CadenEl commented on Nov 7, 2026

    @CadenEl
    Contributor

    The browser panel's tab strip has the same problem on macOS with a trackpad. Once it has enough tabs to scroll, a swipe toward an edge it's already at changes threads: at the left edge it goes back, at the right edge it goes forward. A swipe that starts mid-strip just scrolls the tabs.

    Recording from a desktop dev build of main at bda0e7f4 with demo data. The tab strip in the demo-shop thread is at its left edge, and a swipe toward the start goes back to the previous thread. The swipe is scripted DOM wheel events, not a physical trackpad, since macOS Electron gives each CDP wheel event its own gesture. The red dot marks the pointer.

    Swipe toward the start of the browser tab strip at its left edge navigates back to the previous thread

    MP4

    I reproduced the navigation on main at bda0e7f4 with HistorySwipeNavigation rendered next to the real ScrollArea, using the tab strip's props and an overflowing max-content row:

    Synthetic swipe main bda0e7f4 With #28475's two changed files at 21015dd7
    Back at the left edge navigates back stays
    Forward at the right edge navigates forward stays
    Back from mid-strip stays stays

    With those PR files applied, the three repro cases plus the existing browser and momentum tests pass 42/42.

    This is a reduced test, not a mounted RightPanelTabs: it leaves out the strip's own wheel handler and the desktop titlebar context. The results suggest #28475 fixes the same bug, so I'm adding this case here instead of opening a separate issue or PR. I haven't tested a physical trackpad against a #28475 desktop build.

    Repro test
    import { describe, expect, it, vi } from "vite-plus/test";
    
    import { render } from "../../test/render";
    import { HistorySwipeNavigation } from "./HistorySwipeNavigation";
    import { ScrollArea } from "./ui/scroll-area";
    
    const navigateHistory = vi.hoisted(() => vi.fn());
    vi.mock("../navigationHistory", () => ({ canNavigateHistory: () => true, navigateHistory }));
    
    // Models RightPanelTabs' overflowing ScrollArea; omits its wheel handler.
    function TabStrip() {
      return (
        <div style={{ width: 300 }}>
          <ScrollArea radius="none" hideScrollbars scrollFade data-right-panel-tab-list>
            <div style={{ display: "flex", width: "max-content", gap: 4 }}>
              {Array.from({ length: 8 }, (_, index) => (
                <button key={index} type="button" style={{ width: 140, flex: "none" }}>
                  Tab {index}
                </button>
              ))}
            </div>
          </ScrollArea>
        </div>
      );
    }
    
    function swipe(target: Element, deltaX: number) {
      for (const delta of [deltaX, 0]) {
        target.dispatchEvent(new WheelEvent("wheel", { deltaX: delta, bubbles: true, composed: true }));
      }
    }
    
    describe("browser tab strip swipe repro", () => {
      it.each([
        ["swiping back at the tab strip's left edge", 0, -130],
        ["swiping forward at the tab strip's right edge", Number.MAX_SAFE_INTEGER, 130],
        ["swiping back mid-strip", 200, -130],
      ] as const)("%s keeps the thread", async (_name, scrollLeft, deltaX) => {
        navigateHistory.mockReset();
        await using screen = await render(
          <>
            <HistorySwipeNavigation />
            <TabStrip />
          </>,
        );
        const viewport = screen.container.querySelector<HTMLElement>(
          '[data-slot="scroll-area-viewport"]',
        )!;
        expect(viewport.scrollWidth).toBeGreaterThan(viewport.clientWidth);
        viewport.scrollLeft = scrollLeft;
        swipe(viewport.querySelector("button")!, deltaX);
        expect(navigateHistory).not.toHaveBeenCalled();
      });
    });

    vp test run apps/web/src/components/TabStripSwipeRepro.browser.test.tsx

  5. wiebekaai commented on Nov 8, 2026

    @wiebekaai

    Also affects T3 Code Desktop 0.1.7 on macOS arm64, connected to its local 0.1.7 server. Horizontal scrolling through tabs or a file triggers Back when overscrolling. Expected: scrolling stops at the boundary without navigating away.

    Inspection of the v0.1.7 source confirms that its horizontal-scroll guard permits history navigation at scroll boundaries. This matches the behavior addressed by PR #28475. No independent physical-input reproduction was performed.

    Investigated by GPT-6.1 Sol through Codex in T3 Code.

  6. Tanyawat-Arsaga commented on Nov 9, 2026

    @Tanyawat-Arsaga

    Also experiencing this with two-finger scrolling over the side-panel tabs: trying to scroll the tabs triggers Back for the whole app and navigates away from the current view. A regression test covering the actual side-panel tabs at both scroll boundaries would be helpful alongside #28475.

  7. alex-delia commented on Nov 10, 2026

    @alex-delia

    Would love an option to just entirely disable the two-finger scrolling going forward/back for the app altogether

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions