Skip to content

warpui_core(tui): build TUI element primitives on ratatui-core#12758

Draft
kevinyang372 wants to merge 1 commit into
zb/tui-backend/03b-tui-elementsfrom
kevin/integrate-with-ratatui
Draft

warpui_core(tui): build TUI element primitives on ratatui-core#12758
kevinyang372 wants to merge 1 commit into
zb/tui-backend/03b-tui-elementsfrom
kevin/integrate-with-ratatui

Conversation

@kevinyang372

@kevinyang372 kevinyang372 commented Jun 17, 2026

Copy link
Copy Markdown
Member

Description

Swap the prototype TUI element library's hand-rolled primitive layer for ratatui 0.30 primitives, behind the existing additive tui cargo feature. The default (GUI) and wasm builds are unaffected — tui is off by default and ratatui is an optional dependency.

This is the first step of building a TUI rendering backend for WarpUI (to support a TUI version of the agent harness). It is stacked on the prototype element library (zb/tui-backend/03b-tui-elements).

What changed:

  • TuiBuffer / TuiStyle / Cell now re-export ratatui::buffer::Buffer / ratatui::style::Style / Cell, plus a TuiBufferExt::to_lines headless test helper.
  • TuiSize / TuiRect re-export ratatui::layout::{Size, Rect}. A small local TuiConstraint is kept (ratatui's Constraint is the layout-solver enum, not a min/max measure box), and a TuiRectExt keeps the inset / split_top / split_left helpers the hand-rolled column/container rely on.
  • TuiText wraps and measures via ratatui::widgets::Paragraph (line_count / line_width) instead of the naive splitter.
  • TuiContainer paints through ratatui's Buffer writers (cell_mut / set_style).
  • Depends on the ratatui umbrella crate (crossterm 0.29, matching the prototype) with unstable-rendered-line-info + unstable-widget-ref.

Rationale and the full design (why hybrid / ratatui-core over hand-rolling) are in the plan linked below.

Linked Issue

No linked issue — internal, WIP infrastructure gated behind the tui feature (not user-visible).

Testing

  • cargo nextest run -p warpui_core --features tui — all pass (geometry / buffer / text / element tests ported to ratatui).
  • cargo test -p warpui_core --features tui --doc — pass.
  • cargo build -p warpui_core (default, no tui) — unaffected.
  • ./script/format and cargo clippy -p warpui_core --features tui --all-targets -- -D warnings — clean.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Plan: https://staging.warp.dev/drive/notebook/RQNlhRWhQK3Djnr50YbC4G
Conversation: https://staging.warp.dev/conversation/9293e035-3939-42c7-aeee-110a5a131011

CHANGELOG-NONE

@cla-bot cla-bot Bot added the cla-signed label Jun 17, 2026

kevinyang372 commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

Swap the prototype's hand-rolled cell buffer, geometry, and text wrapping
for ratatui 0.30 primitives, all behind the additive `tui` feature:

- TuiBuffer/TuiStyle/Cell re-export ratatui Buffer/Style/Cell; add a
  TuiBufferExt::to_lines headless test helper.
- TuiSize/TuiRect re-export ratatui Size/Rect; keep a local TuiConstraint
  (ratatui Constraint is the layout-solver enum) plus a TuiRectExt for the
  inset/split_top/split_left helpers ratatui Rect lacks.
- TuiText wraps/measures via ratatui Paragraph (line_count/line_width).
- TuiContainer paints via ratatui Buffer writers (cell_mut/set_style).

Pulls the ratatui umbrella crate (crossterm 0.29, matching the prototype)
with the unstable-rendered-line-info/-widget-ref features.
@zachbai zachbai force-pushed the kevin/integrate-with-ratatui branch from 2998c72 to fa13e01 Compare June 19, 2026 23:57
@zachbai zachbai force-pushed the zb/tui-backend/03b-tui-elements branch from 01cd3c6 to a09fa6e Compare June 19, 2026 23:57

@warp-dev-github-integration warp-dev-github-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Swaps the prototype TUI element library's hand-rolled primitive layer (TuiBuffer/Cell/TuiStyle, TuiSize/TuiRect, and the naive text wrapper) for ratatui 0.30 re-exports, behind the additive tui cargo feature. ratatui is an optional dep and tui is off by default, so the GUI/wasm builds are untouched. Geometry keeps a local TuiConstraint (correctly distinguished from ratatui's layout-solver Constraint) and moves the inset/split_top/split_left helpers onto a TuiRectExt trait; TuiText now measures/paints through Paragraph; TuiContainer paints via Buffer writers; to_lines becomes a TuiBufferExt test helper.

Assessment

Nice, tightly-scoped refactor — the module docs are excellent and the design rationale (hybrid: ratatui primitives + local constraint/slicing helpers) is sound.

Things I checked:

  • contains_position removal is safe — it was only referenced by its own (now-removed) test; no production caller depends on it (ratatui's Rect::contains is available if hit-testing needs it later).
  • Empty-text layout path is consistentconstraint.clamp(TuiSize::ZERO) produces the same result as the non-empty (constrain_width(0), constrain_height(0)) path, and layout/render/desired_height now all defer to Paragraph, so they agree.
  • TuiBufferExt::to_lines wide-grapheme skip is correct — the leading cell sets skip = cell_width-1, trailing continuation columns are skipped, so every glyph is emitted exactly once.
  • Intentional behavior change worth calling out for downstream PRs: wrap policy now preserves whitespace (Wrap { trim: false }) instead of collapsing space runs, and wrapping only breaks once the row width is reached. Tests were updated accordingly.

Concerns

None blocking. Two non-blocking suggestions below (one inline). As an initial, feature-gated, non-user-visible infra PR, I'm treating these as optional.

Note: I reviewed the diff statically and did not independently compile/run the suite (the crate pulls a heavy dep graph); relying on the author's stated cargo nextest/clippy/doc runs.

Verdict

Found: 0 critical, 0 important, 2 suggestions

Approve

Comment on lines +69 to +74
ratatui = { version = "0.30", optional = true, features = [
"scrolling-regions",
"unstable-backend-writer",
"unstable-rendered-line-info",
"unstable-widget-ref",
] }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] Of the four enabled ratatui features, only unstable-rendered-line-info looks exercised by this PR's code (Paragraph::line_count/line_width in text.rs); Widget::render, Buffer, and cell_mut/set_style are all stable. If scrolling-regions, unstable-backend-writer, and unstable-widget-ref are intended for the later stacked runtime/backend PRs, consider enabling each in the PR that first uses it so the feature set tracks the code. As-is this also drifts from the PR description, which lists only two unstable features. Non-blocking.

@harryalbert harryalbert mentioned this pull request Jun 20, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant