feat(tui): powerline separators, chip styles, and sidebar button customization

Merged
LA
2mo ago
+864-142

Closes the visual gap to tmux/zellij status-bar and tab theming, and makes the vertical workspace buttons configurable, building on #10383.

Status bar: status_bar.left_separator / right_separator draw powerline transitions between segments — separator foreground from the previous segment's background, background from the next (the zjstatus/tmux-powerline scheme, mirrored on the right side). status_bar.screens_style (block/pill/slant) wraps the active screen chip in Nerd Font cap glyphs.

Tabs: tabs.style (block/pill/slant) gives solid tab chips catppuccin-style caps; cap cells participate in layout, scrolling, and click hit rects, and replace the ▎ rail accent when active.

Sidebar (vertical workspace buttons):

  • Pinned view actions accept {"action": "new-workspace", "label": "new"} objects to rename buttons, and "command:<id>" entries that pin a user command from commands as a button (labels resolve to the command's display name).
  • sidebar.views[].actions_position: "top" mounts the buttons directly under the view header instead of the bottom edge.
  • sidebar.row_height: 1 drops the subtitle line for dense one-line rows; sidebar.row_gap: 0 removes the padding row between entries (hit rects follow).
  • sidebar.rail_glyph replaces or removes ("none") the active-row accent; sidebar.workspace_label templates rows with {index}/{name}; theme.sidebar_fg/sidebar_selected_fg recolor rows.

Implementation notes: user commands now resolve before sidebar views so buttons can reference them by id, while chord binding still happens after keys overrides; RailPalette stays Copy (the rail glyph is a single char), so rendering never borrows the config; rail::viewport_positioned generalizes the existing bottom-pinned footer.

Docs: docs/configuration.md rows for every key. Tests: chip style and separator parsing, sidebar action objects with labels/positions/command references (including unknown-command rejection), row metrics and template parsing; suite green (1501 tests), fmt and clippy clean, hosted verification passed on Linux and macOS.

Dogfooded in tmux on the hosted binary: powerline bar with paired-color separators and pill screen chip, pill and slant tab caps rendered per chip, dense one-line numbered sidebar with top-mounted new/tab buttons plus a user-command button, all combined with rounded borders and dim-inactive.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Adds powerline separators, chip-cap styles, configurable “+” buttons (with right‑click menus), and sidebar button/layout customization. Improves status‑bar draw performance and validates the sidebar rail glyph to a single‑width character.

  • Status bar: status_bar.left_separator/right_separator render powerline transitions; status_bar.screens_style adds block/pill/slant caps to the active screen chip; status_bar.screens_plus sets the “+” label, optional left‑click action (action or command:<id>), and optional right‑click menu. Right‑click menus dispatch via a new MenuAction::RunConfigured into the existing run_action_for_pane.
  • Tabs: tabs.style adds block/pill/slant caps; cap cells participate in layout/scrolling/hit‑rects and replace the active ▎ rail; tabs.plus customizes the tab “+” label/left‑click action and adds an optional right‑click menu.
  • Sidebar: sidebar.views[].actions now accept {"action":"...","label":"..."} to rename buttons and "command:<id>" to pin user commands; sidebar.views[].actions_position can be "top" or "bottom". sidebar.row_height (1–2), sidebar.row_gap (0–2), sidebar.workspace_label supports {index}/{name}, and new theme.sidebar_fg/theme.sidebar_selected_fg recolor rows. Migration: sidebar.rail_glyph must be exactly one single‑width character or "none" (invalid values are ignored).
  • Ordering and perf: user commands resolve before sidebar views and plus menus so command:<id> can bind; command chords still bind after keys. The status bar draws without per‑frame allocations; the default workspace label path borrows without allocation. Caps, separators, and configurable labels/menus affect layout, scrolling, and click targets. Docs updated in docs/configuration.md.

Summary by CodeRabbit

  • New Features
    • Added customizable sidebar row height, spacing, active-row glyphs, workspace labels, and action placement.
    • Added labeled sidebar actions, configurable action menus, plus-button actions, and pane-specific actions.
    • Added configurable tab and screen chip styles, plus-button labels, and status-bar separators.
    • Expanded sidebar, tab, screen, and workspace labeling and color customization.
  • Documentation
    • Documented the new configuration options.
  • Bug Fixes
    • Improved sidebar hit areas and rendering for variable-height rows and subtitles.

Plus buttons: tabs.plus and status_bar.screens_plus customize the two + buttons — label (any text), action (left-click override: any action name or command:<id>), and menu (a right-click context menu using the sidebar action grammar with per-entry labels). Menu entries dispatch through the new MenuAction::RunConfigured variant into the shared run_action_for_pane path, registered in the menu inventory as composite. Dogfooded in tmux: a + ▾ tab-bar button and ⊕ screen strip button rendered, right-click opened the configured three-entry menu, and clicking the user-command entry spawned its tab.