summaryrefslogtreecommitdiff
path: root/internal/tui/common
diff options
context:
space:
mode:
Diffstat (limited to 'internal/tui/common')
-rw-r--r--internal/tui/common/styles.go128
-rw-r--r--internal/tui/common/styles_test.go39
2 files changed, 132 insertions, 35 deletions
diff --git a/internal/tui/common/styles.go b/internal/tui/common/styles.go
index 06ed596..a71ef81 100644
--- a/internal/tui/common/styles.go
+++ b/internal/tui/common/styles.go
@@ -1,59 +1,117 @@
package common
-import "charm.land/lipgloss/v2"
+import (
+ "image/color"
+
+ "charm.land/lipgloss/v2"
+)
+
+// Palette defines themed colors shared across the TUI package.
+type Palette struct {
+ Background color.Color
+ Panel color.Color
+ Primary color.Color
+ Accent color.Color
+ Muted color.Color
+ Text color.Color
+ Danger color.Color
+}
+
+// NewPalette returns a color palette for dark or light terminal backgrounds.
+func NewPalette(isDark bool) Palette {
+ if isDark {
+ return Palette{
+ Background: lipgloss.Color("235"),
+ Panel: lipgloss.Color("238"),
+ Primary: lipgloss.Color("75"),
+ Accent: lipgloss.Color("222"),
+ Muted: lipgloss.Color("246"),
+ Text: lipgloss.Color("255"),
+ Danger: lipgloss.Color("203"),
+ }
+ }
+
+ return Palette{
+ Background: lipgloss.Color("255"),
+ Panel: lipgloss.Color("250"),
+ Primary: lipgloss.Color("26"),
+ Accent: lipgloss.Color("88"),
+ Muted: lipgloss.Color("242"),
+ Text: lipgloss.Color("235"),
+ Danger: lipgloss.Color("160"),
+ }
+}
var (
// Palette colors shared across the TUI package.
- ColorBackground = lipgloss.Color("235")
- ColorPanel = lipgloss.Color("238")
- ColorPrimary = lipgloss.Color("75")
- ColorAccent = lipgloss.Color("222")
- ColorMuted = lipgloss.Color("246")
- ColorText = lipgloss.Color("255")
- ColorDanger = lipgloss.Color("203")
+ ColorBackground color.Color
+ ColorPanel color.Color
+ ColorPrimary color.Color
+ ColorAccent color.Color
+ ColorMuted color.Color
+ ColorText color.Color
+ ColorDanger color.Color
)
var (
// ScreenStyle is the base style for full-screen models.
- ScreenStyle = lipgloss.NewStyle().
- Foreground(ColorText)
+ ScreenStyle lipgloss.Style
// HeaderStyle is used by top-level titles and screen headers.
- HeaderStyle = lipgloss.NewStyle().
- Bold(true).
- Foreground(ColorPrimary)
+ HeaderStyle lipgloss.Style
// TabActiveStyle is applied to the currently-selected tab.
- TabActiveStyle = lipgloss.NewStyle().
- Bold(true).
- Foreground(ColorBackground).
- Background(ColorPrimary).
- Padding(0, 1)
+ TabActiveStyle lipgloss.Style
// TabInactiveStyle is applied to non-selected tabs.
- TabInactiveStyle = lipgloss.NewStyle().
- Foreground(ColorMuted).
- Padding(0, 1)
+ TabInactiveStyle lipgloss.Style
// PanelStyle is used for boxed sections.
- PanelStyle = lipgloss.NewStyle().
- Border(lipgloss.NormalBorder()).
- BorderForeground(ColorPanel).
- Padding(0, 1)
+ PanelStyle lipgloss.Style
// HelpBarStyle is used for keybinding hints at the bottom.
- HelpBarStyle = lipgloss.NewStyle().
- Foreground(ColorMuted).
- BorderTop(true).
- BorderForeground(ColorPanel)
+ HelpBarStyle lipgloss.Style
// HighlightStyle emphasizes inline values.
- HighlightStyle = lipgloss.NewStyle().
- Bold(true).
- Foreground(ColorAccent)
+ HighlightStyle lipgloss.Style
// ErrorStyle is used for fatal or warning messages.
- ErrorStyle = lipgloss.NewStyle().
- Bold(true).
- Foreground(ColorDanger)
+ ErrorStyle lipgloss.Style
)
+
+// ApplyPalette updates shared colors and styles to match the provided theme.
+func ApplyPalette(isDark bool) {
+ palette := NewPalette(isDark)
+ ColorBackground = palette.Background
+ ColorPanel = palette.Panel
+ ColorPrimary = palette.Primary
+ ColorAccent = palette.Accent
+ ColorMuted = palette.Muted
+ ColorText = palette.Text
+ ColorDanger = palette.Danger
+
+ ScreenStyle = lipgloss.NewStyle().Foreground(ColorText)
+ HeaderStyle = lipgloss.NewStyle().Bold(true).Foreground(ColorPrimary)
+ TabActiveStyle = lipgloss.NewStyle().
+ Bold(true).
+ Foreground(ColorBackground).
+ Background(ColorPrimary).
+ Padding(0, 1)
+ TabInactiveStyle = lipgloss.NewStyle().
+ Foreground(ColorMuted).
+ Padding(0, 1)
+ PanelStyle = lipgloss.NewStyle().
+ Border(lipgloss.NormalBorder()).
+ BorderForeground(ColorPanel).
+ Padding(0, 1)
+ HelpBarStyle = lipgloss.NewStyle().
+ Foreground(ColorMuted).
+ BorderTop(true).
+ BorderForeground(ColorPanel)
+ HighlightStyle = lipgloss.NewStyle().Bold(true).Foreground(ColorAccent)
+ ErrorStyle = lipgloss.NewStyle().Bold(true).Foreground(ColorDanger)
+}
+
+func init() {
+ ApplyPalette(true)
+}
diff --git a/internal/tui/common/styles_test.go b/internal/tui/common/styles_test.go
new file mode 100644
index 0000000..c0900b3
--- /dev/null
+++ b/internal/tui/common/styles_test.go
@@ -0,0 +1,39 @@
+package common
+
+import (
+ "testing"
+
+ "charm.land/lipgloss/v2"
+)
+
+func TestNewPaletteRendersDistinctThemes(t *testing.T) {
+ dark := NewPalette(true)
+ light := NewPalette(false)
+
+ darkRender := lipgloss.NewStyle().
+ Foreground(dark.Text).
+ Background(dark.Background).
+ Render("ior")
+ lightRender := lipgloss.NewStyle().
+ Foreground(light.Text).
+ Background(light.Background).
+ Render("ior")
+
+ if darkRender == lightRender {
+ t.Fatalf("expected dark and light palettes to render differently")
+ }
+}
+
+func TestApplyPaletteUpdatesSharedStyles(t *testing.T) {
+ t.Cleanup(func() { ApplyPalette(true) })
+
+ ApplyPalette(true)
+ dark := ScreenStyle.Render("ior")
+
+ ApplyPalette(false)
+ light := ScreenStyle.Render("ior")
+
+ if dark == light {
+ t.Fatalf("expected ScreenStyle render to differ between dark and light palettes")
+ }
+}