Преглед изворни кода

fix(tui): theme dialog visuals

adamdottv пре 8 месеци
родитељ
комит
3ea2daaa4c

+ 11 - 33
packages/tui/internal/components/dialog/theme.go

@@ -5,7 +5,6 @@ import (
 	list "github.com/sst/opencode/internal/components/list"
 	"github.com/sst/opencode/internal/components/modal"
 	"github.com/sst/opencode/internal/layout"
-	"github.com/sst/opencode/internal/styles"
 	"github.com/sst/opencode/internal/theme"
 	"github.com/sst/opencode/internal/util"
 )
@@ -20,35 +19,12 @@ type ThemeDialog interface {
 	layout.Modal
 }
 
-type themeItem struct {
-	name string
-}
-
-func (t themeItem) Render(selected bool, width int) string {
-	th := theme.CurrentTheme()
-	baseStyle := styles.BaseStyle().
-		Width(width - 2).
-		Background(th.BackgroundElement())
-
-	if selected {
-		baseStyle = baseStyle.
-			Background(th.Primary()).
-			Foreground(th.BackgroundElement()).
-			Bold(true)
-	} else {
-		baseStyle = baseStyle.
-			Foreground(th.Text())
-	}
-
-	return baseStyle.Padding(0, 1).Render(t.name)
-}
-
 type themeDialog struct {
 	width  int
 	height int
 
 	modal         *modal.Modal
-	list          list.List[themeItem]
+	list          list.List[list.StringItem]
 	originalTheme string
 	themeApplied  bool
 }
@@ -66,7 +42,7 @@ func (t *themeDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		switch msg.String() {
 		case "enter":
 			if item, idx := t.list.GetSelectedItem(); idx >= 0 {
-				selectedTheme := item.name
+				selectedTheme := string(item)
 				if err := theme.SetTheme(selectedTheme); err != nil {
 					// status.Error(err.Error())
 					return t, nil
@@ -85,11 +61,11 @@ func (t *themeDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 
 	var cmd tea.Cmd
 	listModel, cmd := t.list.Update(msg)
-	t.list = listModel.(list.List[themeItem])
+	t.list = listModel.(list.List[list.StringItem])
 
 	if item, newIdx := t.list.GetSelectedItem(); newIdx >= 0 && newIdx != prevIdx {
-		theme.SetTheme(item.name)
-		return t, util.CmdHandler(ThemeSelectedMsg{ThemeName: item.name})
+		theme.SetTheme(string(item))
+		return t, util.CmdHandler(ThemeSelectedMsg{ThemeName: string(item)})
 	}
 	return t, cmd
 }
@@ -101,6 +77,7 @@ func (t *themeDialog) Render(background string) string {
 func (t *themeDialog) Close() tea.Cmd {
 	if !t.themeApplied {
 		theme.SetTheme(t.originalTheme)
+		return util.CmdHandler(ThemeSelectedMsg{ThemeName: t.originalTheme})
 	}
 	return nil
 }
@@ -110,17 +87,15 @@ func NewThemeDialog() ThemeDialog {
 	themes := theme.AvailableThemes()
 	currentTheme := theme.CurrentThemeName()
 
-	var themeItems []themeItem
 	var selectedIdx int
 	for i, name := range themes {
-		themeItems = append(themeItems, themeItem{name: name})
 		if name == currentTheme {
 			selectedIdx = i
 		}
 	}
 
-	list := list.NewListComponent(
-		themeItems,
+	list := list.NewStringList(
+		themes,
 		10, // maxVisibleThemes
 		"No themes available",
 		true,
@@ -128,6 +103,9 @@ func NewThemeDialog() ThemeDialog {
 
 	// Set the initial selection to the current theme
 	list.SetSelectedIndex(selectedIdx)
+	
+	// Set the max width for the list to match the modal width
+	list.SetMaxWidth(36) // 40 (modal max width) - 4 (modal padding)
 
 	return &themeDialog{
 		list:          list,

+ 37 - 0
packages/tui/internal/components/list/list.go

@@ -5,6 +5,9 @@ import (
 
 	"github.com/charmbracelet/bubbles/v2/key"
 	tea "github.com/charmbracelet/bubbletea/v2"
+	"github.com/charmbracelet/lipgloss/v2"
+	"github.com/sst/opencode/internal/styles"
+	"github.com/sst/opencode/internal/theme"
 )
 
 type ListItem interface {
@@ -123,6 +126,9 @@ func (c *listComponent[T]) SetSelectedIndex(idx int) {
 func (c *listComponent[T]) View() string {
 	items := c.items
 	maxWidth := c.maxWidth
+	if maxWidth == 0 {
+		maxWidth = 80 // Default width if not set
+	}
 	maxVisibleItems := min(c.maxVisibleItems, len(items))
 	startIdx := 0
 
@@ -161,3 +167,34 @@ func NewListComponent[T ListItem](items []T, maxVisibleItems int, fallbackMsg st
 		selectedIdx:         0,
 	}
 }
+
+// StringItem is a simple implementation of ListItem for string values
+type StringItem string
+
+func (s StringItem) Render(selected bool, width int) string {
+	t := theme.CurrentTheme()
+	baseStyle := styles.BaseStyle()
+
+	var itemStyle lipgloss.Style
+	if selected {
+		itemStyle = baseStyle.
+			Background(t.Primary()).
+			Foreground(t.Background()).
+			Width(width).
+			PaddingLeft(1)
+	} else {
+		itemStyle = baseStyle.
+			PaddingLeft(1)
+	}
+
+	return itemStyle.Render(string(s))
+}
+
+// NewStringList creates a new list component with string items
+func NewStringList(items []string, maxVisibleItems int, fallbackMsg string, useAlphaNumericKeys bool) List[StringItem] {
+	stringItems := make([]StringItem, len(items))
+	for i, item := range items {
+		stringItems[i] = StringItem(item)
+	}
+	return NewListComponent(stringItems, maxVisibleItems, fallbackMsg, useAlphaNumericKeys)
+}