`autoPitchLines` overrides user `pitchColors.lines` on dark ramps — the only prop that breaks user-wins
When `autoPitchLines: true` (default) and the colour ramp is dark (magma, inferno, viridis, or a custom dark gradient), pitch lines are forced to white — even if the user passed `pitchColors.lines="#333"`. Dark ramp + dark lines makes the pitch disappear; legibility wins over API consistency.
Context
Campos generally honours the “user prop wins” precedent: if a consumer passes
a value, the library uses it as given. autoPitchLines is the one place that
rule doesn’t hold. Dark colour ramps over a pitch render the halfway line,
penalty boxes, and centre circle invisible if the theme’s default pitch-line
colour is dark grey. That’s an instant legibility failure on any broadcast or
editorial surface, and opt-in defaults would mean every Heatmap consumer had
to manually pair their ramp with a light pitch-line colour.
Decision
autoPitchLines defaults to true on Heatmap, KDE, and Territory. When it’s
on and the resolved colour ramp’s low-end is below a luminance threshold,
pitchColors.lines is forced to white in the rendered output — user value
ignored. Set autoPitchLines: false to respect user pitchColors unchanged.
Why override instead of warn
The cost of a surprise-override is a small API inconsistency. The cost of respecting the user here is that every dark-ramp heatmap looks broken until the user notices. That’s the wrong trade for a default-publishable library. Consumers who need the user-wins rule turn the auto-override off with one prop.
Consequences
- Docs call this out explicitly as the single exception to the prop-precedence
rule, and the prop name
autoPitchLinesencodes the escape hatch. - Dark-ramp heatmaps are publishable with zero config.
- Light-ramp heatmaps pass through user-supplied pitch-line colour unchanged — the override is conditional, not unconditional.
- New pitch-anchored density components should evaluate this pattern for adoption; it’s deliberately narrow in scope right now.