Show a colour-coded team picker instead of cycling with T
T used to silently cycle Model.activeTeamID through the caller's teams with no visible list of choices. It now opens a full picker (modelled on the existing user picker) listing every team plus "All teams", each with a stable identity colour from a new six-colour theme palette. The same colour now also shows as a bullet next to "team: <name>" in the header, so the active team stays visible without opening the picker. Adds an Identity palette to the theme package (six hues, skipping the ones that already mean firing/critical), Styles.TeamColor to pick one by team id, and identity_1..6 as theme-file tokens alongside the existing twelve so a fully custom theme can still set every token.
This commit is contained in:
+30
-19
@@ -1,30 +1,36 @@
|
||||
package theme
|
||||
|
||||
import "sort"
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
// The gruvbox palettes, in the author's original names. Dark uses the bright
|
||||
// variants and light the faded ones, which is what keeps each readable against
|
||||
// its own background.
|
||||
const (
|
||||
darkBg0 = "#282828"
|
||||
darkFg1 = "#ebdbb2"
|
||||
darkGray = "#928374"
|
||||
darkRed = "#fb4934"
|
||||
darkGrn = "#b8bb26"
|
||||
darkYel = "#fabd2f"
|
||||
darkBlu = "#83a598"
|
||||
darkAqua = "#8ec07c"
|
||||
darkOrng = "#fe8019"
|
||||
darkBg0 = "#282828"
|
||||
darkFg1 = "#ebdbb2"
|
||||
darkGray = "#928374"
|
||||
darkRed = "#fb4934"
|
||||
darkGrn = "#b8bb26"
|
||||
darkYel = "#fabd2f"
|
||||
darkBlu = "#83a598"
|
||||
darkAqua = "#8ec07c"
|
||||
darkOrng = "#fe8019"
|
||||
darkPurple = "#d3869b"
|
||||
|
||||
lightBg0 = "#fbf1c7"
|
||||
lightFg1 = "#3c3836"
|
||||
lightFg4 = "#7c6f64"
|
||||
lightRed = "#9d0006"
|
||||
lightGrn = "#79740e"
|
||||
lightYel = "#b57614"
|
||||
lightBlu = "#076678"
|
||||
lightAqua = "#427b58"
|
||||
lightOrng = "#af3a03"
|
||||
lightBg0 = "#fbf1c7"
|
||||
lightFg1 = "#3c3836"
|
||||
lightFg4 = "#7c6f64"
|
||||
lightRed = "#9d0006"
|
||||
lightGrn = "#79740e"
|
||||
lightYel = "#b57614"
|
||||
lightBlu = "#076678"
|
||||
lightAqua = "#427b58"
|
||||
lightOrng = "#af3a03"
|
||||
lightPurple = "#8f3f71"
|
||||
)
|
||||
|
||||
// GruvboxDark is the default scheme. It assumes a dark terminal background:
|
||||
@@ -46,6 +52,9 @@ var GruvboxDark = Theme{
|
||||
SevError: darkOrng,
|
||||
SevWarning: darkYel,
|
||||
SevInfo: darkAqua,
|
||||
|
||||
// Red already means an alarm, so it is the one gruvbox hue left out here.
|
||||
Identity: [6]lipgloss.Color{darkBlu, darkAqua, darkYel, darkGrn, darkOrng, darkPurple},
|
||||
}
|
||||
|
||||
// GruvboxLight is the same scheme against a light terminal background.
|
||||
@@ -66,6 +75,8 @@ var GruvboxLight = Theme{
|
||||
SevError: lightOrng,
|
||||
SevWarning: lightYel,
|
||||
SevInfo: lightAqua,
|
||||
|
||||
Identity: [6]lipgloss.Color{lightBlu, lightAqua, lightYel, lightGrn, lightOrng, lightPurple},
|
||||
}
|
||||
|
||||
// Default is the theme used when the config names none.
|
||||
|
||||
@@ -32,6 +32,13 @@ type rawTheme struct {
|
||||
SevError *string `yaml:"sev_error"`
|
||||
SevWarning *string `yaml:"sev_warning"`
|
||||
SevInfo *string `yaml:"sev_info"`
|
||||
|
||||
Identity1 *string `yaml:"identity_1"`
|
||||
Identity2 *string `yaml:"identity_2"`
|
||||
Identity3 *string `yaml:"identity_3"`
|
||||
Identity4 *string `yaml:"identity_4"`
|
||||
Identity5 *string `yaml:"identity_5"`
|
||||
Identity6 *string `yaml:"identity_6"`
|
||||
}
|
||||
|
||||
// binding ties a YAML key to its raw value and the field it fills, so parsing,
|
||||
@@ -56,6 +63,12 @@ func bindings(r *rawTheme, t *Theme) []binding {
|
||||
{"sev_error", r.SevError, &t.SevError},
|
||||
{"sev_warning", r.SevWarning, &t.SevWarning},
|
||||
{"sev_info", r.SevInfo, &t.SevInfo},
|
||||
{"identity_1", r.Identity1, &t.Identity[0]},
|
||||
{"identity_2", r.Identity2, &t.Identity[1]},
|
||||
{"identity_3", r.Identity3, &t.Identity[2]},
|
||||
{"identity_4", r.Identity4, &t.Identity[3]},
|
||||
{"identity_5", r.Identity5, &t.Identity[4]},
|
||||
{"identity_6", r.Identity6, &t.Identity[5]},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,12 @@ sev_critical: "#000009"
|
||||
sev_error: "#00000a"
|
||||
sev_warning: "#00000b"
|
||||
sev_info: "#00000c"
|
||||
identity_1: "#00000d"
|
||||
identity_2: "#00000e"
|
||||
identity_3: "#00000f"
|
||||
identity_4: "#000010"
|
||||
identity_5: "#000011"
|
||||
identity_6: "#000012"
|
||||
`)
|
||||
|
||||
got, err := loadFrom(dir, "full")
|
||||
@@ -115,6 +121,9 @@ sev_info: "#00000c"
|
||||
if got.Primary != "#000001" || got.SevInfo != "#00000c" {
|
||||
t.Errorf("tokens not applied: %+v", got)
|
||||
}
|
||||
if got.Identity[0] != "#00000d" || got.Identity[5] != "#000012" {
|
||||
t.Errorf("identity tokens not applied: %+v", got.Identity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFrom_Errors(t *testing.T) {
|
||||
|
||||
@@ -29,4 +29,8 @@ type Theme struct {
|
||||
SevError lipgloss.Color
|
||||
SevWarning lipgloss.Color
|
||||
SevInfo lipgloss.Color
|
||||
|
||||
// Identity tells things like teams apart from one another — not a status
|
||||
// or a severity, so none of the six carries a meaning of its own.
|
||||
Identity [6]lipgloss.Color
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user