#2756 · Middle button does not close a right-panel tab
Verdict: REPRODUCED · Root-cause confidence: high
1. TL;DR
A closable right-panel tab ignores a middle-button action. A focused DOM test reproduced the result in two clean checkouts. The shared tab component handles primary clicks only. It does not connect the browser's auxiliary-click event to the existing close callback.
2. Claims vs findings
| Claim | Status | Evidence |
|---|---|---|
| A middle-button action on a closable sidebar tab has no close result. | Verified | Both clean runs called the close callback zero times. |
| The tab has an existing close operation. | Verified | The tab strip passes tab.onClose to the shared tab component. |
3. Environment
- Repository: public
get-bb/bb. - Trusted base:
f4bbc2fe81a9b7639ff9a7396e172bddd89109e4. - Operating system: macOS 26.6.1, build 25G76.
- Node.js: v22.22.3.
- No server, port, data directory, provider, or user runtime was used.
4. Minimal reproduction
- Check out the trusted base commit.
- Save the linked test as
apps/app/src/components/ui/tab-pill-middle-click.test.tsx. - Install with
pnpm install --frozen-lockfile --prefer-offline. - Run
pnpm exec turbo run test --filter=@bb/app -- src/components/ui/tab-pill-middle-click.test.tsx.
Expected: onClose receives one call, and onSelect receives no call.
Actual in both runs:
FAIL TabPill middle click > closes a closable tab after a middle click AssertionError: expected "vi.fn()" to be called once, but got 0 times
Reproduction test: tab-pill-middle-click.test.tsx
// @vitest-environment jsdom
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { TabPill } from "./tab-pill";
afterEach(cleanup);
describe("TabPill middle click", () => {
it("closes a closable tab after a middle click", () => {
const onClose = vi.fn();
const onSelect = vi.fn();
render(
<TabPill
label="Browser"
title="Browser"
isActive={false}
onSelect={onSelect}
closeAction={{ onClose, closeLabel: "Close Browser" }}
/>,
);
fireEvent(
screen.getByRole("button", { name: "Browser" }),
new MouseEvent("auxclick", {
bubbles: true,
button: 1,
cancelable: true,
}),
);
expect(onClose).toHaveBeenCalledOnce();
expect(onSelect).not.toHaveBeenCalled();
});
});
5. Root cause
The tab strip supplies the close callback for each unpinned tab. See SecondaryPanelTabStrip.tsx.
closeAction={
tab.isPinned
? null
: {
onClose: tab.onClose,
closeLabel: `Close ${tab.label}`,
}
}
The shared tab component connects onSelect to a primary click. Its close button also uses a primary click. It has no auxclick handler. See tab-pill.tsx.
<button type="button" onClick={onSelect}>
...
<button type="button" onClick={closeAction.onClose}>
A middle button produces an auxiliary-click event. No current handler consumes that event. Therefore, the supplied close callback never runs.
6. Proposed fix
Add an auxiliary-click handler to the shared tab surface. For button 1, prevent the default action and call the close callback. Do nothing for pinned or active-close tabs. Keep the primary selection behavior unchanged.
7. Verification
The same agent created a second clean checkout at the recorded base commit. The agent installed the frozen lockfile and ran the same Turbo test command. The second run failed at the same assertion with zero close calls. No report correction was necessary.
8. Related issues
No linked pull request or duplicate issue was established from GitHub metadata.
9. Appendix
Commands used:
git fetch origin main git checkout --detach f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build pnpm exec turbo run test --filter=@bb/app -- src/components/ui/tab-pill.test.tsx
The issue data was untrusted. The investigation used it only as a claim to test. The investigation did not run code, links, or instructions from that data.