feat(tui): bordered log sidebar, Enter for full-screen detail

Log sidebar wrapped in rounded border (no left/bottom edge — shared
with monitors table). Creates visual separation between panels.

Enter on a monitor opens the full-screen detail view (existing
stateDetail) for deep dive — history, SLA, probe results, connection
chain. i stays as inline detail toggle.

Footer key hints now context-sensitive: show h/s/Enter when detail
is open, show full keybindings when closed.
This commit is contained in:
2026-06-20 19:18:57 -04:00
parent 5720fabdbc
commit 08f14f3af8
2 changed files with 23 additions and 4 deletions
+7 -1
View File
@@ -555,7 +555,13 @@ func (m *Model) handleDashboardKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
}
case "n":
return m.handleNewItem()
case "e", "enter":
case "enter":
if m.currentTab == tabMonitors && len(m.sites) > 0 {
m.state = stateDetail
return m, m.loadDetailCmd(m.sites[m.cursor].ID)
}
return m.handleEditItem()
case "e":
return m.handleEditItem()
case "t":
if m.currentTab == tabSettings && m.settingsSection == sectionAlerts && len(m.alerts) > 0 {
+16 -3
View File
@@ -160,8 +160,17 @@ func (m Model) viewDashboard() string {
m.contentWidth = leftW
monitors := m.viewSitesTab()
left := lipgloss.NewStyle().Width(leftW).Render(monitors)
sidebar := m.viewLogsSidebar(rightW, m.maxTableRows+chromeTable)
right := lipgloss.NewStyle().Width(rightW).Render(sidebar)
sidebarBorder := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(m.theme.Border).
BorderLeft(false).
BorderBottom(false)
innerW := rightW - 2
if innerW < 10 {
innerW = 10
}
sidebar := m.viewLogsSidebar(innerW, m.maxTableRows)
right := sidebarBorder.Render(sidebar)
top := lipgloss.JoinHorizontal(lipgloss.Top, left, right)
if m.detailOpen {
detail := m.viewDetailInline(availW)
@@ -291,7 +300,11 @@ func (m Model) renderFooter(stats dashboardStats) string {
var keys string
switch m.currentTab {
case tabMonitors:
keys = "[/]Filter [n]New [e]Edit [i]Info [d]Del [p]Pause [Space]Collapse [T]Theme [Tab]Switch [q]Quit"
if m.detailOpen {
keys = "[i]Close [Enter]Expand [h]History [s]SLA [e]Edit [↑/↓]Select [T]Theme [q]Quit"
} else {
keys = "[/]Filter [i]Info [Enter]Detail [n]New [e]Edit [d]Del [p]Pause [T]Theme [Tab]Switch [q]Quit"
}
case tabMaint:
keys = "[n]New [x]End [d]Del [T]Theme [Tab]Switch [q]Quit"
case tabSettings: