Skip to content

fix: stretch prototype TUI panels to available space#33

Open
dyoung522 wants to merge 5 commits into
feat/tuifrom
feat/tui-visual-iteration
Open

fix: stretch prototype TUI panels to available space#33
dyoung522 wants to merge 5 commits into
feat/tuifrom
feat/tui-visual-iteration

Conversation

@dyoung522

Copy link
Copy Markdown
Collaborator

Summary

  • Starts Phase 2 visual iteration from feat/tui.
  • Closes completed prototype issue Add prototype TUI with retro theme switching #30 and tracks this phase in TUI Phase 2: visual iteration and available-space layout #32.
  • Makes prototype screen panels use available width and content height instead of fixed-size islands.
  • Removes the Profiles screen width cap so it stretches consistently with the other screens.
  • Uses Lip Gloss border-size calculations for panel sizing so rendered boxes match the intended terminal width.
  • Adds layout tests for available width and height behavior.

Test Plan

  • go test ./...
  • go vet ./...
  • go build -o /tmp/lmm-tui-visual ./cmd/lmm
  • Manual PTY smoke test: /tmp/lmm-tui-visual tui --prototype --theme wizardry, then quit with q

Refs #32

Copilot AI review requested due to automatic review settings April 29, 2026 20:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Advances the Phase 2 prototype TUI layout work by making screen panels size to the available terminal width/height (instead of fixed “islands”), and adds regression tests around the new available-space behavior.

Changes:

  • Make prototype screen views render panels at availableWidth() and (mostly) availableContentHeight().
  • Introduce availableContentHeight() and a panelWithHeight() helper to drive fixed-height panel rendering.
  • Add layout tests asserting screens use available width/height; update changelog entry to reflect the new behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
internal/tui/app.go Reworks panel sizing to use available width/height; adds height-aware panel helper and content-height calculation.
internal/tui/app_test.go Adds tests to validate screen views expand to available width and (at least) available content height.
CHANGELOG.md Updates Unreleased notes to mention available-space panel stretching.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/tui/app.go Outdated
Comment on lines +251 to +252
topHeight := max((height-1)/2, 6)
menuHeight := max(height-topHeight, 6)

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

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

In the party dashboard layout, the height split currently over-allocates by one line: screenView renders topHeight (top row) + 1 separator newline + menuHeight, but menuHeight is computed as height-topHeight, so the combined height becomes height+1 and can get clipped. Consider computing the bottom section as the remaining space after accounting for the separator (e.g., height-topHeight-1) and revisiting the minimums so small terminals don’t force 6 + 1 + 6 lines when less space is available.

Suggested change
topHeight := max((height-1)/2, 6)
menuHeight := max(height-topHeight, 6)
separatorHeight := 1
splitHeight := max(height-separatorHeight, 0)
topHeight := splitHeight / 2
menuHeight := splitHeight - topHeight
if splitHeight >= 12 {
topHeight = max(topHeight, 6)
menuHeight = max(menuHeight, 6)
if topHeight+menuHeight > splitHeight {
menuHeight = splitHeight - topHeight
}
}

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/app.go Outdated
width := m.availableWidth()
height := m.availableContentHeight()
gap := 1
panelWidth := max((width-gap)/2, 24)

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

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

panelWidth := max((width-gap)/2, 24) can exceed the available width on smaller windows (e.g., availableWidth() can be 40, but 24+1+24 requires 49). This makes the joined panels wider than availableWidth() and breaks the “use available width” goal on narrow terminals. Consider clamping panelWidth to at most (width-gap)/2 (or switching to a vertical stack layout below a threshold).

