From 5bc0a5771f86fa06ae800c1beacb154e59bb7132 Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Sat, 3 Oct 2026 11:55:14 +0200 Subject: [PATCH] dynamic header view, introduced compact view and compact navigation, minimum allowed terminal width #87 --- internal/ui/app.go | 20 ++++++++++++++++---- internal/ui/commands.go | 6 +++++- internal/ui/render.go | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/internal/ui/app.go b/internal/ui/app.go index 81b42fa..474da51 100644 --- a/internal/ui/app.go +++ b/internal/ui/app.go @@ -571,6 +571,16 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m Model) View() string { + if m.width < minTerminalWidth || m.height < minTerminalHeight { + return lipgloss.Place( + m.width, + m.height, + lipgloss.Center, + lipgloss.Center, + "Terminal window too small", + ) + } + header := m.renderHeader() contentView := m.renderTable() @@ -584,10 +594,12 @@ func (m Model) View() string { if m.resource != nil { var resourceTags strings.Builder - for _, entry := range m.navigation { - resourceTags.WriteString( - navigationTagStyle.Render(" <"+entry.resource+"> ") + " ", - ) + if m.width > compactWidth { + for _, entry := range m.navigation { + resourceTags.WriteString( + navigationTagStyle.Render(" <"+entry.resource+"> ") + " ", + ) + } } activeResourceStyle := resourceTagStyle diff --git a/internal/ui/commands.go b/internal/ui/commands.go index 1016312..ab11d2e 100644 --- a/internal/ui/commands.go +++ b/internal/ui/commands.go @@ -113,7 +113,11 @@ func (m *Model) executeResourceCommand(key string) tea.Cmd { if m.resource.Kind() == "contexts" && key == "a" { m.activatingContext = true m.showLoading = true - m.loadingLabel = "Connecting to " + row.ID + + m.loadingLabel = "Connecting" + if m.width > compactWidth { + m.loadingLabel += " to " + row.ID + } } loadID := m.loadID diff --git a/internal/ui/render.go b/internal/ui/render.go index 8f6e4c9..5d0e335 100644 --- a/internal/ui/render.go +++ b/internal/ui/render.go @@ -15,17 +15,31 @@ const logo = ` ___ _____ _ | |_| | / / | < \___/ /_/ |_|\_\` +const ( + minTerminalWidth = 60 + minTerminalHeight = 15 + compactWidth = 120 + logoWidth = 23 +) + func (m Model) renderHeader() string { - const ( - contextWidth = 55 - logoWidth = 23 - ) + if m.width < minTerminalWidth { + return "" + } - profile := m.renderHeaderContext(contextWidth) commands := m.renderHeaderCommands() + if m.width < compactWidth { + return lipgloss.NewStyle(). + Width(m.width). + Render(commands) + } + + profile := m.renderHeaderContext() renderedLogo := logoStyle.Render(logo) - commandWidth := max(m.width-contextWidth-logoWidth, 1) + availableWidth := m.width + contextWidth := lipgloss.Width(profile) + commandWidth := max(availableWidth-contextWidth-logoWidth, 1) left := lipgloss.NewStyle().Width(contextWidth).Render(profile) center := lipgloss.NewStyle().Width(commandWidth).Align(lipgloss.Left).Render(commands) @@ -34,16 +48,17 @@ func (m Model) renderHeader() string { return lipgloss.JoinHorizontal(lipgloss.Top, left, center, right) } -func (m Model) renderHeaderContext(width int) string { +func (m Model) renderHeaderContext() string { const labelWidth = 10 + const contextWidth = 48 - valueWidth := max(width-labelWidth, 1) + valueWidth := contextWidth - labelWidth field := func(label, value string) string { value = truncate(value, valueWidth) return headerLabelStyle.Width(labelWidth).Render(label) + - headerValueStyle.Render(value) + headerValueStyle.Width(valueWidth).Render(value) } return strings.Join([]string{ @@ -106,6 +121,10 @@ func (m Model) renderTable() string { m.resource.Kind(), m.itemCount, ) + + if m.width < compactWidth && m.context.Cloud != "" { + title = fmt.Sprintf(" (%s)%s", m.context.Cloud, title) + } } innerWidth := max(m.width-2, 1)