summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--internal/tui/person_selector.go59
-rw-r--r--internal/tui/wizard.go143
2 files changed, 126 insertions, 76 deletions
diff --git a/internal/tui/person_selector.go b/internal/tui/person_selector.go
index 2ae8caf..359c7b3 100644
--- a/internal/tui/person_selector.go
+++ b/internal/tui/person_selector.go
@@ -15,12 +15,24 @@ var (
Bold(true).
Foreground(lipgloss.Color("86"))
- selectedStyle = lipgloss.NewStyle().
+ selectedCardStyle = lipgloss.NewStyle().
+ Border(lipgloss.RoundedBorder()).
+ BorderForeground(lipgloss.Color("86")).
+ Padding(0, 1)
+
+ normalCardStyle = lipgloss.NewStyle().
+ Border(lipgloss.RoundedBorder()).
+ BorderForeground(lipgloss.Color("240")).
+ Padding(0, 1)
+
+ nameStyle = lipgloss.NewStyle().
Bold(true).
- Foreground(lipgloss.Color("229")).
- Background(lipgloss.Color("57"))
+ Foreground(lipgloss.Color("229"))
- normalStyle = lipgloss.NewStyle().
+ labelStyle = lipgloss.NewStyle().
+ Foreground(lipgloss.Color("86"))
+
+ valueStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("252"))
dimStyle = lipgloss.NewStyle().
@@ -29,6 +41,10 @@ var (
helpStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("241"))
+ pointerStyle = lipgloss.NewStyle().
+ Foreground(lipgloss.Color("86")).
+ Bold(true)
+
errorStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("196"))
)
@@ -311,9 +327,9 @@ func (m PersonSelectorModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m PersonSelectorModel) visibleHeight() int {
if m.windowHeight > 0 {
- return m.windowHeight
+ return m.windowHeight / 6
}
- return 20
+ return 5
}
func (m PersonSelectorModel) View() string {
@@ -338,32 +354,33 @@ func (m PersonSelectorModel) View() string {
for i := m.offset; i < endIdx; i++ {
p := m.people[i]
- cursor := " "
- style := normalStyle
+ isSelected := i == m.cursor
- if i == m.cursor {
- cursor = "> "
- style = selectedStyle
+ cardStyle := normalCardStyle
+ if isSelected {
+ cardStyle = selectedCardStyle
}
- line := fmt.Sprintf("%s%d. %s", cursor, p.Index, p.Name)
+ var cardContent strings.Builder
+
+ pointer := " "
+ if isSelected {
+ pointer = pointerStyle.Render("▶ ")
+ }
+ cardContent.WriteString(fmt.Sprintf("%s%s\n", pointer, nameStyle.Render(fmt.Sprintf("%d. %s", p.Index, p.Name))))
- details := []string{}
if p.Age != "" {
- details = append(details, fmt.Sprintf("Age: %s", p.Age))
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Age:"), valueStyle.Render(p.Age)))
}
if p.Location != "" {
- details = append(details, p.Location)
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Location:"), valueStyle.Render(p.Location)))
}
if p.PhoneHint != "" {
- details = append(details, fmt.Sprintf("Phone: %s", p.PhoneHint))
- }
-
- if len(details) > 0 {
- line += dimStyle.Render(fmt.Sprintf(" (%s)", strings.Join(details, ", ")))
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Phone:"), valueStyle.Render(p.PhoneHint)))
}
- b.WriteString(style.Render(line))
+ content := strings.TrimSuffix(cardContent.String(), "\n")
+ b.WriteString(cardStyle.Render(content))
b.WriteString("\n")
}
diff --git a/internal/tui/wizard.go b/internal/tui/wizard.go
index 34ba70e..3bbad2e 100644
--- a/internal/tui/wizard.go
+++ b/internal/tui/wizard.go
@@ -6,7 +6,6 @@ import (
"strings"
"git.db.org.ai/dborg/internal/formatter"
- "github.com/charmbracelet/bubbles/table"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
@@ -30,8 +29,9 @@ type WizardModel struct {
state wizardState
inputs []textinput.Model
focusIndex int
- table table.Model
people []Person
+ cursor int
+ offset int
selectedIdx int
sxKey string
reportData map[string]interface{}
@@ -63,10 +63,6 @@ var (
Foreground(lipgloss.Color("86")).
MarginBottom(1)
- tableStyle = lipgloss.NewStyle().
- BorderStyle(lipgloss.NormalBorder()).
- BorderForeground(lipgloss.Color("240"))
-
statusStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("241")).
Italic(true)
@@ -209,7 +205,8 @@ func (m WizardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.people = people
m.sxKey = msg.sxKey
- m.table = m.buildTable()
+ m.cursor = 0
+ m.offset = 0
m.state = stateResults
return m, nil
@@ -279,14 +276,47 @@ func (m WizardModel) updateResults(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
return m.updateFocus(), nil
case "enter":
- m.selectedIdx = m.table.Cursor()
+ m.selectedIdx = m.cursor
m.state = stateGenerating
return m, m.doReport()
+
+ case "up", "k":
+ if m.cursor > 0 {
+ m.cursor--
+ if m.cursor < m.offset {
+ m.offset = m.cursor
+ }
+ }
+
+ case "down", "j":
+ if m.cursor < len(m.people)-1 {
+ m.cursor++
+ visibleHeight := m.resultsVisibleHeight()
+ if m.cursor >= m.offset+visibleHeight {
+ m.offset = m.cursor - visibleHeight + 1
+ }
+ }
+
+ case "home":
+ m.cursor = 0
+ m.offset = 0
+
+ case "end":
+ m.cursor = len(m.people) - 1
+ visibleHeight := m.resultsVisibleHeight()
+ if len(m.people) > visibleHeight {
+ m.offset = len(m.people) - visibleHeight
+ }
}
- var cmd tea.Cmd
- m.table, cmd = m.table.Update(msg)
- return m, cmd
+ return m, nil
+}
+
+func (m WizardModel) resultsVisibleHeight() int {
+ if m.windowHeight > 0 {
+ return (m.windowHeight - 10) / 6
+ }
+ return 4
}
func (m *WizardModel) updateFocus() WizardModel {
@@ -312,48 +342,6 @@ func (m *WizardModel) updateInputs(msg tea.KeyMsg) tea.Cmd {
return tea.Batch(cmds...)
}
-func (m WizardModel) buildTable() table.Model {
- columns := []table.Column{
- {Title: "#", Width: 4},
- {Title: "Name", Width: 25},
- {Title: "Age", Width: 6},
- {Title: "Location", Width: 25},
- {Title: "Phone Hint", Width: 15},
- }
-
- rows := make([]table.Row, len(m.people))
- for i, p := range m.people {
- rows[i] = table.Row{
- fmt.Sprintf("%d", p.Index),
- p.Name,
- p.Age,
- p.Location,
- p.PhoneHint,
- }
- }
-
- t := table.New(
- table.WithColumns(columns),
- table.WithRows(rows),
- table.WithFocused(true),
- table.WithHeight(min(len(rows)+1, 15)),
- )
-
- s := table.DefaultStyles()
- s.Header = s.Header.
- BorderStyle(lipgloss.NormalBorder()).
- BorderForeground(lipgloss.Color("240")).
- BorderBottom(true).
- Bold(false)
- s.Selected = s.Selected.
- Foreground(lipgloss.Color("229")).
- Background(lipgloss.Color("57")).
- Bold(false)
- t.SetStyles(s)
-
- return t
-}
-
func (m WizardModel) View() string {
switch m.state {
case stateForm:
@@ -415,9 +403,54 @@ func (m WizardModel) viewResults() string {
b.WriteString(statusStyle.Render(fmt.Sprintf("Found %d results", len(m.people))))
b.WriteString("\n\n")
- b.WriteString(tableStyle.Render(m.table.View()))
+ visibleHeight := m.resultsVisibleHeight()
+ endIdx := m.offset + visibleHeight
+ if endIdx > len(m.people) {
+ endIdx = len(m.people)
+ }
+
+ if m.offset > 0 {
+ b.WriteString(dimStyle.Render(fmt.Sprintf(" ↑ %d more above\n", m.offset)))
+ }
- b.WriteString("\n\n")
+ for i := m.offset; i < endIdx; i++ {
+ p := m.people[i]
+ isSelected := i == m.cursor
+
+ cardStyle := normalCardStyle
+ if isSelected {
+ cardStyle = selectedCardStyle
+ }
+
+ var cardContent strings.Builder
+
+ pointer := " "
+ if isSelected {
+ pointer = pointerStyle.Render("▶ ")
+ }
+ cardContent.WriteString(fmt.Sprintf("%s%s\n", pointer, nameStyle.Render(fmt.Sprintf("%d. %s", p.Index, p.Name))))
+
+ if p.Age != "" {
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Age:"), valueStyle.Render(p.Age)))
+ }
+ if p.Location != "" {
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Location:"), valueStyle.Render(p.Location)))
+ }
+ if p.PhoneHint != "" {
+ cardContent.WriteString(fmt.Sprintf(" %s %s\n", labelStyle.Render("Phone:"), valueStyle.Render(p.PhoneHint)))
+ }
+
+ content := strings.TrimSuffix(cardContent.String(), "\n")
+ b.WriteString(cardStyle.Render(content))
+ b.WriteString("\n")
+ }
+
+ remaining := len(m.people) - endIdx
+ if remaining > 0 {
+ b.WriteString(dimStyle.Render(fmt.Sprintf(" ↓ %d more below\n", remaining)))
+ }
+
+ b.WriteString("\n")
b.WriteString(helpStyle.Render("j/k or arrows: navigate | enter: select | esc: back | q: quit"))
return b.String()