summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-06-22 05:34:22 -0500
committeradamdottv <[email protected]>2025-06-22 05:34:22 -0500
commit3ea2daaa4c1fef54c3e827300a63bd3b41b88806 (patch)
tree17e2aabe13ecf01a2aa047cc9fec00ae604b864c
parent137e964131703704e99a632b3aa0351ab4921fae (diff)
downloadopencode-3ea2daaa4c1fef54c3e827300a63bd3b41b88806.tar.gz
opencode-3ea2daaa4c1fef54c3e827300a63bd3b41b88806.zip
fix(tui): theme dialog visuals
-rw-r--r--packages/tui/internal/components/dialog/theme.go44
-rw-r--r--packages/tui/internal/components/list/list.go37
2 files changed, 48 insertions, 33 deletions
diff --git a/packages/tui/internal/components/dialog/theme.go b/packages/tui/internal/components/dialog/theme.go
index f00b8d1f0..eea3e74e7 100644
--- a/packages/tui/internal/components/dialog/theme.go
+++ b/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,
diff --git a/packages/tui/internal/components/list/list.go b/packages/tui/internal/components/list/list.go
index cd0bf18c0..c6ddbaf7e 100644
--- a/packages/tui/internal/components/list/list.go
+++ b/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)
+}