Skip to content

feat(tui): reorder session sidebar sections by dragging their headers - #53217

Closed
Nowaker wants to merge 2 commits into
anomalyco:devfrom
Nowaker:tui-sidebar-drag
Closed

Nowaker wants to merge 2 commits into
anomalyco:devfrom
Nowaker:tui-sidebar-drag

Conversation

@Nowaker

@Nowaker Nowaker commented Oct 4, 2026 •

Copy link
Copy Markdown

Note: I'm aware v1 is now the maintenance branch and new features go to v2 only. This PR is here for others who want to use it on v1. I will submit a v2 version once I've migrated my plugin setup to v2.

Issue for this PR

Refs #53198. Builds on #53201: this branch contains that PR's commit too. Review only the last commit, 937fde8 "reorder session sidebar sections by dragging their headers". Kept separate because drag-and-drop is the more opinionated part.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Drag a session sidebar section by its header onto another section to move it there. The order is saved in kv (sidebar_order, like other runtime TUI toggles), applies immediately through the slot registry's updateOrder, and takes precedence over sidebar.order until Reset sidebar order (command palette) clears it. Works for plugin sections as well.

  • Each sidebar_content contribution is wrapped in a host box that handles the drag. It is hidden while the section renders nothing, so empty sections (Todo, Modified Files) still take no space.
  • Only a press on a section's first line, its header, starts a drag. A drag that starts anywhere below the header never moves the section.
  • opentui captures whatever is under the pointer at the first drag event, often the gap between sections, so the dragged section is the one pressed on mouse down, and a drag is recognized from over events that carry a drag source.
  • Collapsible headers (MCP, LSP, Todo, Modified Files) toggle only when pressed and released on the same cell, so a click still collapses and expands, while a drag, or dropping another section onto a header, does not.

What is the drag handle, and what stays copyable. In opentui a press on selectable text starts a text selection and never a capture drag, so a cell can be a drag handle or copyable text, not both. The handle is the header's section name and arrow (▼ MCP, Context), made selectable={false}, plus the header's blank cells. Everything else is selectable text exactly as on dev: section rows, and data after a name on the header line. That data includes the collapsed MCP summary, which this PR moves into its own text so (N active, M errors) can be copied. On dev that summary cannot actually be copied, because the press that starts the selection also expands the section and removes the summary. Toggling on release fixes that too. The only text that stops being selectable is the section names themselves, which carry no information worth copying.

