fix(tui): help dialog visuals

This commit is contained in:
adamdottv 2025-06-22 14:28:08 -05:00
parent 333569bed3
commit d271b9f75b
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
2 changed files with 77 additions and 18 deletions

View file

@ -25,6 +25,7 @@ type commandsComponent struct {
app *app.App
width, height int
showKeybinds bool
showAll bool
background *compat.AdaptiveColor
limit *int
}
@ -75,17 +76,32 @@ func (c *commandsComponent) View() string {
keybindStyle = keybindStyle.Background(*c.background)
}
var commandsWithTriggers []commands.Command
var commandsToShow []commands.Command
var triggeredCommands []commands.Command
var untriggeredCommands []commands.Command
for _, cmd := range c.app.Commands.Sorted() {
if cmd.Trigger != "" {
commandsWithTriggers = append(commandsWithTriggers, cmd)
if c.showAll || cmd.Trigger != "" {
if cmd.Trigger != "" {
triggeredCommands = append(triggeredCommands, cmd)
} else if c.showAll {
untriggeredCommands = append(untriggeredCommands, cmd)
}
}
}
if c.limit != nil && len(commandsWithTriggers) > *c.limit {
commandsWithTriggers = commandsWithTriggers[:*c.limit]
// Combine triggered commands first, then untriggered
commandsToShow = append(commandsToShow, triggeredCommands...)
commandsToShow = append(commandsToShow, untriggeredCommands...)
if c.limit != nil && len(commandsToShow) > *c.limit {
commandsToShow = commandsToShow[:*c.limit]
}
if len(commandsWithTriggers) == 0 {
if len(commandsToShow) == 0 {
if c.showAll {
return styles.Muted().Render("No commands available")
}
return styles.Muted().Render("No commands with triggers available")
}
@ -101,10 +117,15 @@ func (c *commandsComponent) View() string {
keybinds string
}
rows := make([]commandRow, 0, len(commandsWithTriggers))
rows := make([]commandRow, 0, len(commandsToShow))
for _, cmd := range commandsWithTriggers {
trigger := "/" + cmd.Trigger
for _, cmd := range commandsToShow {
trigger := ""
if cmd.Trigger != "" {
trigger = "/" + cmd.Trigger
} else {
trigger = string(cmd.Name)
}
description := cmd.Description
// Format keybindings
@ -144,6 +165,7 @@ func (c *commandsComponent) View() string {
// Build the output
var output strings.Builder
maxWidth := 0
for _, row := range rows {
// Pad each column to align properly
trigger := fmt.Sprintf("%-*s", maxTriggerWidth, row.trigger)
@ -160,10 +182,14 @@ func (c *commandsComponent) View() string {
}
output.WriteString(line + "\n")
maxWidth = max(maxWidth, lipgloss.Width(line))
}
// Remove trailing newline
result := strings.TrimSuffix(output.String(), "\n")
if c.background != nil {
result = lipgloss.NewStyle().Background(c.background).Width(maxWidth).Render(result)
}
return result
}
@ -188,11 +214,18 @@ func WithLimit(limit int) Option {
}
}
func WithShowAll(showAll bool) Option {
return func(c *commandsComponent) {
c.showAll = showAll
}
}
func New(app *app.App, opts ...Option) CommandsComponent {
c := &commandsComponent{
app: app,
background: nil,
showKeybinds: true,
showAll: false,
}
for _, opt := range opts {
opt(c)

View file

@ -1,6 +1,7 @@
package dialog
import (
"github.com/charmbracelet/bubbles/v2/viewport"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/sst/opencode/internal/app"
commandsComponent "github.com/sst/opencode/internal/components/commands"
@ -15,28 +16,47 @@ type helpDialog struct {
modal *modal.Modal
app *app.App
commandsComponent commandsComponent.CommandsComponent
viewport viewport.Model
}
func (h *helpDialog) Init() tea.Cmd {
return h.commandsComponent.Init()
return tea.Batch(
h.commandsComponent.Init(),
h.viewport.Init(),
)
}
func (h *helpDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
h.width = msg.Width
h.height = msg.Height
h.commandsComponent.SetSize(msg.Width, msg.Height)
// Set viewport size with some padding for the modal
h.viewport = viewport.New(viewport.WithWidth(msg.Width-4), viewport.WithHeight(msg.Height-6))
h.commandsComponent.SetSize(msg.Width-4, msg.Height-6)
}
_, cmd := h.commandsComponent.Update(msg)
return h, cmd
// Update commands component first to get the latest content
_, cmdCmd := h.commandsComponent.Update(msg)
cmds = append(cmds, cmdCmd)
// Update viewport content
h.viewport.SetContent(h.commandsComponent.View())
// Update viewport
var vpCmd tea.Cmd
h.viewport, vpCmd = h.viewport.Update(msg)
cmds = append(cmds, vpCmd)
return h, tea.Batch(cmds...)
}
func (h *helpDialog) View() string {
t := theme.CurrentTheme()
h.commandsComponent.SetBackgroundColor(t.BackgroundElement())
return h.commandsComponent.View()
return h.viewport.View()
}
func (h *helpDialog) Render(background string) string {
@ -52,9 +72,15 @@ type HelpDialog interface {
}
func NewHelpDialog(app *app.App) HelpDialog {
vp := viewport.New(viewport.WithHeight(12))
return &helpDialog{
app: app,
commandsComponent: commandsComponent.New(app, commandsComponent.WithBackground(theme.CurrentTheme().BackgroundElement())),
modal: modal.New(modal.WithTitle("Help")),
app: app,
commandsComponent: commandsComponent.New(app,
commandsComponent.WithBackground(theme.CurrentTheme().BackgroundElement()),
commandsComponent.WithShowAll(true),
commandsComponent.WithKeybinds(true),
),
modal: modal.New(modal.WithTitle("Help")),
viewport: vp,
}
}