Summary
vimcode keeps its primitive rasterisers (`quadraui_tui::draw_` in `src/tui_main/`, `quadraui_gtk::draw_` in `src/gtk/`) private to the vimcode crate. That means every external consumer of `quadraui` — `kubeui` today, the SQL client (#46), the k8s dashboard tracking issue (#145), any future Lua-plugin-driven app via #146 — has to reimplement `draw_list`, `draw_status_bar`, `draw_tree`, `draw_palette`, etc. from scratch.
This is the single biggest gap between what quadraui delivers today and what its design promise claims.
Evidence from the kubeui spike (just merged on develop, #145)
Three workspace crates ended up at:
| Crate |
Lines |
What |
| `kubeui-core` (lib) |
910 |
state + k8s + view-builders + Action reducer — fully shared |
| `kubeui` (TUI bin) |
494 |
crossterm + ratatui rasterisers + KeyCode→Action map |
| `kubeui-gtk` (GTK bin) |
502 |
gtk4 + Cairo/Pango rasterisers + gdk::Key→Action map |
Code sharing: ~65%. The TUI and GTK binaries are structurally identical (same `paint` flow, same modal precedence, same primitive consumption) but each contains ~300 lines of rasterisation that mirrors what `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` already do, just slightly differently.
Pushing the rasterisers into quadraui takes that to ~90%.
Proposal
Create new modules inside the quadraui crate:
```
quadraui/
├── src/
│ ├── lib.rs
│ ├── primitives/ ← already exists
│ ├── tui/ ← NEW — public ratatui rasterisers
│ │ ├── mod.rs
│ │ ├── list.rs
│ │ ├── tree.rs
│ │ ├── palette.rs
│ │ ├── status_bar.rs
│ │ └── tab_bar.rs
│ └── gtk/ ← NEW — public Cairo + Pango rasterisers
│ ├── mod.rs
│ ├── list.rs
│ ├── tree.rs
│ ├── palette.rs
│ ├── status_bar.rs
│ └── tab_bar.rs
└── Cargo.toml ← gate each on a feature
```
Feature gates (matches the existing `gtk-example` precedent):
```toml
[features]
tui = ["dep:ratatui"]
gtk = ["dep:gtk4", "dep:pangocairo"]
[dependencies]
ratatui = { version = "0.29", optional = true }
gtk4 = { version = "0.7", optional = true, features = ["v4_10"] }
pangocairo = { version = "0.18", optional = true }
```
Pure-data primitives stay default-feature (no bloat for consumers that only use the data layer). Apps that want the TUI rasterisers enable `tui`; apps that want the GTK rasterisers enable `gtk`. Vimcode enables both.
Rasterisers should take a backend-agnostic theme handle (a `Theme` struct or trait) so consumers can supply their own colour scheme rather than vimcode's hardcoded one.
Migration plan
- Pilot: pick one primitive (`StatusBar` or `TabBar` — already on D6) and lift just that pair (TUI + GTK) into quadraui. Add tests.
- Vimcode adopts: replace `src/tui_main/quadraui_tui.rs::draw_status_bar` and `src/gtk/quadraui_gtk.rs::draw_status_bar` with re-exports from `quadraui::tui::draw_status_bar` etc. Existing private helpers stay until the next primitive is migrated.
- kubeui adopts: drop `kubeui::draw_status_bar` in both backends, call the quadraui-provided version directly.
- Iterate primitive by primitive: `ListView`, `TreeView`, `Palette`, `Form`, `Tooltip`, `Dialog`, `ContextMenu`. Each migration is a per-primitive commit, vimcode + kubeui both gain the move-up at the same time.
- Cleanup: once all primitives are migrated, vimcode's `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` shrink to pass-throughs and can be deleted.
Tradeoffs
- + External apps stop reimplementing. Bug fixes in rasterisers go to one place. Adding a third backend (Win-GUI) means writing one set of rasterisers, not N.
- + Vimcode's GTK + TUI rewrites (Phase B.5–B.6) become smaller — they consume quadraui rasterisers instead of carrying their own private set.
- - Theme handling needs to generalise. Vimcode's `Theme` is rich (LSP semantic colours, git diff colours, …) but that's specific to a code editor. Quadraui's primitives only need a small surface (bg, fg, accent, border, etc.). Likely outcome: quadraui defines a small `Theme` struct, vimcode and kubeui each populate it from their own theme systems.
- - Versioning friction — once rasterisers are public, primitive layout changes can break consumers' visual output. Existing Phase B.4 already exposes `*Layout` types; raster surface is similar.
Why this is a v1 priority
The k8s dashboard tracking issue (#145) is explicit:
The point isn't the dashboard — it's exercising quadraui from outside vimcode to see what's awkward.
The kubeui spike answered "what's awkward": rasterisers are private. Every other awkwardness was minor — types had `underline: false` extra fields, `StatusBarSegment` had no `width_cells`, etc. — and those are documentation issues. This is structural.
Files
- New: `quadraui/src/tui/`, `quadraui/src/gtk/` (per-primitive rasteriser modules)
- New: `quadraui/src/theme.rs` (small backend-agnostic Theme struct)
- Modified: `quadraui/Cargo.toml` (feature gates)
- Modified: `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` (vimcode-side adoption, primitive by primitive)
- Modified: `kubeui/src/main.rs` and `kubeui-gtk/src/main.rs` (drop reimplemented rasterisers)
Surfaced by
The kubeui validation spike on develop (`1cbc98b`).
Summary
vimcode keeps its primitive rasterisers (`quadraui_tui::draw_` in `src/tui_main/`, `quadraui_gtk::draw_` in `src/gtk/`) private to the vimcode crate. That means every external consumer of `quadraui` — `kubeui` today, the SQL client (#46), the k8s dashboard tracking issue (#145), any future Lua-plugin-driven app via #146 — has to reimplement `draw_list`, `draw_status_bar`, `draw_tree`, `draw_palette`, etc. from scratch.
This is the single biggest gap between what quadraui delivers today and what its design promise claims.
Evidence from the kubeui spike (just merged on develop, #145)
Three workspace crates ended up at:
Code sharing: ~65%. The TUI and GTK binaries are structurally identical (same `paint` flow, same modal precedence, same primitive consumption) but each contains ~300 lines of rasterisation that mirrors what `src/tui_main/quadraui_tui.rs` and `src/gtk/quadraui_gtk.rs` already do, just slightly differently.
Pushing the rasterisers into quadraui takes that to ~90%.
Proposal
Create new modules inside the quadraui crate:
```
quadraui/
├── src/
│ ├── lib.rs
│ ├── primitives/ ← already exists
│ ├── tui/ ← NEW — public ratatui rasterisers
│ │ ├── mod.rs
│ │ ├── list.rs
│ │ ├── tree.rs
│ │ ├── palette.rs
│ │ ├── status_bar.rs
│ │ └── tab_bar.rs
│ └── gtk/ ← NEW — public Cairo + Pango rasterisers
│ ├── mod.rs
│ ├── list.rs
│ ├── tree.rs
│ ├── palette.rs
│ ├── status_bar.rs
│ └── tab_bar.rs
└── Cargo.toml ← gate each on a feature
```
Feature gates (matches the existing `gtk-example` precedent):
```toml
[features]
tui = ["dep:ratatui"]
gtk = ["dep:gtk4", "dep:pangocairo"]
[dependencies]
ratatui = { version = "0.29", optional = true }
gtk4 = { version = "0.7", optional = true, features = ["v4_10"] }
pangocairo = { version = "0.18", optional = true }
```
Pure-data primitives stay default-feature (no bloat for consumers that only use the data layer). Apps that want the TUI rasterisers enable `tui`; apps that want the GTK rasterisers enable `gtk`. Vimcode enables both.
Rasterisers should take a backend-agnostic theme handle (a `Theme` struct or trait) so consumers can supply their own colour scheme rather than vimcode's hardcoded one.
Migration plan
Tradeoffs
Why this is a v1 priority
The k8s dashboard tracking issue (#145) is explicit:
The kubeui spike answered "what's awkward": rasterisers are private. Every other awkwardness was minor — types had `underline: false` extra fields, `StatusBarSegment` had no `width_cells`, etc. — and those are documentation issues. This is structural.
Files
Surfaced by
The kubeui validation spike on develop (`1cbc98b`).