fix: align GIS theme styling on ultrawide
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-14 18:08:43 +02:00
parent 0bb2c8fd65
commit 3a2d1fae74
7 changed files with 119 additions and 44 deletions
+62 -41
View File
@@ -7,6 +7,8 @@ import type { MapViewportState, VectorSelectionBBox } from '../types'
interface GeoMapProps {
data: GeoJSON.FeatureCollection | null
dataFillColor?: string
dataLineColor?: string
areaData?: GeoJSON.FeatureCollection | null
selectedFeature?: GeoJSON.Feature | null
selectionData?: GeoJSON.FeatureCollection | null
@@ -50,6 +52,48 @@ const DEFAULT_ROAD_BASEMAP_STYLE: maplibregl.StyleSpecification = {
],
}
function datasetFillColor(fallbackColor: string): maplibregl.ExpressionSpecification {
return [
'case',
['==', ['get', 'layer_type'], 'municipality_boundary'],
'#0f766e',
[
'match',
['get', 'change_type'],
'added',
'#16a34a',
'removed',
'#dc2626',
'modified',
'#d97706',
'unchanged',
'#2563eb',
fallbackColor,
],
]
}
function datasetLineColor(fallbackColor: string): maplibregl.ExpressionSpecification {
return [
'case',
['==', ['get', 'layer_type'], 'municipality_boundary'],
'#0f5f59',
[
'match',
['get', 'change_type'],
'added',
'#15803d',
'removed',
'#b91c1c',
'modified',
'#b45309',
'unchanged',
'#1d4ed8',
fallbackColor,
],
]
}
function defaultMapStyle(): string | maplibregl.StyleSpecification {
return import.meta.env.VITE_MAP_STYLE_URL || DEFAULT_ROAD_BASEMAP_STYLE
}
@@ -103,6 +147,8 @@ function bboxToFeatureCollection(
function GeoMap({
data,
dataFillColor = '#f97316',
dataLineColor = '#ea580c',
areaData = null,
selectedFeature = null,
selectionData = null,
@@ -326,26 +372,7 @@ function GeoMap({
type: 'fill',
source: 'dataset',
paint: {
'fill-color': [
'case',
['==', ['get', 'layer_type'], 'municipality_boundary'],
'#0f766e',
['==', ['get', 'layer_type'], 'building'],
'#0891b2',
[
'match',
['get', 'change_type'],
'added',
'#16a34a',
'removed',
'#dc2626',
'modified',
'#d97706',
'unchanged',
'#2563eb',
'#f97316',
],
],
'fill-color': datasetFillColor(dataFillColor),
'fill-opacity': 0.4,
},
})
@@ -354,26 +381,7 @@ function GeoMap({
type: 'line',
source: 'dataset',
paint: {
'line-color': [
'case',
['==', ['get', 'layer_type'], 'municipality_boundary'],
'#0f5f59',
['==', ['get', 'layer_type'], 'building'],
'#0e7490',
[
'match',
['get', 'change_type'],
'added',
'#15803d',
'removed',
'#b91c1c',
'modified',
'#b45309',
'unchanged',
'#1d4ed8',
'#ea580c',
],
],
'line-color': datasetLineColor(dataLineColor),
'line-width': ['interpolate', ['linear'], ['zoom'], 8, 0.25, 12, 0.8, 16, 2],
},
})
@@ -388,7 +396,20 @@ function GeoMap({
}
}
}
}, [data, fitDataOnChange, mapStyleReady])
}, [data, dataFillColor, dataLineColor, fitDataOnChange, mapStyleReady])
useEffect(() => {
const map = mapRef.current
if (!map || !mapStyleReady || !map.isStyleLoaded()) {
return
}
if (map.getLayer('dataset-fill')) {
map.setPaintProperty('dataset-fill', 'fill-color', datasetFillColor(dataFillColor))
}
if (map.getLayer('dataset-line')) {
map.setPaintProperty('dataset-line', 'line-color', datasetLineColor(dataLineColor))
}
}, [dataFillColor, dataLineColor, mapStyleReady])
useEffect(() => {
const map = mapRef.current
+13 -1
View File
@@ -70,6 +70,15 @@ const DATA_THEMES: DataTheme[] = [
},
]
const DATA_THEME_MAP_STYLES: Record<DataThemeId, { fill: string; line: string }> = {
buildings: { fill: '#d45f3d', line: '#9f3e24' },
population: { fill: '#7559a6', line: '#5b3f88' },
forest: { fill: '#347950', line: '#225f3b' },
water: { fill: '#2676a8', line: '#155b85' },
roads: { fill: '#6b7280', line: '#4b5563' },
parcels: { fill: '#a7792f', line: '#7d571f' },
}
function datasetSearchText(dataset: DatasetCreateResponse): string {
return [
dataset.name,
@@ -563,6 +572,7 @@ export function MapWorkspace({
[availableMapDatasets],
)
const activeTheme = DATA_THEMES.find((theme) => theme.id === activeThemeId) ?? DATA_THEMES[0]
const activeThemeMapStyle = DATA_THEME_MAP_STYLES[activeTheme.id]
const activeThemeDataset = themeDatasetMap[activeTheme.id]
const activeTemporalSeriesGroups = useMemo(
() => listThemeTemporalSeries(availableMapDatasets, activeTheme),
@@ -1056,6 +1066,8 @@ export function MapWorkspace({
<div className={bboxSelectionMode ? 'geo-map-canvas geo-map-canvas-drawing' : 'geo-map-canvas'}>
<GeoMap
data={analysisMode === 'evolution' && temporalComparison?.geojson.features.length ? temporalComparison.geojson : mapFeatureCollection}
dataFillColor={activeThemeMapStyle.fill}
dataLineColor={activeThemeMapStyle.line}
areaData={areaFeatureCollection}
selectedFeature={selectedFeature}
selectionData={analysisMode === 'current' ? mapSelectionResult?.geojson ?? null : null}
@@ -1082,7 +1094,7 @@ export function MapWorkspace({
</>
) : (
<>
<span><i className="geo-legend-layer" /> {activeTheme.shortLabel}</span>
<span><i className={`geo-legend-layer geo-legend-layer-${activeTheme.id}`} /> {activeTheme.shortLabel}</span>
<span><i className="geo-legend-selection" /> Selectie</span>
</>
)}
+25
View File
@@ -5790,6 +5790,31 @@ section {
background: rgba(212, 95, 61, 0.24);
}
.geo-map-legend .geo-legend-layer-population {
border-color: #5b3f88;
background: rgba(117, 89, 166, 0.24);
}
.geo-map-legend .geo-legend-layer-forest {
border-color: #225f3b;
background: rgba(52, 121, 80, 0.24);
}
.geo-map-legend .geo-legend-layer-water {
border-color: #155b85;
background: rgba(38, 118, 168, 0.24);
}
.geo-map-legend .geo-legend-layer-roads {
border-color: #4b5563;
background: rgba(107, 114, 128, 0.24);
}
.geo-map-legend .geo-legend-layer-parcels {
border-color: #7d571f;
background: rgba(167, 121, 47, 0.24);
}
.geo-map-legend .geo-legend-selection {
border-color: #6b4aaa;
background: rgba(107, 74, 170, 0.18);
+5
View File
@@ -1202,6 +1202,11 @@ details.ai-lab-model-surface > summary strong {
/* Responsive shell */
@media (min-width: 1800px) {
.workbench-main > .geo-explorer {
width: 100%;
max-width: none;
}
.workbench-layout {
grid-template-columns: 13.25rem minmax(0, 1fr);
}