Suggested change
panelWidth := max((width-gap)/2, 24)
panelWidth := (width - gap) / 2

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/app.go Outdated
Comment on lines +419 to +425
func (m Model) availableContentHeight() int {
if m.height == 0 {
return 12
}

const chromeHeight = 6 // title, nav, spacer lines, and one-line footer.
return max(m.height-m.theme.App.GetVerticalFrameSize()-chromeHeight, 8)

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

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

availableContentHeight() hard-codes chromeHeight = 6 as if the non-content chrome is always 6 lines, but View() currently renders 5 fixed lines when help is hidden (title + nav + 2 spacer blank lines + 1-line footer). Also, when m.showHelp is true the footer becomes a multi-line panel, so the available content height should shrink (or help should overlay/replace content) to avoid the view exceeding the terminal height.

Suggested change
func (m Model) availableContentHeight() int {
if m.height == 0 {
return 12
}
const chromeHeight = 6 // title, nav, spacer lines, and one-line footer.
return max(m.height-m.theme.App.GetVerticalFrameSize()-chromeHeight, 8)
func (m Model) contentChromeHeight() int {
const baseChromeHeight = 5 // title, nav, two spacer lines, and one-line footer.
if !m.showHelp {
return baseChromeHeight
}
const extraHelpHeight = 3 // help footer replaces the one-line footer with a multi-line panel.
return baseChromeHeight + extraHelpHeight
}
func (m Model) availableContentHeight() int {
if m.height == 0 {
return 12
}
return max(m.height-m.theme.App.GetVerticalFrameSize()-m.contentChromeHeight(), 8)

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/app_test.go Outdated

for _, screen := range screens {
model.screen = screen
require.GreaterOrEqual(t, lipgloss.Height(model.screenView()), model.availableContentHeight(), screen.String())

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

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

The height assertion here only checks >= availableContentHeight(), which allows screens to overflow the intended content area (e.g., an off-by-one newline in a composed view). Since the goal is to fit the available space, it would be more robust to assert the rendered height does not exceed the available content height as well (or even equals it for fixed-height panels).

Suggested change
require.GreaterOrEqual(t, lipgloss.Height(model.screenView()), model.availableContentHeight(), screen.String())
height := lipgloss.Height(model.screenView())
availableHeight := model.availableContentHeight()
require.GreaterOrEqual(t, height, availableHeight, screen.String())
require.LessOrEqual(t, height, availableHeight, screen.String())

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/app.go Outdated
Comment on lines 300 to 304
width := m.availableWidth()
height := m.availableContentHeight()
gap := 1
leftWidth := max((width-gap)/2, 24)
rightWidth := max(width-gap-leftWidth, 24)

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

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

The commander dashboard’s 2-column width math can exceed availableWidth() on narrow terminals: leftWidth is forced to at least 24 and rightWidth is also forced to at least 24, so the total minimum becomes 24 + 1 + 24 = 49 even though availableWidth() can return as low as 40. Consider clamping the per-column minimum based on width (or falling back to a stacked layout when width < 49).

Copilot uses AI. Check for mistakes.
@dyoung522

Copy link
Copy Markdown
Collaborator Author

Follow-up from Donovan's terminal screenshot:

  • Removed explicit background painting from non-selected theme chrome (App, title, panel fill, panel titles, muted/help text).
  • Kept selected/badge backgrounds so active items still highlight.
  • Added a regression test asserting wizardry chrome uses the terminal default background (lipgloss.NoColor{}), which should avoid the stray dark blocks around the Quest Log panel and between nav/menu labels on terminals with a non-black default background.

Re-verified:

  • go test ./...
  • go vet ./...
  • go build -o /tmp/lmm-tui-visual ./cmd/lmm
  • PTY smoke run for tui --prototype --theme wizardry quit cleanly with q

@dyoung522

Copy link
Copy Markdown
Collaborator Author

Documented the Phase 2 theme decision: wizardry is the selected default for the TUI because it best matches the RPG/tool identity. amber, dos, and green stay available as alternates, with amber noted as the VAX/VMS nostalgia lane.

@dyoung522

Copy link
Copy Markdown
Collaborator Author

Added the implementation-phase note that users should be able to configure their own default TUI theme, analogous to the existing default game workflow. wizardry stays the fresh-install/default recommendation, but --theme remains a per-run override and config should support personal defaults like amber, dos, green, or future themes.

@dyoung522

dyoung522 commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed Copilot's layout-boundary comments in 7f4df61:

  • Removed fixed 24-column minimums from the two-column dashboard layouts so wizardry and dos do not overflow narrow terminals.
  • Tightened the large-terminal content-height regression from >= to exact equality, so off-by-one composition bugs fail instead of being tolerated.
  • Made available content height account for the expanded help footer, so ? help mode still fits the terminal bounds.
  • Added regressions for narrow dashboards and help-visible terminal bounds.

Re-verified:

  • go test ./...
  • go vet ./...
  • go build -o /tmp/lmm-tui-visual ./cmd/lmm
  • PTY smoke run for tui --prototype --theme wizardry, quit cleanly with q

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants