|
| 1 | +# TUI Enhancement Design |
| 2 | + |
| 3 | +**Date**: 2026-03-22 |
| 4 | +**Status**: Draft |
| 5 | + |
| 6 | +## Context |
| 7 | + |
| 8 | +The current TUI (`mxcli tui`) uses bubbles `list.Model` for panels with page-based scrolling, fixed 3-panel layout, no mouse support, no syntax highlighting, and no BSON/NDSL integration. This design overhauls the TUI for a more fluid, interactive experience. |
| 9 | + |
| 10 | +## Requirements |
| 11 | + |
| 12 | +1. **Unified ScrollList** — Replace `list.Model` with custom component using picker-style smooth scrolling + visual scrollbar |
| 13 | +2. **Breadcrumb navigation** — Top of each panel shows navigation path, clickable |
| 14 | +3. **Z mode** — Press `z` to zoom current panel to fullscreen |
| 15 | +4. **Progressive expansion** — Start with 1 panel, expand as user drills in |
| 16 | +5. **Panel 3 summary mode** — Show metadata summary, Enter opens fullscreen overlay |
| 17 | +6. **Mouse support** — Click selection, scroll wheel, breadcrumb click |
| 18 | +7. **MDL/SQL/NDSL syntax highlighting** — Using alecthomas/chroma |
| 19 | +8. **BSON/NDSL commands** — Cmdbar verbs with multi-level completion |
| 20 | + |
| 21 | +## Architecture |
| 22 | + |
| 23 | +### New Files |
| 24 | + |
| 25 | +| File | Lines | Responsibility | |
| 26 | +|------|-------|----------------| |
| 27 | +| `tui/panels/scrolllist.go` | ~350 | Reusable scrollable list: cursor, scrollOffset, scrollbar, filter, mouse | |
| 28 | +| `tui/panels/breadcrumb.go` | ~80 | Breadcrumb path display and click-to-navigate | |
| 29 | +| `tui/highlight.go` | ~120 | Chroma-based syntax highlighting (MDL/SQL/NDSL) | |
| 30 | +| `tui/overlay.go` | ~150 | Fullscreen overlay with scrollable viewport | |
| 31 | + |
| 32 | +### Modified Files |
| 33 | + |
| 34 | +| File | Changes | |
| 35 | +|------|---------| |
| 36 | +| `tui/panels/modules.go` | Replace `list.Model` → `ScrollList`, add breadcrumb + nav stack | |
| 37 | +| `tui/panels/elements.go` | Same refactor as modules | |
| 38 | +| `tui/layout.go` | Dynamic panel widths, `PanelRect` geometry for mouse hit testing | |
| 39 | +| `tui/model.go` | Visibility state, zen mode, mouse routing, overlay integration, BSON dispatch | |
| 40 | +| `tui/styles.go` | Remove duplicate `typeIconMap`, add scrollbar/overlay styles | |
| 41 | +| `tui/cmdbar.go` | Multi-level completion tree, qualified name completion | |
| 42 | + |
| 43 | +### New Dependency |
| 44 | + |
| 45 | +- `github.com/alecthomas/chroma/v2` |
| 46 | + |
| 47 | +## Phase 1: ScrollList + Breadcrumb (Foundation) |
| 48 | + |
| 49 | +### ScrollList (`tui/panels/scrolllist.go`) |
| 50 | + |
| 51 | +```go |
| 52 | +type ScrollListItem interface { |
| 53 | + Label() string |
| 54 | + Icon() string |
| 55 | + Description() string |
| 56 | + FilterValue() string |
| 57 | +} |
| 58 | + |
| 59 | +type ScrollList struct { |
| 60 | + items []ScrollListItem |
| 61 | + filteredItems []int // indices into items (nil = no filter) |
| 62 | + cursor int |
| 63 | + scrollOffset int |
| 64 | + filterInput textinput.Model |
| 65 | + filterActive bool |
| 66 | + width, height int |
| 67 | + focused bool |
| 68 | + headerHeight int // reserved for breadcrumb |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +**Scrolling**: `scrollOffset + maxVisible` window. Cursor moves smoothly, scrollOffset follows. |
| 73 | + |
| 74 | +**Scrollbar**: Right-side vertical track (`│`) with thumb (`█`). Position = `scrollOffset / (total - maxVisible) * trackHeight`. |
| 75 | + |
| 76 | +**Mouse**: `MouseWheelUp/Down` adjusts scrollOffset. `MouseActionPress` computes `clickedIndex = scrollOffset + (Y - topOffset)`. |
| 77 | + |
| 78 | +**Filter**: `/` activates textinput, real-time substring filter on `FilterValue()`. Esc exits. |
| 79 | + |
| 80 | +### Breadcrumb (`tui/panels/breadcrumb.go`) |
| 81 | + |
| 82 | +```go |
| 83 | +type BreadcrumbSegment struct { |
| 84 | + Label string |
| 85 | +} |
| 86 | + |
| 87 | +type Breadcrumb struct { |
| 88 | + segments []BreadcrumbSegment |
| 89 | + width int |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +Methods: `Push()`, `PopTo(level)`, `Depth()`, `View()` (renders `A > B > C`), `ClickedSegment(x int) int`. |
| 94 | + |
| 95 | +### Panel Refactor |
| 96 | + |
| 97 | +Each panel (modules, elements) maintains: |
| 98 | +- `ScrollList` instead of `list.Model` |
| 99 | +- `Breadcrumb` for navigation path |
| 100 | +- `navigationStack [][]*TreeNode` for drill-in/back |
| 101 | + |
| 102 | +## Phase 2: Progressive Expansion + Z Mode |
| 103 | + |
| 104 | +### Dynamic Layout (`tui/layout.go`) |
| 105 | + |
| 106 | +```go |
| 107 | +type PanelVisibility int |
| 108 | +const ( |
| 109 | + ShowOnePanel PanelVisibility = iota // modules only, 100% |
| 110 | + ShowTwoPanels // modules 35% + elements 65% |
| 111 | + ShowThreePanels // 20% + 30% + 50% |
| 112 | + ShowZoomed // zoomed panel 100% |
| 113 | +) |
| 114 | + |
| 115 | +type PanelRect struct { |
| 116 | + X, Y, Width, Height int |
| 117 | + Visible bool |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +### Visibility State Machine |
| 122 | + |
| 123 | +- Start: `ShowOnePanel` |
| 124 | +- Select module + right/enter → `ShowTwoPanels` |
| 125 | +- Select element → `ShowThreePanels` |
| 126 | +- Left from elements (empty stack) → `ShowOnePanel` |
| 127 | +- Left from preview → `ShowTwoPanels` |
| 128 | + |
| 129 | +### Z Mode |
| 130 | + |
| 131 | +- `z` toggles between `ShowZoomed` and previous visibility |
| 132 | +- Remembers `zenPrevFocus` and `zenPrevVisibility` for restore |
| 133 | +- `Esc` also exits zen mode |
| 134 | + |
| 135 | +## Phase 3: Mouse Support |
| 136 | + |
| 137 | +Root model translates `tea.MouseMsg` coordinates using `PanelRect`: |
| 138 | + |
| 139 | +```go |
| 140 | +case tea.MouseMsg: |
| 141 | + for i, rect := range m.panelLayout { |
| 142 | + if rect.contains(msg.X, msg.Y) { |
| 143 | + localMsg := translateMouse(msg, rect) |
| 144 | + m.focus = Focus(i) |
| 145 | + // forward to panel |
| 146 | + } |
| 147 | + } |
| 148 | +``` |
| 149 | + |
| 150 | +ScrollList handles translated coordinates internally. Breadcrumb click detected by checking `localMsg.Y < headerHeight`. |
| 151 | + |
| 152 | +## Phase 4: Summary + Overlay + Highlighting |
| 153 | + |
| 154 | +### Preview Summary Mode |
| 155 | + |
| 156 | +Panel 3 shows compact metadata card: |
| 157 | +``` |
| 158 | +Type: Entity |
| 159 | +Module: MyModule |
| 160 | +Name: Customer |
| 161 | +Attrs: 5 Assocs: 2 |
| 162 | +[Enter] view details |
| 163 | +``` |
| 164 | + |
| 165 | +`SetContent()` stores both `summaryContent` (panel) and `fullContent` (overlay). |
| 166 | + |
| 167 | +### Fullscreen Overlay (`tui/overlay.go`) |
| 168 | + |
| 169 | +- Reuses `viewport.Model` for scrollable content |
| 170 | +- `lipgloss.Place` for centering |
| 171 | +- Title bar + content + bottom hints |
| 172 | +- Serves: detail view, BSON dump, NDSL output |
| 173 | + |
| 174 | +### Syntax Highlighting (`tui/highlight.go`) |
| 175 | + |
| 176 | +- `alecthomas/chroma/v2` with `terminal256` formatter + `monokai` style |
| 177 | +- SQL lexer as MDL base |
| 178 | +- Custom NDSL lexer (regex: field paths, type annotations, values) |
| 179 | +- Functions: `HighlightMDL()`, `HighlightSQL()`, `HighlightNDSL()`, `DetectAndHighlight()` |
| 180 | + |
| 181 | +## Phase 5: BSON/NDSL Commands |
| 182 | + |
| 183 | +### Multi-level Cmdbar |
| 184 | + |
| 185 | +```go |
| 186 | +type cmdDef struct { |
| 187 | + name string |
| 188 | + children []cmdDef |
| 189 | +} |
| 190 | +``` |
| 191 | + |
| 192 | +Commands: `bson dump <name>`, `bson compare <name>`, `ndsl <name>` |
| 193 | + |
| 194 | +Completion levels: |
| 195 | +1. Command name (bson, ndsl, callers, ...) |
| 196 | +2. Subcommand (dump, compare) |
| 197 | +3. Qualified name (from flattened tree nodes) |
| 198 | + |
| 199 | +Results → `HighlightNDSL()` → `OpenOverlayMsg` → fullscreen overlay |
| 200 | + |
| 201 | +## Phase Dependency |
| 202 | + |
| 203 | +``` |
| 204 | +Phase 1 (ScrollList + Breadcrumb) |
| 205 | + ├──→ Phase 2 (Layout + Z Mode) |
| 206 | + │ └──→ Phase 3 (Mouse) |
| 207 | + └──→ Phase 4 (Summary + Overlay + Highlighting) |
| 208 | + └──→ Phase 5 (BSON/NDSL Commands) |
| 209 | +``` |
| 210 | + |
| 211 | +Phases 2 and 4 can proceed in parallel after Phase 1. |
| 212 | + |
| 213 | +## Verification |
| 214 | + |
| 215 | +After each phase: |
| 216 | +1. `make build` — compiles cleanly |
| 217 | +2. `./bin/mxcli tui -p /mnt/data_sdd/gh/mxproj-GenAIDemo/App.mpr` — manual testing |
| 218 | +3. Verify scrolling, mouse, breadcrumb, overlay, highlighting visually |
| 219 | +4. Run `make test` for any unit tests added |
0 commit comments