gitstack

grindlemire/go-tui code browser

2.2 KB 93 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
84
85
86
87
88
89
90
91
92
93
package main

import tui "github.com/grindlemire/go-tui"

type sidebar struct {
	category *tui.State[string]
	expanded *tui.State[bool]
	selected *tui.State[int]
}

var categories = []string{"Documents", "Images", "Music", "Projects", "Downloads"}

func Sidebar(category *tui.State[string]) *sidebar {
	return &sidebar{
		category: category,
		expanded: tui.NewState(true),
		selected: tui.NewState(0),
	}
}

func (s *sidebar) KeyMap() tui.KeyMap {
	km := tui.KeyMap{
		tui.On(tui.Rune('b').Ctrl(), func(ke tui.KeyEvent) {
			s.expanded.Set(!s.expanded.Get())
		}),
	}
	if s.expanded.Get() {
		km = append(km, tui.On(tui.Rune('j'), func(ke tui.KeyEvent) { s.moveDown() }))
		km = append(km, tui.On(tui.Rune('k'), func(ke tui.KeyEvent) { s.moveUp() }))
		km = append(km, tui.On(tui.KeyDown, func(ke tui.KeyEvent) { s.moveDown() }))
		km = append(km, tui.On(tui.KeyUp, func(ke tui.KeyEvent) { s.moveUp() }))
		km = append(km, tui.On(tui.KeyEnter, func(ke tui.KeyEvent) {
			idx := s.selected.Get()
			if idx >= 0 && idx < len(categories) {
				s.category.Set(categories[idx])
			}
		}))
	}
	return km
}

func (s *sidebar) moveDown() {
	s.selected.Update(func(v int) int {
		if v >= len(categories)-1 {
			return 0
		}
		return v + 1
	})
	s.category.Set(categories[s.selected.Get()])
}

func (s *sidebar) moveUp() {
	s.selected.Update(func(v int) int {
		if v <= 0 {
			return len(categories) - 1
		}
		return v - 1
	})
	s.category.Set(categories[s.selected.Get()])
}

func (s *sidebar) sidebarWidth() int {
	if s.expanded.Get() {
		return 22
	}
	return 5
}

templ (s *sidebar) Render() {
	<div class="flex-col border-single shrink-0" width={s.sidebarWidth()}>
		if s.expanded.Get() {
			<div class="flex-col px-1">
				<span class="text-gradient-cyan-magenta font-bold">Folders</span>
			</div>
			<hr />
			<div class="flex-col px-1 grow">
				for i, cat := range categories {
					if i == s.selected.Get() {
						<span class="text-cyan font-bold">{"> " + cat}</span>
					} else {
						<span class="font-dim">{"  " + cat}</span>
					}
				}
			</div>
			<hr />
			<div class="flex-col px-1">
				<span class="font-dim text-cyan">Ctrl+B hide</span>
			</div>
		} else {
			<span class="text-cyan font-bold px-1">F</span>
		}
	</div>
}