Rules-based browser launcher for TUI + GNOME. switchyard.aly.codes
tui gome bowser go
0

Configure Feed

Select the types of activity you want to include in your feed.

cmd/sw: replace built-in list header and pager with custom views

Aly Raffauf (Jul 5, 2026, 10:52 PM EDT) e5c737df a4d0dc02

+37 -11
+7 -4
cmd/sw/main.go
··· 20 20 browserListWidth = 30 21 21 actionListWidth = 25 22 22 listHeight = 20 23 + listHeaderHeight = 2 24 + listPagerHeight = 1 23 25 24 - // The actions column is a 2-row header stacked on its list; making the list 25 - // shorter keeps that column the same height as the browser list. 26 - actionListHeight = listHeight - 2 26 + browserListHeight = listHeight - listHeaderHeight - listPagerHeight 27 + actionListHeight = browserListHeight 27 28 28 29 // Everything is laid out inside this fixed-size box and then centered, so 29 30 // opening actions never resizes the outer block. Width has slack for the ··· 62 63 delegate.Styles = newDelegateStyles(true) 63 64 64 65 browserList := list.New(items, delegate, browserListWidth, listHeight) 65 - browserList.Title = "Switchyard" 66 + browserList.SetHeight(browserListHeight) 67 + browserList.SetShowTitle(false) 66 68 browserList.SetShowStatusBar(false) 69 + browserList.SetShowPagination(false) 67 70 browserList.SetFilteringEnabled(false) 68 71 browserList.SetShowHelp(false) 69 72
+30 -6
cmd/sw/model.go
··· 188 188 if m.pickingAction { 189 189 columns = sideBySideView(m) 190 190 } else { 191 - columns = m.browserList.View() 191 + columns = browserColumnView(m) 192 192 } 193 193 194 194 content := lipgloss.JoinVertical(lipgloss.Left, ··· 250 250 Render(positioned) 251 251 } 252 252 253 + func browserColumnView(m model) string { 254 + return lipgloss.JoinVertical(lipgloss.Left, 255 + headerView(m, "Switchyard", browserListWidth), 256 + m.browserList.View(), 257 + pagerView(m), 258 + ) 259 + } 260 + 261 + func headerView(m model, title string, width int) string { 262 + header := m.styles.title. 263 + Width(width). 264 + Render(title) 265 + return lipgloss.JoinVertical(lipgloss.Left, header, "") 266 + } 267 + 268 + func pagerView(m model) string { 269 + pager := " " 270 + if m.browserList.Paginator.TotalPages < 2 { 271 + return pager 272 + } 273 + pager = m.browserList.Paginator.View() 274 + return lipgloss.PlaceHorizontal(browserListWidth, lipgloss.Center, pager) 275 + } 276 + 253 277 func sideBySideView(m model) string { 254 - browserView := m.browserList.View() 278 + browserView := browserColumnView(m) 255 279 256 - header := lipgloss.NewStyle(). 257 - Padding(0, 0, 1, 2). 258 - Render(m.styles.title.Render("Actions")) 259 - actionView := lipgloss.JoinVertical(lipgloss.Left, header, m.actionList.View()) 280 + actionView := lipgloss.JoinVertical(lipgloss.Left, 281 + headerView(m, "Actions", actionListWidth), 282 + m.actionList.View(), 283 + ) 260 284 261 285 height := max(lipgloss.Height(browserView), lipgloss.Height(actionView)) 262 286 separator := m.styles.separator.Render(verticalRule(height))
-1
cmd/sw/styles.go
··· 32 32 s.title = lipgloss.NewStyle(). 33 33 Foreground(lipgloss.Color("#FFFDF5")). 34 34 Background(lipgloss.Color(green)). 35 - Width(browserListWidth). 36 35 Align(lipgloss.Center) 37 36 38 37 s.pagination = list.DefaultStyles(darkBG).PaginationStyle.PaddingLeft(4)