gitstack

grindlemire/go-tui code browser

1.8 KB 83 lines 2026-03-15 · e5befc1 raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package main

import (
	"fmt"
	tui "github.com/grindlemire/go-tui"
)

// Helper function: formats an item label
func itemLabel(index int, name string, selected bool) string {
	prefix := "  "
	if selected {
		prefix = "> "
	}
	return fmt.Sprintf("%s%d. %s", prefix, index+1, name)
}

// Helper function: returns a style class based on selection
func itemClass(selected bool) string {
	if selected {
		return "text-cyan font-bold"
	}
	return ""
}

// Pure component with children slot
templ Panel(title string) {
	<div class="border-rounded p-1 flex-col gap-1" width={32}>
		<span class="font-bold text-gradient-cyan-magenta">{title}</span>
		<hr />
		{children...}
	</div>
}

// Struct component with state and key handling
type listApp struct {
	items    []string
	selected *tui.State[int]
}

func ListApp() *listApp {
	return &listApp{
		items:    []string{"Alpha", "Bravo", "Charlie", "Delta"},
		selected: tui.NewState(0),
	}
}

func (l *listApp) KeyMap() tui.KeyMap {
	return tui.KeyMap{
		tui.On(tui.KeyEscape, func(ke tui.KeyEvent) { ke.App().Stop() }),
		tui.On(tui.KeyUp, func(ke tui.KeyEvent) {
			l.selected.Update(func(v int) int {
				if v > 0 {
					return v - 1
				}
				return v
			})
		}),
		tui.On(tui.KeyDown, func(ke tui.KeyEvent) {
			l.selected.Update(func(v int) int {
				if v < len(l.items)-1 {
					return v + 1
				}
				return v
			})
		}),
	}
}

templ (l *listApp) Render() {
	<div class="flex-col items-center justify-center h-full">
		@Panel("Select an Item") {
			for i, item := range l.items {
				<span class={itemClass(i == l.selected.Get())}>
					{itemLabel(i, item, i == l.selected.Get())}
				</span>
			}
			<br />
			if l.selected.Get() >= 0 {
				<span class="font-dim">{fmt.Sprintf("Selected: %s", l.items[l.selected.Get()])}</span>
			}
		}
	</div>
}