diff --git a/go/display/tui/style/color.go b/go/display/tui/style/color.go index d075f17..a3951bb 100644 --- a/go/display/tui/style/color.go +++ b/go/display/tui/style/color.go @@ -21,3 +21,21 @@ type LightDark = lipgloss.LightDarkFunc // NewLightDark builds a LightDark chooser for the given background. func NewLightDark(isDark bool) LightDark { return lipgloss.LightDark(isDark) } + +// AdaptiveColor pairs a light-background and a dark-background colour for one +// role, resolved once the terminal background is known — the render-time +// replacement for lipgloss v1's implicit adaptation, which v2 removed. A theme +// keeps the pair as data and resolves it per frame, e.g. +// +// accent := style.AdaptiveColor{Light: "#2e5cc5", Dark: "#7aa2f7"} +// st := style.New().Foreground(accent.Resolve(isDark)) +type AdaptiveColor struct { + Light, Dark string +} + +// Resolve returns the Light Paint on a light terminal and the Dark Paint on a +// dark one, delegating to NewLightDark so it matches every other light/dark +// choice in the package. +func (a AdaptiveColor) Resolve(isDark bool) Paint { + return NewLightDark(isDark)(Color(a.Light), Color(a.Dark)) +} diff --git a/go/display/tui/style/color_test.go b/go/display/tui/style/color_test.go new file mode 100644 index 0000000..9d2acb2 --- /dev/null +++ b/go/display/tui/style/color_test.go @@ -0,0 +1,33 @@ +package style_test + +import ( + "testing" + + "dappco.re/go/html/display/tui/style" +) + +func TestAdaptiveColor_Resolve_PicksDarkOnADarkTerminal(t *testing.T) { + c := style.AdaptiveColor{Light: "#000000", Dark: "#ffffff"} + + r, g, b, _ := c.Resolve(true).RGBA() + if r != 0xffff || g != 0xffff || b != 0xffff { + t.Fatalf("Resolve(isDark=true) = %d,%d,%d, want the Dark colour white (65535,65535,65535)", r, g, b) + } +} + +func TestAdaptiveColor_Resolve_PicksLightOnALightTerminal(t *testing.T) { + c := style.AdaptiveColor{Light: "#000000", Dark: "#ffffff"} + + r, g, b, _ := c.Resolve(false).RGBA() + if r != 0 || g != 0 || b != 0 { + t.Fatalf("Resolve(isDark=false) = %d,%d,%d, want the Light colour black (0,0,0)", r, g, b) + } +} + +func TestAdaptiveColor_Resolve_ZeroValueResolvesWithoutPanicking(t *testing.T) { + var c style.AdaptiveColor // both fields empty — an unset theme role + + if got := c.Resolve(true); got == nil { + t.Fatal("Resolve on a zero AdaptiveColor returned a nil Paint, want a non-nil no-colour") + } +} diff --git a/go/display/tui/style/example_test.go b/go/display/tui/style/example_test.go index cd03791..9849e4c 100644 --- a/go/display/tui/style/example_test.go +++ b/go/display/tui/style/example_test.go @@ -32,3 +32,15 @@ func ExampleBlend1D() { // Output: // true } + +// ExampleAdaptiveColor_Resolve keeps one light/dark colour pair and resolves it +// for a dark terminal — the per-frame replacement for lipgloss v1's implicit +// AdaptiveColor, which v2 removed. +func ExampleAdaptiveColor_Resolve() { + accent := style.AdaptiveColor{Light: "#000000", Dark: "#ffffff"} + + r, g, b, _ := accent.Resolve(true).RGBA() + fmt.Printf("%d %d %d\n", r, g, b) + // Output: + // 65535 65535 65535 +}