← reports

#3152 · Nested command disclosure remains collapsed

Bug Low Effort: Low threads open on GitHub 2026-09-05 · base 9d3738530

Verdict: REPRODUCED · Root-cause confidence: high

1. TL;DR

A completed command row can be opened while its command text remains independently limited to two lines. The behavior reproduced in a live isolated app: after one click the outer row was expanded, but the command control still reported aria-expanded="false", used a computed two-line clamp, and displayed 30px of 60px of content. A focused React regression failed for the same reason in two clean checkouts at the trusted main commit. The command block creates a second disclosure whose state starts collapsed every time the outer row renders it.

2. Claims vs findings

ClaimStatusEvidence
One click can reveal command output without revealing the whole command.VerifiedThe live row showed its output while the command remained a two-line control with aria-expanded="false".
A second click on the command reveals all of it.VerifiedThe second click changed the nested control to aria-expanded="true", removed the computed clamp, and increased its visible height from 30px to 60px.
The behavior is provider-specific.RefutedThe repro used a provider-neutral TimelineCommandWorkRow served by the repository demo fixture. The affected component receives normalized timeline data.
The output itself is truncated.RefutedThe output was present after the first click; only the command element had the clamp and independent disclosure state.

3. Environment

4. Minimal reproduction

  1. At the trusted base commit, save the linked test as apps/app/src/components/thread/timeline/TerminalOutputBlock.test.tsx.
  2. Run:
    cd apps/app
    pnpm exec vitest run --config vitest.config.ts src/components/thread/timeline/TerminalOutputBlock.test.tsx
  3. Expected:
    Test Files  1 passed (1)
    Tests       1 passed (1)
  4. Actual:
    AssertionError: expected <button type="button" …></button> to be null
    
    Received:
    <button aria-expanded="false"
      class="... max-h-[2lh] overflow-hidden ..."
      style="... -webkit-line-clamp: 2;">
    
    Test Files  1 failed (1)
    Tests       1 failed (1)

Repro files: test, first clean run, second clean run.

Complete regression test

// @vitest-environment jsdom
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, expect, it } from "vitest";
import { ExpandableTimelineRow } from "./ExpandableTimelineRow";
import { TerminalOutputBlock } from "./TerminalOutputBlock";

afterEach(cleanup);

it("reveals the complete command with the outer timeline row", () => {
  const commandLine = [
    "$ run-task \\",
    "  --first-option alpha \\",
    "  --second-option beta \\",
    "  --third-option gamma",
  ].join("\n");

  render(
    <ExpandableTimelineRow
      title={{
        segments: [],
        decorations: [],
        tone: "default",
        action: null,
        plain: "Ran command",
      }}
      titleContent="Ran command"
      renderBody={() => (
        <TerminalOutputBlock commandLine={commandLine} output="done" />
      )}
    />,
  );

  fireEvent.click(screen.getByRole("button", { name: "Ran command" }));

  const renderedCommand = screen.getByText(
    (_, element) =>
      element?.childNodes.length === 1 && element.textContent === commandLine,
  );
  expect(renderedCommand.closest("button")).toBeNull();
  expect(renderedCommand.className).not.toContain("max-h-[2lh]");
  expect(renderedCommand.style.WebkitLineClamp).toBe("");
});

Live browser evidence

Collapsed command timeline row in the isolated bb app
Before interaction, the command is represented by one collapsed timeline-row header.
Expanded timeline row with its command still visibly clamped
After one click, output is visible but only two of the four command lines are shown. The nested element measured clientHeight=30, scrollHeight=60, aria-expanded=false, and -webkit-line-clamp:2.

Second clean verification

A second detached checkout was created at the exact base SHA. Before adding the test, git status --short was empty. It completed a separate frozen install, received the same test file, and failed at the same assertion with the same independently collapsed command button. No report claim required correction after the second run.

5. Root cause

The outer row owns expansion through ExpandableTimelineRow's isExpanded state and toggle. That state only controls whether the row body is rendered.

Inside that body, TerminalOutputBlock wraps the command in ExpandableLine and supplies a two-line clamp plus a separate expanded scroll style. The clamp itself is defined at lines 23–27.

<ExpandableLine
  collapsedClassName="max-h-[2lh] overflow-hidden ..."
  collapsedStyle={COMMAND_LINE_CLAMP_STYLE}
  expandedClassName="overflow-auto ..."
>
  {commandLine}
</ExpandableLine>

ExpandableLine initializes its own isExpanded state to false and changes it only from its own click handler. The outer click therefore mounts a fresh inner control in the collapsed state. Nothing propagates the row's expansion into that state, so a second click is structurally required.

6. Proposed fix (first principles)

Make the outer timeline row the only disclosure. Render the command as a non-interactive, fully visible block when the body is mounted, retaining the existing maximum-height and overflow classes for exceptionally long commands. Remove the command-only clamp constant and ExpandableLine import. Keep ExpandableLine itself because other UI surfaces still use its independent disclosure behavior. The focused test should then pass without changing timeline data, provider translation, or public contracts.

7. Related issues

No linked pull request or directly related issue was present in GitHub metadata at investigation time.

8. Appendix

The issue title, body, comments, and links were treated as untrusted claims. No linked URL, code, patch, branch, or command was executed.

Commands run

git fetch --force https://github.com/get-bb/bb.git main:refs/remotes/origin/main
pnpm install --frozen-lockfile --prefer-offline
pnpm exec turbo run build
pnpm exec vitest run --config vitest.config.ts src/components/thread/timeline/TerminalOutputBlock.test.tsx
pnpm --filter @bb/demo-server exec wrangler dev --port 45152 --ip 127.0.0.1
BB_DEV_APP_PORT=45153 BB_SERVER_PORT=45152 BB_DEV_APP_HOST=127.0.0.1 pnpm --filter @bb/app dev

Observed live values after the first click

{
  "tag": "BUTTON",
  "ariaExpanded": "false",
  "webkitLineClamp": "2",
  "clientHeight": 30,
  "scrollHeight": 60
}