feat(appearance): left stripe by default, with fill and strength as choices

The first version filled the whole row at 24%, and in a real log that meant
every row was painted: nearly every contact has SOME QSL state, so colour was
present everywhere and stopped being information — a striped background with
the data behind it.

The default is now a 3px stripe down the left edge. Same signal, nothing lost
to read it. A filled row is still offered, with a strength slider, for
operators who want the block — and the rule cards in Settings preview whichever
is chosen, so the decision is made by looking rather than by imagining.

Drawn as an inset shadow rather than a border: a border would shift the cells
three pixels on coloured rows only, and the columns would stop lining up.

Style and strength are normalised rather than rejected — a value out of range
is a slider that got away, not a reason to reset the operator's colours.
This commit is contained in:
2026-08-13 01:42:08 +02:00
parent 83e7727aab
commit 4ffdfc2548
7 changed files with 129 additions and 19 deletions
+26 -3
View File
@@ -23,8 +23,18 @@ type RowColorRule struct {
// RowColorSettings is the whole appearance block.
type RowColorSettings struct {
Enabled bool `json:"enabled"`
Rules []RowColorRule `json:"rules"`
Enabled bool `json:"enabled"`
// Style is how the colour is shown: "bar" paints a stripe down the left edge,
// "tint" washes the row, "both" does each.
//
// A bar is the default because a filled row is a poor signal in a log where
// nearly every contact has SOME QSL state: colour that is always present
// stops being information and becomes a striped background, with the data
// behind it. The stripe says the same thing and costs nothing to read.
Style string `json:"style"`
// Intensity is the tint strength in percent. Only used by "tint"/"both".
Intensity int `json:"intensity"`
Rules []RowColorRule `json:"rules"`
}
// The rule ids, in priority order. The frontend matches on these and holds the
@@ -56,7 +66,20 @@ func normRowColors(s RowColorSettings) RowColorSettings {
for _, r := range s.Rules {
byID[r.ID] = r
}
out := RowColorSettings{Enabled: s.Enabled}
out := RowColorSettings{Enabled: s.Enabled, Style: s.Style, Intensity: s.Intensity}
switch out.Style {
case "bar", "tint", "both":
default:
out.Style = "bar"
}
// Clamped rather than rejected: the value only shapes a colour-mix, and a
// number outside the range is a slider that got away, not a fault worth
// resetting the operator's whole choice for.
if out.Intensity < 5 {
out.Intensity = 12
} else if out.Intensity > 45 {
out.Intensity = 45
}
for _, id := range rowColorOrder {
r := byID[id]
r.ID = id