add hover highlight
This commit is contained in:
+13
-6
@@ -182,13 +182,14 @@ func (t *FsTree) GetSelectedContent() (string, error) {
|
|||||||
return string(contentBytes), nil
|
return string(contentBytes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *FsTree) Render() string {
|
func (t *FsTree) Render(hoverLine int) string {
|
||||||
builder := &strings.Builder{}
|
builder := &strings.Builder{}
|
||||||
t.renderNode(t.root, 0, builder)
|
lineCounter := 0
|
||||||
|
t.renderNode(t.root, 0, builder, hoverLine, &lineCounter)
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *FsTree) renderNode(node *FsNode, depth int, builder *strings.Builder) {
|
func (t *FsTree) renderNode(node *FsNode, depth int, builder *strings.Builder, hoverLine int, currentLine *int) {
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -209,18 +210,24 @@ func (t *FsTree) renderNode(node *FsNode, depth int, builder *strings.Builder) {
|
|||||||
icon = lipgloss.NewStyle().Faint(true).Render(prevIndent + icon + indent)
|
icon = lipgloss.NewStyle().Faint(true).Render(prevIndent + icon + indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// highlight if selected
|
// highlight if selected or hovered
|
||||||
fileName := node.FileName()
|
fileName := node.FileName()
|
||||||
if node == t.selectedNode() {
|
isSelected := node == t.selectedNode()
|
||||||
|
isHovered := hoverLine >= 0 && *currentLine == hoverLine
|
||||||
|
|
||||||
|
if isSelected {
|
||||||
fileName = lipgloss.NewStyle().Foreground(styles.Highlight).Bold(true).Render(fileName)
|
fileName = lipgloss.NewStyle().Foreground(styles.Highlight).Bold(true).Render(fileName)
|
||||||
|
} else if isHovered {
|
||||||
|
fileName = lipgloss.NewStyle().Foreground(styles.HoverHighlight).Render(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
line := icon + " " + fileName + "\n"
|
line := icon + " " + fileName + "\n"
|
||||||
builder.WriteString(line)
|
builder.WriteString(line)
|
||||||
|
*currentLine++
|
||||||
|
|
||||||
if node.expanded {
|
if node.expanded {
|
||||||
for _, child := range node.children {
|
for _, child := range node.children {
|
||||||
t.renderNode(child, depth+1, builder)
|
t.renderNode(child, depth+1, builder, hoverLine, currentLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,10 @@ type model struct {
|
|||||||
tree *fs.FsTree
|
tree *fs.FsTree
|
||||||
// spinner needs to be state as I need to update the spinner on
|
// spinner needs to be state as I need to update the spinner on
|
||||||
// each tick in update func
|
// each tick in update func
|
||||||
spinner spinner.Model
|
spinner spinner.Model
|
||||||
loading bool
|
loading bool
|
||||||
viewport viewport.Model
|
viewport viewport.Model
|
||||||
|
hoverLine int // track which line is being hovered
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial model state
|
// initial model state
|
||||||
@@ -63,6 +64,7 @@ func createModel() model {
|
|||||||
spinner: s,
|
spinner: s,
|
||||||
loading: true,
|
loading: true,
|
||||||
viewport: viewport.New(0, 0),
|
viewport: viewport.New(0, 0),
|
||||||
|
hoverLine: -1, // no hover initially
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +107,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.spinner, cmd = m.spinner.Update(msg)
|
m.spinner, cmd = m.spinner.Update(msg)
|
||||||
return m, cmd
|
return m, cmd
|
||||||
case tea.MouseMsg:
|
case tea.MouseMsg:
|
||||||
|
// track hover for all mouse events within file tree
|
||||||
|
if msg.X < m.width {
|
||||||
|
m.hoverLine = msg.Y
|
||||||
|
} else {
|
||||||
|
m.hoverLine = -1
|
||||||
|
}
|
||||||
|
|
||||||
if msg.Button == tea.MouseButtonLeft {
|
if msg.Button == tea.MouseButtonLeft {
|
||||||
// within file tree
|
// within file tree
|
||||||
if msg.X < m.width {
|
if msg.X < m.width {
|
||||||
@@ -151,7 +160,7 @@ func (m model) View() string {
|
|||||||
|
|
||||||
left := lipgloss.NewStyle().
|
left := lipgloss.NewStyle().
|
||||||
Width(m.width).
|
Width(m.width).
|
||||||
Render(m.tree.Render())
|
Render(m.tree.Render(m.hoverLine))
|
||||||
|
|
||||||
right := lipgloss.NewStyle().
|
right := lipgloss.NewStyle().
|
||||||
Width(m.terminalWidth - m.width - 1).
|
Width(m.terminalWidth - m.width - 1).
|
||||||
@@ -173,7 +182,7 @@ func main() {
|
|||||||
p := tea.NewProgram(
|
p := tea.NewProgram(
|
||||||
createModel(),
|
createModel(),
|
||||||
tea.WithAltScreen(), // full screen tui
|
tea.WithAltScreen(), // full screen tui
|
||||||
tea.WithMouseCellMotion(),
|
tea.WithMouseAllMotion(),
|
||||||
)
|
)
|
||||||
if _, err := p.Run(); err != nil {
|
if _, err := p.Run(); err != nil {
|
||||||
fmt.Printf("Error: %v", err)
|
fmt.Printf("Error: %v", err)
|
||||||
|
|||||||
+5
-4
@@ -11,10 +11,11 @@ import "github.com/charmbracelet/lipgloss"
|
|||||||
|
|
||||||
// ==================== colors ====================
|
// ==================== colors ====================
|
||||||
var (
|
var (
|
||||||
Primary = lipgloss.Color("#7D56F4")
|
Primary = lipgloss.Color("#7D56F4")
|
||||||
Secondary = lipgloss.Color("#FF5C8F")
|
Secondary = lipgloss.Color("#FF5C8F")
|
||||||
Background = lipgloss.Color("#1E1E2E")
|
Background = lipgloss.Color("#1E1E2E")
|
||||||
Highlight = lipgloss.Color("#FFA500") // Orange highlight for selected node
|
Highlight = lipgloss.Color("#FFA500") // Orange highlight for selected node
|
||||||
|
HoverHighlight = lipgloss.Color("#4ECDC4") // Teal highlight for hovered node
|
||||||
// TODO: to extend as needed, right now this is just a
|
// TODO: to extend as needed, right now this is just a
|
||||||
// placeholder
|
// placeholder
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user