add reusable TUI tab bar component#13831
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
061490a to
c8ca6af
Compare
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds a retained, reusable TUI tab bar component plus shared text-width/truncation helpers and scenario-based tests. The implementation generally follows the intended retained-state and paging model, and I did not find security issues in the changed code.
Concerns
- Keyboard navigation falls through to the off-page fallback even when there is no valid selected key, so callers can unexpectedly select a visible tab from an unselected or stale-selection state.
Verdict
Found: 0 critical, 1 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| }; | ||
| return navigation.order.get(target_index).cloned(); | ||
| } | ||
| match direction { |
There was a problem hiding this comment.
selected_is_visible == false also covers selected_key == None or a stale key, so this fallback makes keyboard navigation select the first/last visible tab when there is no current selection. Return None unless the selected key exists in the supplied order, then use the off-page fallback.
| match direction { | |
| selected_index?; | |
| match direction { |
4835202 to
fced1e8
Compare
ce8145f to
14791bf
Compare
kevinyang372
left a comment
There was a problem hiding this comment.
My feedback is instead of building a dedicated tab bar element, we should have a tab bar view that renders with generic elements
This should be do-able given we have sizing-aware conditional elements implemented in GUI -- we could probably reference that and built it for TUI
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
fced1e8 to
87dd32b
Compare
14791bf to
af903e1
Compare

Description
Adds
TuiTabBar, a retained horizontal tab component for the shared TUI element library. Callers own semantic state—the ordered tabs, selected key, focus, and page anchor—while the component owns stable pointer state, display-cell-aware packing, overflow boundaries, and settled keyboard navigation. It supports an optional fixed main tab, pageable secondary tabs, caller-rendered leading elements, focused/unfocused selection styles, grapheme-safe truncation, semantic click events, and built-in tab/arrow hover affordances.The main implementation is
crates/warpui_core/src/elements/tui/tab_bar.rs. The module documentation at the top of that file is the best entry point: it explains ownership, the per-frame layout flow, how leading elements are measured and reused, how pure paging feeds the rendered row, and why only settled navigation is retained after layout.Shared terminal-string measurement and grapheme-safe ellipsis logic lives in
text_helpers.rsand is reused by both the tab bar and existing TUI column formatting. The tests are intentionally scenario-based rather than one test per field/state.This PR only introduces the reusable primitive. No user-visible surface consumes it yet; the orchestration integration is in the PR above, so screenshots/video are not applicable here.
Linked Issue
CODE-1822 — Orchestration
Review guide
crates/warpui_core/src/elements/tui/tab_bar.rs— main component, retained-state boundary, row construction, paging, navigation, pointer interaction, and top-level architecture documentation.crates/warpui_core/src/elements/tui/text_helpers.rs— shared display-cell width and grapheme-safe truncation.Testing
./script/run-tuiNo visual changes yet, that'll come in the PR above this one in the stack
Agent Mode