feat(tui): render hotbar in sidebar#2945
Conversation
Render configured/default hotbar slots at the bottom of the sidebar. Load resolved hotbar bindings into app state, display them as compact sidebar rows, highlight active slots, and preserve unknown actions visibly. Keep narrow sidebar rows within the available width so slots do not wrap or disappear. Add focused sidebar hotbar render and layout tests.
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
Code Review
This pull request introduces a configurable hotbar panel at the bottom of the TUI sidebar. It resolves hotbar bindings from the configuration, splits the sidebar layout vertically to allocate space for the hotbar when the terminal height is sufficient, and renders the hotbar slots with active/inactive states and custom labels. The review feedback suggests two improvements in crates/tui/src/tui/sidebar.rs: first, using unicode_width::UnicodeWidthStr::width instead of standard Rust formatting padding to prevent layout overflow when hotbar labels contain double-width characters or emojis; second, avoiding unnecessary cloning of binding.label by using .as_ref() and .cloned() during the filtering step.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| let text = truncate_line_to_width(&format!("{}:{label}", cell.slot), cell_width); | ||
| let padded = format!("{text:<cell_width$}"); |
There was a problem hiding this comment.
Using Rust's standard formatting width specifier (e.g., {text:<cell_width$}) pads based on the number of Unicode code points (char count) rather than the actual visual display width. If the hotbar action labels contain double-width characters (such as East Asian characters or emojis), this will cause the padded cells to exceed cell_width in visual width, leading to layout overflow or clipping in the sidebar.\n\nWe can resolve this by calculating the visual width using unicode_width::UnicodeWidthStr::width and manually extending the string with the correct number of spaces.
let mut padded = truncate_line_to_width(&format!("{}:{label}", cell.slot), cell_width);\n let text_width = unicode_width::UnicodeWidthStr::width(padded.as_str());\n padded.extend(std::iter::repeat(' ').take(cell_width.saturating_sub(text_width)));| let label = binding | ||
| .label | ||
| .clone() | ||
| .filter(|label| !label.trim().is_empty()) |
There was a problem hiding this comment.
|
Merged to main — thanks @reidliu41. Retargeted from the stewardship branch since your fork point was already contained in main. Key dispatch (1-8 / Alt+1..8) green-lit as the follow-up slice; part of the #2061 Hotbar program. |
Summary
Ref: #2065
Part of #2061
This adds the sidebar rendering layer for the Hotbar work:
This PR only adds the visible Hotbar panel. Key dispatch for
1-8/Alt+1..8remains a separate follow-up.Testing
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-featurescargo test --workspace --all-featuresChecklist