feat(bar): add bar.background option for transparent top and bottom bars
- commit
- 60de5551af97145edad96df48d46b7c9cc487d15
- author
- brice · · 2026-10-08 08:42 UTC
- parent
- 0254710
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
7 files · +118 -5
M docs/configuration.md +3 -0
| @@ -78,6 +78,8 @@ snapshot.restore_processes = vi,vim,nvim,emacs,man,less,more,tail,top,htop,btop, | |||
| 78 | 78 | bar.top-right = | |
| 79 | 79 | bar.bottom-right = | |
| 80 | 80 | bar.interval = 5s | |
| 81 | + | # Fill the top and bottom bars with the theme surface; off keeps the terminal background. | |
| 82 | + | bar.background = on | |
| 81 | 83 | ||
| 82 | 84 | # Command palette codes: 2-3 letters or digits. | |
| 83 | 85 | code.new-tab = CNT | |
| @@ -215,6 +217,7 @@ If the daemon refuses to start because its session data is broken, do not edit t | |||
| 215 | 217 | | `theme.palette = off` | Neutral colors, no accent. | | |
| 216 | 218 | | `theme.accent = auto` | Pick an accent from your terminal's ANSI colors (blue if unsure). | | |
| 217 | 219 | | `theme.accent = 0`–`15` | Use exactly that ANSI color as the accent. | | |
| 220 | + | | `bar.background = off` | Keep the terminal background behind the top and bottom bars (useful with a transparent terminal). Tabs and recent sessions keep their colors. | | |
| 218 | 221 | ||
| 219 | 222 | - vev only colors its own UI (bars, borders, palette). Pane content is never recolored. | |
| 220 | 223 | - Tinted backgrounds need a truecolor or 256-color terminal. On 16-color and monochrome terminals vev uses bold, reverse, and faint instead. See [terminal colors](terminal.md#colors). | |
| @@ -78,6 +78,8 @@ snapshot.restore_processes = vi,vim,nvim,emacs,man,less,more,tail,top,htop,btop, | |||||
| 78 | bar.top-right = | 78 | bar.top-right = | ||
| 79 | bar.bottom-right = | 79 | bar.bottom-right = | ||
| 80 | bar.interval = 5s | 80 | bar.interval = 5s | ||
| 81 | + | # Fill the top and bottom bars with the theme surface; off keeps the terminal background. | |||
| 82 | + | bar.background = on | |||
| 81 | 83 | ||||
| 82 | # Command palette codes: 2-3 letters or digits. | 84 | # Command palette codes: 2-3 letters or digits. | ||
| 83 | code.new-tab = CNT | 85 | code.new-tab = CNT | ||
| @@ -215,6 +217,7 @@ If the daemon refuses to start because its session data is broken, do not edit t | |||||
| 215 | | `theme.palette = off` | Neutral colors, no accent. | | 217 | | `theme.palette = off` | Neutral colors, no accent. | | ||
| 216 | | `theme.accent = auto` | Pick an accent from your terminal's ANSI colors (blue if unsure). | | 218 | | `theme.accent = auto` | Pick an accent from your terminal's ANSI colors (blue if unsure). | | ||
| 217 | | `theme.accent = 0`–`15` | Use exactly that ANSI color as the accent. | | 219 | | `theme.accent = 0`–`15` | Use exactly that ANSI color as the accent. | | ||
| 220 | + | | `bar.background = off` | Keep the terminal background behind the top and bottom bars (useful with a transparent terminal). Tabs and recent sessions keep their colors. | | |||
| 218 | 221 | ||||
| 219 | - vev only colors its own UI (bars, borders, palette). Pane content is never recolored. | 222 | - vev only colors its own UI (bars, borders, palette). Pane content is never recolored. | ||
| 220 | - Tinted backgrounds need a truecolor or 256-color terminal. On 16-color and monochrome terminals vev uses bold, reverse, and faint instead. See [terminal colors](terminal.md#colors). | 223 | - Tinted backgrounds need a truecolor or 256-color terminal. On 16-color and monochrome terminals vev uses bold, reverse, and faint instead. See [terminal colors](terminal.md#colors). | ||
M internal/adapters/config/config.go +7 -0
| @@ -122,6 +122,13 @@ func Parse(r io.Reader) (domain.Config, []domain.Warning, error) { | |||
| 122 | 122 | interval = domain.MinBarInterval | |
| 123 | 123 | } | |
| 124 | 124 | cfg.Bar.Interval = interval | |
| 125 | + | case key == "bar.background": | |
| 126 | + | on, ok := parseOnOff(value) | |
| 127 | + | if !ok { | |
| 128 | + | warnings = append(warnings, domain.Warning{Line: lineNo, Msg: fmt.Sprintf("invalid bar.background %q", value)}) | |
| 129 | + | continue | |
| 130 | + | } | |
| 131 | + | cfg.Bar.Transparent = !on | |
| 125 | 132 | case key == "palette.anchor": | |
| 126 | 133 | warnings = warnDuplicateKey(warnings, seenPaletteKeys, key, lineNo) | |
| 127 | 134 | if strings.EqualFold(strings.TrimSpace(value), "auto") { | |
| @@ -122,6 +122,13 @@ func Parse(r io.Reader) (domain.Config, []domain.Warning, error) { | |||||
| 122 | interval = domain.MinBarInterval | 122 | interval = domain.MinBarInterval | ||
| 123 | } | 123 | } | ||
| 124 | cfg.Bar.Interval = interval | 124 | cfg.Bar.Interval = interval | ||
| 125 | + | case key == "bar.background": | |||
| 126 | + | on, ok := parseOnOff(value) | |||
| 127 | + | if !ok { | |||
| 128 | + | warnings = append(warnings, domain.Warning{Line: lineNo, Msg: fmt.Sprintf("invalid bar.background %q", value)}) | |||
| 129 | + | continue | |||
| 130 | + | } | |||
| 131 | + | cfg.Bar.Transparent = !on | |||
| 125 | case key == "palette.anchor": | 132 | case key == "palette.anchor": | ||
| 126 | warnings = warnDuplicateKey(warnings, seenPaletteKeys, key, lineNo) | 133 | warnings = warnDuplicateKey(warnings, seenPaletteKeys, key, lineNo) | ||
| 127 | if strings.EqualFold(strings.TrimSpace(value), "auto") { | 134 | if strings.EqualFold(strings.TrimSpace(value), "auto") { | ||
M internal/adapters/config/config_test.go +33 -0
| @@ -428,6 +428,39 @@ func TestParseThemePalette(t *testing.T) { | |||
| 428 | 428 | } | |
| 429 | 429 | } | |
| 430 | 430 | ||
| 431 | + | func TestParseBarBackground(t *testing.T) { | |
| 432 | + | t.Parallel() | |
| 433 | + | ||
| 434 | + | tests := []struct { | |
| 435 | + | name string | |
| 436 | + | input string | |
| 437 | + | wantTransparent bool | |
| 438 | + | wantWarnings []domain.Warning | |
| 439 | + | }{ | |
| 440 | + | {name: "on keeps the theme surface", input: "bar.background = on\n"}, | |
| 441 | + | {name: "off makes bars transparent", input: "bar.background = off\n", wantTransparent: true}, | |
| 442 | + | { | |
| 443 | + | name: "invalid value warns and keeps default", | |
| 444 | + | input: "bar.background = none\n", | |
| 445 | + | wantWarnings: []domain.Warning{ | |
| 446 | + | {Line: 1, Msg: "invalid bar.background \"none\""}, | |
| 447 | + | }, | |
| 448 | + | }, | |
| 449 | + | {name: "absent key keeps default", input: "bar.interval = 2s\n"}, | |
| 450 | + | } | |
| 451 | + | ||
| 452 | + | for _, tt := range tests { | |
| 453 | + | t.Run(tt.name, func(t *testing.T) { | |
| 454 | + | t.Parallel() | |
| 455 | + | ||
| 456 | + | got, warnings, err := Parse(strings.NewReader(tt.input)) | |
| 457 | + | require.NoError(t, err) | |
| 458 | + | require.Equal(t, tt.wantTransparent, got.Bar.Transparent) | |
| 459 | + | require.Equal(t, tt.wantWarnings, warnings) | |
| 460 | + | }) | |
| 461 | + | } | |
| 462 | + | } | |
| 463 | + | ||
| 431 | 464 | func TestDefaultsThemePalette(t *testing.T) { | |
| 432 | 465 | t.Parallel() | |
| 433 | 466 | ||
| @@ -428,6 +428,39 @@ func TestParseThemePalette(t *testing.T) { | |||||
| 428 | } | 428 | } | ||
| 429 | } | 429 | } | ||
| 430 | 430 | ||||
| 431 | + | func TestParseBarBackground(t *testing.T) { | |||
| 432 | + | t.Parallel() | |||
| 433 | + | ||||
| 434 | + | tests := []struct { | |||
| 435 | + | name string | |||
| 436 | + | input string | |||
| 437 | + | wantTransparent bool | |||
| 438 | + | wantWarnings []domain.Warning | |||
| 439 | + | }{ | |||
| 440 | + | {name: "on keeps the theme surface", input: "bar.background = on\n"}, | |||
| 441 | + | {name: "off makes bars transparent", input: "bar.background = off\n", wantTransparent: true}, | |||
| 442 | + | { | |||
| 443 | + | name: "invalid value warns and keeps default", | |||
| 444 | + | input: "bar.background = none\n", | |||
| 445 | + | wantWarnings: []domain.Warning{ | |||
| 446 | + | {Line: 1, Msg: "invalid bar.background \"none\""}, | |||
| 447 | + | }, | |||
| 448 | + | }, | |||
| 449 | + | {name: "absent key keeps default", input: "bar.interval = 2s\n"}, | |||
| 450 | + | } | |||
| 451 | + | ||||
| 452 | + | for _, tt := range tests { | |||
| 453 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 454 | + | t.Parallel() | |||
| 455 | + | ||||
| 456 | + | got, warnings, err := Parse(strings.NewReader(tt.input)) | |||
| 457 | + | require.NoError(t, err) | |||
| 458 | + | require.Equal(t, tt.wantTransparent, got.Bar.Transparent) | |||
| 459 | + | require.Equal(t, tt.wantWarnings, warnings) | |||
| 460 | + | }) | |||
| 461 | + | } | |||
| 462 | + | } | |||
| 463 | + | ||||
| 431 | func TestDefaultsThemePalette(t *testing.T) { | 464 | func TestDefaultsThemePalette(t *testing.T) { | ||
| 432 | t.Parallel() | 465 | t.Parallel() | ||
| 433 | 466 | ||||
M internal/domain/config.go +4 -1
| @@ -47,11 +47,14 @@ func DefaultSnapshotRestoreProcesses() []string { | |||
| 47 | 47 | return append([]string(nil), defaultSnapshotRestoreProcesses...) | |
| 48 | 48 | } | |
| 49 | 49 | ||
| 50 | - | // BarConfig contains user-configurable bar right-anchor settings. | |
| 50 | + | // BarConfig contains user-configurable bar settings. | |
| 51 | 51 | type BarConfig struct { | |
| 52 | 52 | TopRight string | |
| 53 | 53 | BottomRight string | |
| 54 | 54 | Interval time.Duration | |
| 55 | + | // Transparent keeps the terminal background behind the top and bottom | |
| 56 | + | // bars instead of the theme surface color (bar.background = off). | |
| 57 | + | Transparent bool | |
| 55 | 58 | } | |
| 56 | 59 | ||
| 57 | 60 | // CopyConfig contains copy-mode selection and mouse motion settings. | |
| @@ -47,11 +47,14 @@ func DefaultSnapshotRestoreProcesses() []string { | |||||
| 47 | return append([]string(nil), defaultSnapshotRestoreProcesses...) | 47 | return append([]string(nil), defaultSnapshotRestoreProcesses...) | ||
| 48 | } | 48 | } | ||
| 49 | 49 | ||||
| 50 | - | // BarConfig contains user-configurable bar right-anchor settings. | 50 | + | // BarConfig contains user-configurable bar settings. |
| 51 | type BarConfig struct { | 51 | type BarConfig struct { | ||
| 52 | TopRight string | 52 | TopRight string | ||
| 53 | BottomRight string | 53 | BottomRight string | ||
| 54 | Interval time.Duration | 54 | Interval time.Duration | ||
| 55 | + | // Transparent keeps the terminal background behind the top and bottom | |||
| 56 | + | // bars instead of the theme surface color (bar.background = off). | |||
| 57 | + | Transparent bool | |||
| 55 | } | 58 | } | ||
| 56 | 59 | ||||
| 57 | // CopyConfig contains copy-mode selection and mouse motion settings. | 60 | // CopyConfig contains copy-mode selection and mouse motion settings. | ||
A internal/usecase/daemon/bar_background_test.go +55 -0
| @@ -0,0 +1,55 @@ | |||
| 1 | + | package daemon | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "testing" | |
| 5 | + | ||
| 6 | + | "github.com/stretchr/testify/require" | |
| 7 | + | ||
| 8 | + | renderer "github.com/bnema/vev-vt" | |
| 9 | + | "github.com/bnema/vev/internal/domain" | |
| 10 | + | "github.com/bnema/vev/internal/domain/terminalcap" | |
| 11 | + | themeui "github.com/bnema/vev/internal/usecase/theme" | |
| 12 | + | ) | |
| 13 | + | ||
| 14 | + | func TestBarBackgroundConfigResolvesBarSurface(t *testing.T) { | |
| 15 | + | paletteColors := [16]renderer.RGB{} | |
| 16 | + | paletteColors[4] = renderer.RGB{R: 40, G: 90, B: 220} | |
| 17 | + | raw := themeui.Theme{ | |
| 18 | + | Foreground: renderer.RGB{R: 230, G: 230, B: 230}, Background: renderer.RGB{R: 8, G: 9, B: 10}, | |
| 19 | + | HasFG: true, HasBG: true, Known: true, UsePalette: true, | |
| 20 | + | Palette: paletteColors, PaletteKnown: 1 << 4, | |
| 21 | + | } | |
| 22 | + | ||
| 23 | + | tests := []struct { | |
| 24 | + | name string | |
| 25 | + | transparent bool | |
| 26 | + | color terminalcap.ColorCapabilities | |
| 27 | + | }{ | |
| 28 | + | {name: "truecolor themed", color: terminalcap.ColorCapabilities{Mode: terminalcap.TrueColor}}, | |
| 29 | + | {name: "truecolor transparent", transparent: true, color: terminalcap.ColorCapabilities{Mode: terminalcap.TrueColor}}, | |
| 30 | + | {name: "ansi16 transparent", transparent: true, color: terminalcap.ColorCapabilities{Mode: terminalcap.ANSI16}}, | |
| 31 | + | } | |
| 32 | + | for _, tt := range tests { | |
| 33 | + | t.Run(tt.name, func(t *testing.T) { | |
| 34 | + | cfg := domain.Defaults() | |
| 35 | + | cfg.Bar.Transparent = tt.transparent | |
| 36 | + | d := newTestDaemon(t, nil, stubClock{}) | |
| 37 | + | d.ApplyConfig(cfg) | |
| 38 | + | ||
| 39 | + | themed := themeui.ResolveForColor(raw, cfg.ThemeAccent, tt.color).Styles | |
| 40 | + | got := d.resolveAppliedTheme(raw, tt.color).Resolved.Styles | |
| 41 | + | ||
| 42 | + | if tt.transparent { | |
| 43 | + | require.True(t, got.SurfaceBar.Equal(renderer.DefaultStyle()), "bar fill uses the terminal background") | |
| 44 | + | } else { | |
| 45 | + | require.True(t, got.SurfaceBar.Equal(themed.SurfaceBar)) | |
| 46 | + | } | |
| 47 | + | // Every other role keeps its theme colors. | |
| 48 | + | require.True(t, got.SurfaceInactive.Equal(themed.SurfaceInactive)) | |
| 49 | + | require.True(t, got.TabActive.Equal(themed.TabActive)) | |
| 50 | + | require.True(t, got.MRUStyle(0, 2).Equal(themed.MRUStyle(0, 2))) | |
| 51 | + | require.True(t, got.CopyStatus.Equal(themed.CopyStatus)) | |
| 52 | + | require.True(t, got.StatusBar.Equal(themed.StatusBar)) | |
| 53 | + | }) | |
| 54 | + | } | |
| 55 | + | } | |
| @@ -0,0 +1,55 @@ | |||||
| 1 | + | package daemon | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "testing" | |||
| 5 | + | ||||
| 6 | + | "github.com/stretchr/testify/require" | |||
| 7 | + | ||||
| 8 | + | renderer "github.com/bnema/vev-vt" | |||
| 9 | + | "github.com/bnema/vev/internal/domain" | |||
| 10 | + | "github.com/bnema/vev/internal/domain/terminalcap" | |||
| 11 | + | themeui "github.com/bnema/vev/internal/usecase/theme" | |||
| 12 | + | ) | |||
| 13 | + | ||||
| 14 | + | func TestBarBackgroundConfigResolvesBarSurface(t *testing.T) { | |||
| 15 | + | paletteColors := [16]renderer.RGB{} | |||
| 16 | + | paletteColors[4] = renderer.RGB{R: 40, G: 90, B: 220} | |||
| 17 | + | raw := themeui.Theme{ | |||
| 18 | + | Foreground: renderer.RGB{R: 230, G: 230, B: 230}, Background: renderer.RGB{R: 8, G: 9, B: 10}, | |||
| 19 | + | HasFG: true, HasBG: true, Known: true, UsePalette: true, | |||
| 20 | + | Palette: paletteColors, PaletteKnown: 1 << 4, | |||
| 21 | + | } | |||
| 22 | + | ||||
| 23 | + | tests := []struct { | |||
| 24 | + | name string | |||
| 25 | + | transparent bool | |||
| 26 | + | color terminalcap.ColorCapabilities | |||
| 27 | + | }{ | |||
| 28 | + | {name: "truecolor themed", color: terminalcap.ColorCapabilities{Mode: terminalcap.TrueColor}}, | |||
| 29 | + | {name: "truecolor transparent", transparent: true, color: terminalcap.ColorCapabilities{Mode: terminalcap.TrueColor}}, | |||
| 30 | + | {name: "ansi16 transparent", transparent: true, color: terminalcap.ColorCapabilities{Mode: terminalcap.ANSI16}}, | |||
| 31 | + | } | |||
| 32 | + | for _, tt := range tests { | |||
| 33 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 34 | + | cfg := domain.Defaults() | |||
| 35 | + | cfg.Bar.Transparent = tt.transparent | |||
| 36 | + | d := newTestDaemon(t, nil, stubClock{}) | |||
| 37 | + | d.ApplyConfig(cfg) | |||
| 38 | + | ||||
| 39 | + | themed := themeui.ResolveForColor(raw, cfg.ThemeAccent, tt.color).Styles | |||
| 40 | + | got := d.resolveAppliedTheme(raw, tt.color).Resolved.Styles | |||
| 41 | + | ||||
| 42 | + | if tt.transparent { | |||
| 43 | + | require.True(t, got.SurfaceBar.Equal(renderer.DefaultStyle()), "bar fill uses the terminal background") | |||
| 44 | + | } else { | |||
| 45 | + | require.True(t, got.SurfaceBar.Equal(themed.SurfaceBar)) | |||
| 46 | + | } | |||
| 47 | + | // Every other role keeps its theme colors. | |||
| 48 | + | require.True(t, got.SurfaceInactive.Equal(themed.SurfaceInactive)) | |||
| 49 | + | require.True(t, got.TabActive.Equal(themed.TabActive)) | |||
| 50 | + | require.True(t, got.MRUStyle(0, 2).Equal(themed.MRUStyle(0, 2))) | |||
| 51 | + | require.True(t, got.CopyStatus.Equal(themed.CopyStatus)) | |||
| 52 | + | require.True(t, got.StatusBar.Equal(themed.StatusBar)) | |||
| 53 | + | }) | |||
| 54 | + | } | |||
| 55 | + | } | |||
M internal/usecase/daemon/config.go +8 -4
| @@ -21,9 +21,10 @@ var commandCodePattern = regexp.MustCompile(`^[A-Z0-9]{2,3}$`) | |||
| 21 | 21 | // themeConfigSnapshot is the theme slice of runtimeConfig. Its zero value is | |
| 22 | 22 | // the default theme configuration: automatic mode with palette inheritance on. | |
| 23 | 23 | type themeConfigSnapshot struct { | |
| 24 | - | mode domain.ThemeMode | |
| 25 | - | paletteOff bool | |
| 26 | - | accent domain.ThemeAccent | |
| 24 | + | mode domain.ThemeMode | |
| 25 | + | paletteOff bool | |
| 26 | + | accent domain.ThemeAccent | |
| 27 | + | barTransparent bool | |
| 27 | 28 | } | |
| 28 | 29 | ||
| 29 | 30 | // runtimeConfig is the immutable derived configuration published by | |
| @@ -96,7 +97,7 @@ func (d *Daemon) ApplyConfig(cfg domain.Config) { | |||
| 96 | 97 | tabs: cfg.Tabs, | |
| 97 | 98 | ephemeral: cfg.Ephemeral, | |
| 98 | 99 | scrollback: scrollback, | |
| 99 | - | theme: themeConfigSnapshot{mode: cfg.Theme, paletteOff: !cfg.ThemePalette, accent: cfg.ThemeAccent}, | |
| 100 | + | theme: themeConfigSnapshot{mode: cfg.Theme, paletteOff: !cfg.ThemePalette, accent: cfg.ThemeAccent, barTransparent: cfg.Bar.Transparent}, | |
| 100 | 101 | } | |
| 101 | 102 | d.bindings.Store(bindings) | |
| 102 | 103 | d.config.Store(snapshot) | |
| @@ -359,6 +360,9 @@ func (d *Daemon) resolveAppliedTheme(raw theme.Theme, color terminalcap.ColorCap | |||
| 359 | 360 | config := d.currentThemeConfig() | |
| 360 | 361 | effective := effectiveThemeForConfig(raw, config) | |
| 361 | 362 | resolved := theme.ResolveForColor(effective, config.accent, color) | |
| 363 | + | if config.barTransparent { | |
| 364 | + | resolved.Styles = resolved.Styles.WithTransparentBar() | |
| 365 | + | } | |
| 362 | 366 | return appliedTheme{Raw: resolved.Theme, Resolved: resolved} | |
| 363 | 367 | } | |
| 364 | 368 | ||
| @@ -21,9 +21,10 @@ var commandCodePattern = regexp.MustCompile(`^[A-Z0-9]{2,3}$`) | |||||
| 21 | // themeConfigSnapshot is the theme slice of runtimeConfig. Its zero value is | 21 | // themeConfigSnapshot is the theme slice of runtimeConfig. Its zero value is | ||
| 22 | // the default theme configuration: automatic mode with palette inheritance on. | 22 | // the default theme configuration: automatic mode with palette inheritance on. | ||
| 23 | type themeConfigSnapshot struct { | 23 | type themeConfigSnapshot struct { | ||
| 24 | - | mode domain.ThemeMode | 24 | + | mode domain.ThemeMode |
| 25 | - | paletteOff bool | 25 | + | paletteOff bool |
| 26 | - | accent domain.ThemeAccent | 26 | + | accent domain.ThemeAccent |
| 27 | + | barTransparent bool | |||
| 27 | } | 28 | } | ||
| 28 | 29 | ||||
| 29 | // runtimeConfig is the immutable derived configuration published by | 30 | // runtimeConfig is the immutable derived configuration published by | ||
| @@ -96,7 +97,7 @@ func (d *Daemon) ApplyConfig(cfg domain.Config) { | |||||
| 96 | tabs: cfg.Tabs, | 97 | tabs: cfg.Tabs, | ||
| 97 | ephemeral: cfg.Ephemeral, | 98 | ephemeral: cfg.Ephemeral, | ||
| 98 | scrollback: scrollback, | 99 | scrollback: scrollback, | ||
| 99 | - | theme: themeConfigSnapshot{mode: cfg.Theme, paletteOff: !cfg.ThemePalette, accent: cfg.ThemeAccent}, | 100 | + | theme: themeConfigSnapshot{mode: cfg.Theme, paletteOff: !cfg.ThemePalette, accent: cfg.ThemeAccent, barTransparent: cfg.Bar.Transparent}, |
| 100 | } | 101 | } | ||
| 101 | d.bindings.Store(bindings) | 102 | d.bindings.Store(bindings) | ||
| 102 | d.config.Store(snapshot) | 103 | d.config.Store(snapshot) | ||
| @@ -359,6 +360,9 @@ func (d *Daemon) resolveAppliedTheme(raw theme.Theme, color terminalcap.ColorCap | |||||
| 359 | config := d.currentThemeConfig() | 360 | config := d.currentThemeConfig() | ||
| 360 | effective := effectiveThemeForConfig(raw, config) | 361 | effective := effectiveThemeForConfig(raw, config) | ||
| 361 | resolved := theme.ResolveForColor(effective, config.accent, color) | 362 | resolved := theme.ResolveForColor(effective, config.accent, color) | ||
| 363 | + | if config.barTransparent { | |||
| 364 | + | resolved.Styles = resolved.Styles.WithTransparentBar() | |||
| 365 | + | } | |||
| 362 | return appliedTheme{Raw: resolved.Theme, Resolved: resolved} | 366 | return appliedTheme{Raw: resolved.Theme, Resolved: resolved} | ||
| 363 | } | 367 | } | ||
| 364 | 368 | ||||
M internal/usecase/theme/styles.go +8 -0
| @@ -127,6 +127,14 @@ type Styles struct { | |||
| 127 | 127 | PickerSelectionMuted renderer.Style | |
| 128 | 128 | } | |
| 129 | 129 | ||
| 130 | + | // WithTransparentBar returns s with the top and bottom bar fill on the | |
| 131 | + | // terminal's default colors. Tabs, MRU entries, and every other role keep | |
| 132 | + | // their theme colors. | |
| 133 | + | func (s Styles) WithTransparentBar() Styles { | |
| 134 | + | s.SurfaceBar = renderer.DefaultStyle() | |
| 135 | + | return s | |
| 136 | + | } | |
| 137 | + | ||
| 130 | 138 | // NewStyles applies the default automatic policy. New callers that own a | |
| 131 | 139 | // policy should use Resolve and retain its complete immutable result. | |
| 132 | 140 | func NewStyles(t Theme) Styles { | |
| @@ -127,6 +127,14 @@ type Styles struct { | |||||
| 127 | PickerSelectionMuted renderer.Style | 127 | PickerSelectionMuted renderer.Style | ||
| 128 | } | 128 | } | ||
| 129 | 129 | ||||
| 130 | + | // WithTransparentBar returns s with the top and bottom bar fill on the | |||
| 131 | + | // terminal's default colors. Tabs, MRU entries, and every other role keep | |||
| 132 | + | // their theme colors. | |||
| 133 | + | func (s Styles) WithTransparentBar() Styles { | |||
| 134 | + | s.SurfaceBar = renderer.DefaultStyle() | |||
| 135 | + | return s | |||
| 136 | + | } | |||
| 137 | + | ||||
| 130 | // NewStyles applies the default automatic policy. New callers that own a | 138 | // NewStyles applies the default automatic policy. New callers that own a | ||
| 131 | // policy should use Resolve and retain its complete immutable result. | 139 | // policy should use Resolve and retain its complete immutable result. | ||
| 132 | func NewStyles(t Theme) Styles { | 140 | func NewStyles(t Theme) Styles { | ||