How did you verify your code works?

  • Tests in packages/tui/test/plugin/slots.test.tsx drive the real slot host with mockMouse: a drag from a header reorders; a drag from a non-text cell below the header does not; a drag over the data after a header name selects it (•3) and does not reorder; on the real MCP section, a click collapses it, a drag selects (0 active from the summary, and a click on the summary expands it again. The second and the last test fail without this commit's handle rule and summary split. Plus tests for the move function and the click handler. bun typecheck in packages/tui and packages/opencode.
  • Drove the TUI in tmux with SGR mouse sequences and an isolated config (3 failing MCP servers so MCP is collapsible), reading what copy-on-select puts on the clipboard from tmux's OSC 52 buffer:
    • click on the MCP header collapses and expands it, also when clicking the summary text;
    • drag-select over the collapsed summary copies (0 active and shows "Copied to clipboard"; the Context lines and MCP rows copy too;
    • drag the MCP heading word onto Context → MCP, Context, LSP; MCP stays expanded; kv sidebar_order = ["mcp","context","lsp","todo","files"];
    • a drag that starts in the gap after an MCP row's bullet does not reorder;
    • order survives a restart; dragging Context down onto LSP → MCP, LSP, Context;
    • Reset sidebar order → default order live, kv key removed.

Screenshots / recordings

Sidebar after dragging the MCP header onto Context (captured from tmux):

Fake title
▼ MCP
• demo-a MCP error -32000: Connection closed
• demo-b MCP error -32000: Connection closed
• demo-c MCP error -32000: Connection closed
Context
234,124 tokens
40% used
$0.00 spent
LSP
LSPs are disabled

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

This PR is AI generated, but under direct supervision and on request of @Nowaker.

Add `sidebar.order` and `sidebar.hidden` to tui.json. Sections are named
`context`, `mcp`, `lsp`, `todo`, `files`, or by the slot id a plugin's
registration received, so plugin-contributed sidebar sections can be
ordered and hidden the same way as built-in ones.

Listed sections render first, in the given order; every unlisted section
keeps its default order after them, so a section added later is never
silently dropped. The session title is a separate slot and always stays
first. Without the option nothing changes.

Slot order belongs to a whole registration, so the host moves a
registration's `sidebar_content` into its own registration and leaves
its other slots (e.g. `sidebar_footer`) where they were.
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 4, 2026
Feature and session records for `sidebar.order` / `sidebar.hidden` and
drag-and-drop reordering (bc5aa4e, dc68262), upstream issue anomalyco#53198
and PRs anomalyco#53201 / anomalyco#53217, and the 1.18.34-vt-80-907b3bc518 build on
desktop and m4max. The compact Context feature gets a timeline row for
its header now toggling through the shared drag-aware click handler.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: high
AI-Platform: linux
AI-Harness: Vibeterm 3ae7f02
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
Dragging a sidebar section by its header onto another section moves it
there. The resulting order is saved in kv (`sidebar_order`) and wins
over `sidebar.order` from tui.json until "Reset sidebar order" in the
command palette clears it. Reordering applies live through the slot
registry's `updateOrder`, for built-in and plugin sections alike.

Every `sidebar_content` contribution is now wrapped in a host box that
handles the drag. The box is hidden while the section renders nothing,
so empty sections still take no space. Only a press on the section's
first line, its header, starts a drag; a drag that starts anywhere below
it never moves the section. opentui captures the renderable under the
pointer at the first drag event, which may be a gap between sections,
so the dragged section is the one pressed on mouse down and a drag is
recognized from `over` events that carry a drag source.

A press on selectable text starts a text selection instead, so the drag
handle is the header's section name and arrow, which are non-selectable,
plus its blank cells. Everything else stays selectable text as before,
including the collapsed MCP summary, which moves into its own text so
"(N active, M errors)" can be copied. Collapsible headers toggle only
when pressed and released on the same cell, so a click still collapses
while a drag, or a drop onto a header, does not; this also keeps the
collapsed summary on screen while it is being selected.
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 5, 2026
dc68262 made each sidebar section header the drag handle by marking
the whole header text unselectable. That took copy-on-select away from
the values merged onto those headers since: the compact Context line
(tokens, percent, cost), the MCP status summary and counts, the Todo
summary, and "are disabled" after the LSP heading. It also let a press
on any blank cell of a section, such as the gap after an MCP row's
bullet, start a section drag.

Only the section name and its arrow stay unselectable now; the values
after them on the header line are their own selectable text. A drag
reorders only when it starts on the section's first line, its header.
Clicking anywhere on the header, values included, still toggles it,
because toggling needs a press and release on the same cell, which a
drag-select never is. This is the same handle rule as the amended
upstream PR anomalyco#53217 head 937fde8.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: max
AI-Platform: linux
AI-Harness: Vibeterm bd50370
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 5, 2026
…g handle

Session record for the 2026-10-05 fix 1c06f29: the values merged onto
sidebar header lines (compact Context, MCP counts and summary, Todo
summary, "are disabled") copy on drag-select again, only section names
and arrows stay the drag handle, and a drag starts only on a section's
first line. PR anomalyco#53217 head amended to 937fde8; desktop runs
1.18.34-vt-101-907b3bc518 and m4max 1.18.34-vt-100-907b3bc518. The
section-order feature gains the change row, and the compact Context, MCP
summary, Todo summary and LSP one-line features gain timeline rows.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: max
AI-Platform: linux
AI-Harness: Vibeterm 50691e9
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
@thdxr

thdxr commented Oct 10, 2026

Copy link
Copy Markdown
Member

This branch has been upgraded to V2. We're no longer taking PRs for V1. If you think this is still relevant, please port it over and open it for V2.

— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

@thdxr thdxr closed this Oct 10, 2026
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 11, 2026
Feature and session records for `sidebar.order` / `sidebar.hidden` and
drag-and-drop reordering (bc5aa4e, dc68262), upstream issue anomalyco#53198
and PRs anomalyco#53201 / anomalyco#53217, and the 1.18.34-vt-80-907b3bc518 build on
desktop and m4max. The compact Context feature gets a timeline row for
its header now toggling through the shared drag-aware click handler.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: high
AI-Platform: linux
AI-Harness: Vibeterm 3ae7f02
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 11, 2026
dc68262 made each sidebar section header the drag handle by marking
the whole header text unselectable. That took copy-on-select away from
the values merged onto those headers since: the compact Context line
(tokens, percent, cost), the MCP status summary and counts, the Todo
summary, and "are disabled" after the LSP heading. It also let a press
on any blank cell of a section, such as the gap after an MCP row's
bullet, start a section drag.

Only the section name and its arrow stay unselectable now; the values
after them on the header line are their own selectable text. A drag
reorders only when it starts on the section's first line, its header.
Clicking anywhere on the header, values included, still toggles it,
because toggling needs a press and release on the same cell, which a
drag-select never is. This is the same handle rule as the amended
upstream PR anomalyco#53217 head 937fde8.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: max
AI-Platform: linux
AI-Harness: Vibeterm bd50370
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 11, 2026
…g handle

Session record for the 2026-10-05 fix 1c06f29: the values merged onto
sidebar header lines (compact Context, MCP counts and summary, Todo
summary, "are disabled") copy on drag-select again, only section names
and arrows stay the drag handle, and a drag starts only on a section's
first line. PR anomalyco#53217 head amended to 937fde8; desktop runs
1.18.34-vt-101-907b3bc518 and m4max 1.18.34-vt-100-907b3bc518. The
section-order feature gains the change row, and the compact Context, MCP
summary, Todo summary and LSP one-line features gain timeline rows.

AI-Tool: opencode 1.18.33-vt-60-2fa3363c92
AI-Model: anthropic/claude-opus-5-5
AI-Variant: max
AI-Platform: linux
AI-Harness: Vibeterm 50691e9
AI-Session-ID: ses_ef81ad30fffeo7m3HoZisuJdli
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants