Skip to content

Info widget: optional pinned column, [x] to close, start hidden - #22

Closed
levz0r wants to merge 1 commit into
dragonked2:mainfrom
levz0r:info-widget-pinned
Closed

levz0r wants to merge 1 commit into
dragonked2:mainfrom
levz0r:info-widget-pinned

Conversation

@levz0r

@levz0r levz0r commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Problem

The info widget panel (Session, Todos, ...) docks in the transcript's empty right margin and rides with the line it's anchored to. That keeps it off the text, but it also moves, hides and reappears as output streams and scrolls. Some users would rather have it in one place. The only way to dismiss it is the toggle key, which some terminals can't send (Option+I on macOS types ˆ unless Option is mapped to Alt). It also comes back in every new window.

Change

Three opt-in additions. Defaults leave the current behaviour unchanged.

  • display.info_widget_position = "pinned" reserves a fixed 40-cell column on the right of the transcript. Widgets stack top-down in it in priority order: Overview first, absorbing its mergeable widgets as in flow mode, then whatever else fits. The column is decided before the transcript is prepared, so lines wrap to the narrower width instead of running under the panel. The composer, status line and banner keep the full width. If the chat area is under 100 columns (40 + a 60-column minimum for the chat), it falls back to flow. With the panel hidden or empty, no column is reserved and the transcript gets the full width back. "flow" is the default.
  • [x] in each widget's top border. Clicking it hides the panel for the window, exactly like the toggle key. render_all publishes the drawn [x] cells, and the mouse handler hit-tests against those, so the click target always matches what's on screen. The targets are cleared when the widget pass is skipped.
  • display.info_widget = false starts with the panel hidden. The toggle key still shows it.

Also: info_widget::set_enabled, the InfoWidgetPosition enum (lenient, so an unknown value falls back to flow), docs in the default config, and a CHANGELOG entry.

info_widget_data() is now fetched once, earlier in draw_inner (the pinned decision needs it), with its timing kept. The debug-capture "intrudes into content" check is skipped for pinned placements, since they own their column.

Tests

  • pinned_column_needs_pinned_mode_and_room_for_the_chat
  • pinned_widgets_stack_from_the_top_of_the_column: Overview first, one-cell gutter, mergeable widgets absorbed, gaps between widgets, all inside the column.
  • pinned_column_too_short_places_nothing
  • close_button_sits_inside_the_top_right_corner: rect and hit-test bounds.
  • rendered_widget_draws_the_close_button_where_it_is_hit_tested: renders to a TestBackend and reads [x] back from the cells the hit test uses.
  • pinned_info_column_is_carved_off_the_right_edge, no_pinned_info_column_leaves_the_area_alone
  • info_widget_options_default_to_shown_and_flowing, info_widget_options_parse_and_unknown_position_falls_back

Local results (macOS, Rust 1.94.1):

  • cargo fmt --all -- --check passes.
  • cargo clippy --locked --lib --all-targets -- -D warnings: nothing in the touched files. Everything it reports is in untouched files, which are green on ubuntu CI.
  • cargo test --lib --locked: 6,476 passed and 4 failed, all in untouched code and the same as on main: login_openai_phase_is_default_when_no_imports and 3 latex_image tests that fail only in the parallel run.

Live check in a 132-column pane (dev server on its own socket):

 client · perf:reduced                                                    ╭ ◆ AlphaCode · Session ─────────[x]╮
 ───────────────────────────────────────────────────────────────────────  │✎ Free · Alphax Free               │
 api-key:alphax free · ● Alphax Free · /model to switch                   │C:3.2k/2000.0m · est. $0.00        │
 ┌ /private/tmp/ac-pin                                                    │Queue off                          │
                                                                          ╰───────────────────────────────────╯
 1› Reply with exactly one plain paragraph of about 120 words about terminal
 multiplexers. No lists, no headings, no tools.

The prompt and a long multi-line notice (the free model was rate-limited) both wrapped before the column. A left click on [x] (sent as an SGR mouse sequence) hid the panel, and the transcript reflowed to full width.

🤖 Generated with Claude Code

display.info_widget_position = "pinned" stacks the panel in a fixed
40-cell column on the right of the transcript, which wraps narrower so
the panel never covers text or moves. Falls back to flow below a
100-column chat area. Default "flow" is unchanged.

Each widget draws an [x] in its top border; clicking it hides the panel
like the toggle key. Hit targets come from what render_all drew.

display.info_widget = false starts with the panel hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dragonked2

Copy link
Copy Markdown
Owner

Merged and released as v1.0.92. 🎉

Thanks for the clean, well-scoped PR! All three opt-in additions landed:

  • display.info_widget_position = "pinned" (fixed 40-cell right column)
  • [x] close button per widget
  • display.info_widget = false start-hidden

Checks all passed on main at your base commit 2fb16c5:

  • cargo fmt --all -- --check ✅
  • cargo clippy --profile selfdev --locked --lib --all-targets -- -D warnings ✅
  • cargo test --lib: 6441 passed; the 2 failures (backend.rs, ui_header.rs) are pre-existing in untouched files unrelated to this PR

I also fixed two pre-existing clippy::redundant_closure warnings in server_events.rs tests so clippy is fully green, and kept your changelog entry alongside our existing Unreleased notes.

Your in-flight work is untouched — this only touched main. PR base was exactly our HEAD, so it merged cleanly.

dragonked2 pushed a commit that referenced this pull request Nov 2, 2026
Merge PR #22: info widget optional pinned column, [x] to close, start hidden

- display.info_widget_position = "pinned" reserves a fixed 40-cell right
  column; transcript wraps narrower so the panel never covers text or moves
  while output scrolls (falls back to flow below 100 columns)
- [x] close button in each widget's top border hides the panel for the window
- display.info_widget = false starts the panel hidden

Also:
- Bump version to 1.0.92
- Fix redundant closures in server_events.rs tests (clippy::redundant_closure)

Co-authored-by: levz0r <levz0r@users.noreply.github.com>
@dragonked2

Copy link
Copy Markdown
Owner

Already merged locally and released as v1.0.92 (commit b7f3ac1). Changes are in main; closing this PR as redundant.

@dragonked2 dragonked2 closed this Nov 2, 2026
@levz0r
levz0r deleted the info-widget-pinned branch November 2, 2026 20:38
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