map: markers legible on both the white and the dark blueprint
Some checks failed
CI / backend (push) Has been cancelled
CI / naming (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / migrations-mysql (push) Has been cancelled

Markers sit on two very different surfaces - the light blueprint on white and
the dark blueprint over the near-black navy card - but the palette only ever
suited one. The grey "no subtype" default sat at 1.88:1 against white and the
orange asset-type step at 2.16:1, so both effectively disappeared on the light
blueprint. The fixed white ring made it worse: on white it added nothing.

Re-step the asset-type colors to versions of the SAME hues that clear 3:1
against both surfaces, replace the grey default with a neutral that clears
5.4:1 / 3.7:1, and derive the ring from the fill's luminance (light fill ->
dark ring, dark fill -> light ring) so every marker keeps a hard edge on
either background. The ring also rescues a washed-out color a user picks by
hand for a subtype, which no palette change can reach. The PDF export applies
the same rule to its markers and legend swatches, keeping print in parity.

Colors were chosen against a contrast/CVD validator rather than by eye. Note
that five simultaneous hues cannot all stay distinguishable under color-blind
simulation - past roughly five subtypes on screen, the legend and the hover
tooltip carry identity.

Adds computed contrast assertions so a future palette edit cannot
reintroduce a washed-out step.
This commit is contained in:
cproudlock
2026-07-31 09:03:24 -04:00
parent d5635a4306
commit c80c612922
4 changed files with 102 additions and 20 deletions

View File

@@ -97,7 +97,7 @@ import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { loadMapConfig, blueprintUrlFor, state as mapConfig } from '../composables/mapConfig'
import { assetTypeLabel, assetDetailRoute } from '../utils/assetTypes'
import { getSubtypeId } from '../utils/mapColors'
import { getSubtypeId, markerRingColor, UNSPECIFIED_COLOR } from '../utils/mapColors'
import api from '../api'
const props = defineProps({
@@ -451,7 +451,7 @@ function renderMarkers() {
// Unified asset mode - use subtype colors when a type is selected
if (props.selectedAssetType) {
const subtypeId = getSubtypeId(item)
color = (subtypeId && props.subtypeColors[subtypeId]) || '#BDBDBD'
color = (subtypeId && props.subtypeColors[subtypeId]) || UNSPECIFIED_COLOR
typeName = (subtypeId && props.subtypeNames[subtypeId]) || item.assettype || ''
} else {
// Prefer the stored AssetType.color; fall back to the built-in map.
@@ -477,7 +477,9 @@ function renderMarkers() {
const marker = L.circleMarker([leafletY, leafletX], {
radius: 6,
fillColor: color,
color: 'rgba(255,255,255,0.8)',
// Ring picked from the fill, not fixed white - a white ring on a light
// marker vanished against the light (white) blueprint.
color: markerRingColor(color),
weight: 2,
fillOpacity: 1,
renderer: canvasRenderer