From 52facdacefc77187b56c61ca3932e824336f2bfc Mon Sep 17 00:00:00 2001 From: Max Kohler Date: Fri, 26 Jun 2026 17:56:57 +0200 Subject: [PATCH 1/6] Add story --- .../MapStyle/SWRDataLabDark.stories.svelte | 26 ++++++++- .../src/maplibre/MapStyle/components/Admin.ts | 4 +- .../maplibre/MapStyle/components/Buildings.ts | 16 +++-- .../maplibre/MapStyle/components/Hillshade.ts | 4 +- .../maplibre/MapStyle/components/Landuse.ts | 4 +- .../MapStyle/components/PlaceLabels.ts | 23 ++++---- .../src/maplibre/MapStyle/components/Roads.ts | 58 ++++++++++++------- .../maplibre/MapStyle/components/Transit.ts | 4 +- .../maplibre/MapStyle/components/Walking.ts | 4 +- components/src/maplibre/types.ts | 2 + 10 files changed, 97 insertions(+), 48 deletions(-) diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte index 125891c2..9b203989 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte @@ -290,7 +290,31 @@ showDebug style={SWRDataLabDark()} maxZoom={20} - initialLocation={{lng: 9.558006092459436, lat: 47.69445218974644, zoom: 15.664592047703644}} + initialLocation={{ + lng: 9.558006092459436, + lat: 47.69445218974644, + zoom: 15.664592047703644 + }} + > + + + + + + + + +
+
+ diff --git a/components/src/maplibre/MapStyle/components/Admin.ts b/components/src/maplibre/MapStyle/components/Admin.ts index e1ec05d1..f0c9a91b 100644 --- a/components/src/maplibre/MapStyle/components/Admin.ts +++ b/components/src/maplibre/MapStyle/components/Admin.ts @@ -1,6 +1,6 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; -export default function makeAdmin(tokens, options): any { +export default function makeAdmin(tokens: styleTokens, options): any { const admin: Layer[] = [ { id: 'boundary-country:case', diff --git a/components/src/maplibre/MapStyle/components/Buildings.ts b/components/src/maplibre/MapStyle/components/Buildings.ts index 752b5488..72f53d0d 100644 --- a/components/src/maplibre/MapStyle/components/Buildings.ts +++ b/components/src/maplibre/MapStyle/components/Buildings.ts @@ -1,15 +1,23 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; -export default function makeBuildings(tokens): any { +export default function makeBuildings(tokens: styleTokens): any { const extrusionLayer = { source: 'basemap-de', type: 'fill-extrusion', minzoom: 14, - maxzoom: 20, + maxzoom: 20, paint: { 'fill-extrusion-color': tokens.building, 'fill-extrusion-opacity': ['interpolate', ['linear'], ['zoom'], 15.5, 0, 16, 1], - 'fill-extrusion-height': ['interpolate', ['linear'], ['zoom'], 15.5, 0, 16, ["to-number", ['get', 'hoehe']]] + 'fill-extrusion-height': [ + 'interpolate', + ['linear'], + ['zoom'], + 15.5, + 0, + 16, + ['to-number', ['get', 'hoehe']] + ] } }; diff --git a/components/src/maplibre/MapStyle/components/Hillshade.ts b/components/src/maplibre/MapStyle/components/Hillshade.ts index e2613cc3..cf97f2f8 100644 --- a/components/src/maplibre/MapStyle/components/Hillshade.ts +++ b/components/src/maplibre/MapStyle/components/Hillshade.ts @@ -1,6 +1,6 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; -export default function makeHillshade(tokens): any { +export default function makeHillshade(tokens: styleTokens): any { const hillshade: Layer[] = [ { id: 'hillshade-light', diff --git a/components/src/maplibre/MapStyle/components/Landuse.ts b/components/src/maplibre/MapStyle/components/Landuse.ts index 144a9ffb..579ed32b 100644 --- a/components/src/maplibre/MapStyle/components/Landuse.ts +++ b/components/src/maplibre/MapStyle/components/Landuse.ts @@ -1,6 +1,6 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; -export default function makeLanduse(tokens): any { +export default function makeLanduse(tokens: styleTokens): any { const landuse: Layer[] = [ { id: 'background', diff --git a/components/src/maplibre/MapStyle/components/PlaceLabels.ts b/components/src/maplibre/MapStyle/components/PlaceLabels.ts index baf0e74a..52fed6b1 100644 --- a/components/src/maplibre/MapStyle/components/PlaceLabels.ts +++ b/components/src/maplibre/MapStyle/components/PlaceLabels.ts @@ -1,4 +1,5 @@ import type { SymbolLayerSpecification } from 'maplibre-gl'; +import type { styleTokens } from '../../types'; // Hand-authored list of place labes we want to show at low zoom levels // Ideally majorCities would include Frankfurt and Leipzig, but they're not @@ -11,7 +12,7 @@ const majorCities = ['Berlin', 'Stuttgart', 'München', 'Frankfurt', 'Hamburg', // values for "city" and anything below. // See: https://github.com/versatiles-org/shortbread-tilemaker/blob/69e5d4c586a1d2726b746a24829bfb05d4dbeb91/process.lua#L198-L242 -export default function makePlaceLabels(tokens) { +export default function makePlaceLabels(tokens: styleTokens) { const placeLabels: SymbolLayerSpecification[] = [ { id: 'label-place-quarter', @@ -41,10 +42,12 @@ export default function makePlaceLabels(tokens) { layout: { 'text-size': { stops: [ - [11, 14], - [15, 16] + [14, 12], + [16, 17] ] - } + }, + 'text-letter-spacing': 0.1, + 'text-transform': 'uppercase' }, paint: { 'text-color': tokens.label_secondary @@ -63,7 +66,7 @@ export default function makePlaceLabels(tokens) { 'text-size': { stops: [ [10, 14], - [12, 15] + [12, 16] ] } } @@ -79,11 +82,13 @@ export default function makePlaceLabels(tokens) { ['!in', 'name', ...majorCities] ], minzoom: 8.5, + maxzoom: 13, + layout: { 'text-size': { stops: [ [8, 14], - [12, 16] + [12, 18] ] } } @@ -184,11 +189,7 @@ export default function makePlaceLabels(tokens) { const boundaryLabels = [ { id: 'label-boundary-country', - filter: [ - 'all', - ['==', 'admin_level', 2], - ['!in', 'name', 'Jersey', 'Guernsey', 'Insel Man'] - ], + filter: ['all', ['==', 'admin_level', 2], ['!in', 'name', 'Jersey', 'Guernsey', 'Insel Man']], minzoom: 4, maxzoom: 8, layout: { diff --git a/components/src/maplibre/MapStyle/components/Roads.ts b/components/src/maplibre/MapStyle/components/Roads.ts index d1caa456..4d844572 100644 --- a/components/src/maplibre/MapStyle/components/Roads.ts +++ b/components/src/maplibre/MapStyle/components/Roads.ts @@ -1,4 +1,4 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; import type { SymbolLayerSpecification } from 'maplibre-gl'; const street_layout = { @@ -10,7 +10,7 @@ const case_layout = { 'line-cap': 'butt' }; -export default function makeRoads(tokens) { +export default function makeRoads(tokens: styleTokens) { const motorway = { line_color: { stops: [ @@ -198,22 +198,37 @@ export default function makeRoads(tokens) { const roadLabels: SymbolLayerSpecification[] = [ { id: 'label-street-misc', - filter: ['in', 'kind', 'residential', 'livingstreet', 'unclassified'], - minzoom: 15, + filter: [ + 'in', + 'kind', + 'residential', + 'pedestrian', + 'livingstreet', + 'living_street', + 'unclassified', + 'footway' + ], + minzoom: 14, layout: { + 'text-letter-spacing': 0.02, + 'text-overlap': 'cooperative', 'text-size': { stops: [ [12, 10], - [15, 13] + [15, 12] ] } + }, + paint: { + 'text-color': tokens.label_tertiary } }, { id: 'label-street-tertiary', filter: ['==', 'kind', 'tertiary'], - minzoom: 15, + minzoom: 14, layout: { + 'text-overlap': 'cooperative', 'text-size': { stops: [ [12, 10], @@ -227,27 +242,29 @@ export default function makeRoads(tokens) { filter: ['==', 'kind', 'secondary'], minzoom: 14, layout: { - 'text-letter-spacing': 0.025, + 'text-letter-spacing': 0.01, 'text-size': { stops: [ [12, 10], [15, 14] ] } - } + }, + 'text-overlap': 'always' }, { id: 'label-street-primary', filter: ['==', 'kind', 'primary'], minzoom: 14, layout: { - 'text-letter-spacing': 0.025, + 'text-letter-spacing': 0.01, 'text-size': { stops: [ [12, 10], [15, 14] ] - } + }, + 'text-overlap': 'always' }, paint: { 'text-color': tokens.label_primary @@ -258,6 +275,8 @@ export default function makeRoads(tokens) { filter: ['==', 'kind', 'trunk'], minzoom: 13, layout: { + 'text-overlap': 'always', + 'text-offset': [0, 4], 'text-size': { stops: [ [12, 10], @@ -279,16 +298,16 @@ export default function makeRoads(tokens) { 'text-field': '{name}', 'text-font': tokens.sans_regular, 'symbol-placement': 'line', - 'text-anchor': 'center', + 'text-variable-anchor': ['center', 'left', 'right'], ...el.layout }, paint: { 'text-color': tokens.label_secondary, 'text-halo-color': tokens.background, - 'text-halo-width': 1.5, + 'text-halo-width': 1, ...el.paint } - } as SymbolLayerSpecification; + }; }); const roadBridges: Layer[] = [ @@ -1258,16 +1277,11 @@ export default function makeRoads(tokens) { layout: street_layout }, { - id: 'street-livingstreet', - filter: [ - 'all', - ['==', 'kind', 'living_street'], - ['!=', 'bridge', true], - ['!=', 'tunnel', true] - ], + id: 'street-footway', + filter: ['all', ['in', 'kind', 'footway'], ['!=', 'bridge', true], ['!=', 'tunnel', true]], paint: { 'line-color': street_residential.line_color, - 'line-width': street_residential.line_width, + 'line-width': 2, 'line-opacity': street_residential.line_opacity }, layout: street_layout @@ -1276,7 +1290,7 @@ export default function makeRoads(tokens) { id: 'street-residential', filter: [ 'all', - ['==', 'kind', 'residential'], + ['in', 'kind', 'residential', 'livingstreet'], ['!=', 'bridge', true], ['!=', 'tunnel', true] ], diff --git a/components/src/maplibre/MapStyle/components/Transit.ts b/components/src/maplibre/MapStyle/components/Transit.ts index 63024545..9a431b16 100644 --- a/components/src/maplibre/MapStyle/components/Transit.ts +++ b/components/src/maplibre/MapStyle/components/Transit.ts @@ -1,6 +1,6 @@ -import type { Layer } from '../../types'; +import type { Layer, styleTokens } from '../../types'; -export default function makeTransit(tokens) { +export default function makeTransit(tokens: styleTokens) { const rail = { line_color: tokens.rail, line_dasharray: [2, 2], diff --git a/components/src/maplibre/MapStyle/components/Walking.ts b/components/src/maplibre/MapStyle/components/Walking.ts index ccfe9310..90d7168a 100644 --- a/components/src/maplibre/MapStyle/components/Walking.ts +++ b/components/src/maplibre/MapStyle/components/Walking.ts @@ -1,4 +1,4 @@ -import { type Layer } from '../../types'; +import { type Layer, type styleTokens } from '../../types'; import type { SymbolLayerSpecification } from 'maplibre-gl'; const street_layout = { @@ -6,7 +6,7 @@ const street_layout = { 'line-cap': 'butt' }; -export default function makeWalking(tokens): any { +export default function makeWalking(tokens: styleTokens): any { const street_residential = { line_color: tokens.street_tertiary, line_width: { diff --git a/components/src/maplibre/types.ts b/components/src/maplibre/types.ts index e09611bc..6e98d1e3 100644 --- a/components/src/maplibre/types.ts +++ b/components/src/maplibre/types.ts @@ -52,3 +52,5 @@ export interface SourceProps { attribution?: string; children?: Snippet; } + +export type styleTokens = Record; From bd0420a87e6760ecadfcc46dce258a4b55640011 Mon Sep 17 00:00:00 2001 From: Max Kohler Date: Sun, 28 Jun 2026 13:09:19 +0200 Subject: [PATCH 2/6] extract makeRoadLabels --- .../MapStyle/SWRDataLabDark.stories.svelte | 8 +- .../src/maplibre/MapStyle/SWRDataLabDark.ts | 10 +- .../src/maplibre/MapStyle/SWRDataLabLight.ts | 8 +- .../MapStyle/components/PlaceLabels.ts | 13 +- .../MapStyle/components/RoadLabels.ts | 125 ++++++++++++++++++ .../src/maplibre/MapStyle/components/Roads.ts | 117 +--------------- components/src/maplibre/types.ts | 2 +- 7 files changed, 152 insertions(+), 131 deletions(-) create mode 100644 components/src/maplibre/MapStyle/components/RoadLabels.ts diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte index 9b203989..a3be787c 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte @@ -302,7 +302,7 @@
- +
@@ -311,9 +311,9 @@ style={SWRDataLabDark()} maxZoom={20} initialLocation={{ - lng: 9.168427169271467, - lat: 47.668888671750324, - zoom: 14.798741203087438 + lng: 9.561655796873652, + lat: 47.6999494832024, + zoom: 15.426291620556794 }} > diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.ts b/components/src/maplibre/MapStyle/SWRDataLabDark.ts index 95fdf3e7..b5053102 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.ts @@ -7,12 +7,15 @@ import makeAdmin from './components/Admin'; import makeBuildings from './components/Buildings'; import makeLanduse from './components/Landuse'; import makeTransit from './components/Transit'; -import makePlaceLabels from './components/PlaceLabels'; import makeWalking from './components/Walking'; import makeRoads from './components/Roads'; +import makePlaceLabels from './components/PlaceLabels'; +import makeRoadLabels from './components/RoadLabels'; import makeHillshade from './components/Hillshade'; -const tokens = { +import type { styleTokens } from '../types'; + +const tokens: styleTokens = { sans_regular: ['swr_sans_regular'], sans_medium: ['swr_sans_medium'], sans_bold: ['swr_sans_bold'], @@ -53,9 +56,10 @@ const { landuse } = makeLanduse(tokens); const { placeLabels, boundaryLabels } = makePlaceLabels(tokens); const { airports, transitBridges, transitSurface, transitTunnels } = makeTransit(tokens); const { walkingLabels, walkingTunnels, walkingSurface, walkingBridges } = makeWalking(tokens); -const { roadLabels, roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); +const { roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens); const { hillshade } = makeHillshade(tokens); +const { roadLabels } = makeRoadLabels(tokens); interface styleFunction { (options?: StyleOptions): StyleSpecification; diff --git a/components/src/maplibre/MapStyle/SWRDataLabLight.ts b/components/src/maplibre/MapStyle/SWRDataLabLight.ts index 6e829be1..3cf8acea 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabLight.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabLight.ts @@ -7,10 +7,13 @@ import makeLanduse from './components/Landuse'; import makeTransit from './components/Transit'; import makePlaceLabels from './components/PlaceLabels'; import makeWalking from './components/Walking'; +import makeRoadLabels from './components/RoadLabels'; import makeRoads from './components/Roads'; import defaultOptions from './defaultOptions'; import makeHillshade from './components/Hillshade'; +import type { styleTokens } from '../types'; + const water = { stops: [ [6, 'white'], @@ -18,7 +21,7 @@ const water = { ] }; -const tokens = { +const tokens: styleTokens = { sans_regular: ['swr_sans_regular'], sans_medium: ['swr_sans_medium'], sans_bold: ['swr_sans_bold'], @@ -59,7 +62,8 @@ const { landuse } = makeLanduse(tokens); const { placeLabels, boundaryLabels } = makePlaceLabels(tokens); const { airports, transitBridges, transitSurface, transitTunnels } = makeTransit(tokens); const { walkingLabels, walkingTunnels, walkingSurface, walkingBridges } = makeWalking(tokens); -const { roadLabels, roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); +const { roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); +const { roadLabels } = makeRoadLabels(tokens); const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens); const { hillshade } = makeHillshade(tokens); diff --git a/components/src/maplibre/MapStyle/components/PlaceLabels.ts b/components/src/maplibre/MapStyle/components/PlaceLabels.ts index 52fed6b1..dc7e8c2f 100644 --- a/components/src/maplibre/MapStyle/components/PlaceLabels.ts +++ b/components/src/maplibre/MapStyle/components/PlaceLabels.ts @@ -17,14 +17,17 @@ export default function makePlaceLabels(tokens: styleTokens) { { id: 'label-place-quarter', filter: ['all', ['in', 'kind', 'neighbourhood']], - minzoom: 13, + minzoom: 14.5, layout: { 'text-size': { stops: [ - [10, 13], - [15, 16] + [10, 11], + [15, 13] ] - } + }, + 'text-letter-spacing': 0.1, + 'text-transform': 'uppercase', + 'text-overlap': 'never' }, paint: { 'text-color': tokens.label_secondary @@ -42,7 +45,7 @@ export default function makePlaceLabels(tokens: styleTokens) { layout: { 'text-size': { stops: [ - [14, 12], + [14, 14], [16, 17] ] }, diff --git a/components/src/maplibre/MapStyle/components/RoadLabels.ts b/components/src/maplibre/MapStyle/components/RoadLabels.ts new file mode 100644 index 00000000..0dea2217 --- /dev/null +++ b/components/src/maplibre/MapStyle/components/RoadLabels.ts @@ -0,0 +1,125 @@ +import type { styleTokens } from '../../types'; +import type { SymbolLayerSpecification } from 'maplibre-gl'; + +export default function makeRoadLabels(tokens: styleTokens) { + const roadLabels: SymbolLayerSpecification[] = [ + { + id: 'label-street-misc', + filter: [ + 'in', + 'kind', + 'residential', + 'pedestrian', + 'path', + 'track', + 'steps', + 'service', + 'livingstreet', + 'living_street', + 'unclassified', + 'footway' + ], + minzoom: 14, + layout: { + 'text-letter-spacing': 0.05, + 'text-overlap': 'cooperative', + 'text-size': { + stops: [ + [12, 10], + [15, 11] + ] + } + }, + paint: { + 'text-color': tokens.label_tertiary + } + }, + { + id: 'label-street-tertiary', + filter: ['==', 'kind', 'tertiary'], + minzoom: 14, + layout: { + 'text-overlap': 'cooperative', + 'text-size': { + stops: [ + [12, 10], + [15, 13] + ] + } + } + }, + { + id: 'label-street-secondary', + filter: ['==', 'kind', 'secondary'], + minzoom: 14, + layout: { + 'text-letter-spacing': 0.01, + 'text-size': { + stops: [ + [12, 10], + [15, 14] + ] + } + }, + 'text-overlap': 'always' + }, + { + id: 'label-street-primary', + filter: ['==', 'kind', 'primary'], + minzoom: 14, + layout: { + 'text-letter-spacing': 0.05, + 'text-size': { + stops: [ + [12, 10], + [15, 13] + ] + }, + 'text-overlap': 'always' + }, + paint: { + 'text-color': tokens.label_secondary + } + }, + { + id: 'label-street-trunk', + filter: ['==', 'kind', 'trunk'], + minzoom: 13, + layout: { + 'text-overlap': 'always', + 'text-offset': [0, 4], + 'text-size': { + stops: [ + [12, 10], + [15, 13] + ] + } + }, + paint: { + 'text-color': tokens.label_primary + } + } + ].map((el) => { + return { + type: 'symbol', + source: 'versatiles-osm', + 'source-layer': 'street_labels', + ...el, + layout: { + 'text-field': '{name}', + 'text-font': tokens.sans_regular, + 'symbol-placement': 'line', + 'text-variable-anchor': ['center', 'left', 'right'], + ...el.layout + }, + paint: { + 'text-color': tokens.label_secondary, + 'text-halo-color': tokens.background, + 'text-halo-width': 1, + ...el.paint + } + }; + }); + + return { roadLabels }; +} diff --git a/components/src/maplibre/MapStyle/components/Roads.ts b/components/src/maplibre/MapStyle/components/Roads.ts index 4d844572..0079aa0f 100644 --- a/components/src/maplibre/MapStyle/components/Roads.ts +++ b/components/src/maplibre/MapStyle/components/Roads.ts @@ -195,121 +195,6 @@ export default function makeRoads(tokens: styleTokens) { } }; - const roadLabels: SymbolLayerSpecification[] = [ - { - id: 'label-street-misc', - filter: [ - 'in', - 'kind', - 'residential', - 'pedestrian', - 'livingstreet', - 'living_street', - 'unclassified', - 'footway' - ], - minzoom: 14, - layout: { - 'text-letter-spacing': 0.02, - 'text-overlap': 'cooperative', - 'text-size': { - stops: [ - [12, 10], - [15, 12] - ] - } - }, - paint: { - 'text-color': tokens.label_tertiary - } - }, - { - id: 'label-street-tertiary', - filter: ['==', 'kind', 'tertiary'], - minzoom: 14, - layout: { - 'text-overlap': 'cooperative', - 'text-size': { - stops: [ - [12, 10], - [15, 13] - ] - } - } - }, - { - id: 'label-street-secondary', - filter: ['==', 'kind', 'secondary'], - minzoom: 14, - layout: { - 'text-letter-spacing': 0.01, - 'text-size': { - stops: [ - [12, 10], - [15, 14] - ] - } - }, - 'text-overlap': 'always' - }, - { - id: 'label-street-primary', - filter: ['==', 'kind', 'primary'], - minzoom: 14, - layout: { - 'text-letter-spacing': 0.01, - 'text-size': { - stops: [ - [12, 10], - [15, 14] - ] - }, - 'text-overlap': 'always' - }, - paint: { - 'text-color': tokens.label_primary - } - }, - { - id: 'label-street-trunk', - filter: ['==', 'kind', 'trunk'], - minzoom: 13, - layout: { - 'text-overlap': 'always', - 'text-offset': [0, 4], - 'text-size': { - stops: [ - [12, 10], - [15, 13] - ] - } - }, - paint: { - 'text-color': tokens.label_primary - } - } - ].map((el) => { - return { - type: 'symbol', - source: 'versatiles-osm', - 'source-layer': 'street_labels', - ...el, - layout: { - 'text-field': '{name}', - 'text-font': tokens.sans_regular, - 'symbol-placement': 'line', - 'text-variable-anchor': ['center', 'left', 'right'], - ...el.layout - }, - paint: { - 'text-color': tokens.label_secondary, - 'text-halo-color': tokens.background, - 'text-halo-width': 1, - ...el.paint - } - }; - }); - const roadBridges: Layer[] = [ { id: 'bridge-street-service:case', @@ -1510,5 +1395,5 @@ export default function makeRoads(tokens: styleTokens) { return { source: 'versatiles-osm', type: 'line', 'source-layer': 'streets', ...el } as Layer; }); - return { roadLabels, roadBridges, roadSurface, roadTunnels }; + return { roadBridges, roadSurface, roadTunnels }; } diff --git a/components/src/maplibre/types.ts b/components/src/maplibre/types.ts index 6e98d1e3..1e60f65c 100644 --- a/components/src/maplibre/types.ts +++ b/components/src/maplibre/types.ts @@ -53,4 +53,4 @@ export interface SourceProps { children?: Snippet; } -export type styleTokens = Record; +export type styleTokens = Record; From 2da156c1dd39bff7f916dc4628ff3aa0cc45add0 Mon Sep 17 00:00:00 2001 From: Max Kohler Date: Sun, 28 Jun 2026 14:26:52 +0200 Subject: [PATCH 3/6] iterate labels --- .../MapStyle/SWRDataLabDark.stories.svelte | 43 +++++- .../src/maplibre/MapStyle/SWRDataLabDark.ts | 6 +- .../src/maplibre/MapStyle/SWRDataLabLight.ts | 8 +- .../maplibre/MapStyle/components/Buildings.ts | 2 +- .../MapStyle/components/PlaceLabels.ts | 10 +- .../MapStyle/components/RoadLabels.ts | 131 ++++++++---------- .../src/maplibre/MapStyle/components/Roads.ts | 8 +- components/src/maplibre/MapStyle/types.ts | 7 +- 8 files changed, 117 insertions(+), 98 deletions(-) diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte index a3be787c..498302a8 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte @@ -6,9 +6,10 @@ import AttributionControl from '../AttributionControl/AttributionControl.svelte'; import GeocoderControl from '../GeocoderControl/GeocoderControl.svelte'; - import { SWRDataLabDark } from './index'; + import { SWRDataLabDark, SWRDataLabLight } from './index'; import locations from './storyLocations'; import NavigationControl from '../NavigationControl/NavigationControl.svelte'; + import { type RoadLabelDensity } from './types'; const { Story } = defineMeta({ title: 'Maplibre/Style/SWR Data Lab Dark', @@ -302,18 +303,41 @@
- + -
+
+ {#each ['none', 'default', 'dense'] as s} +
+ {s} + + + +
+ {/each} +
+ + + + +
@@ -330,7 +354,12 @@ grid-template-rows: auto; height: 700px; } + .row { + display: flex; + height: 700px; + } .container { + flex-grow: 1; overflow: hidden; } diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.ts b/components/src/maplibre/MapStyle/SWRDataLabDark.ts index b5053102..a81c2b6d 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.ts @@ -42,7 +42,7 @@ const tokens: styleTokens = { street_tertiary_case: 'hsl(0, 0%, 14%)', label_primary: 'hsl(240, 5%, 96%)', label_secondary: 'hsl(0, 2%, 85%)', - label_tertiary: 'hsl(0, 1%, 75%)', + label_tertiary: 'hsl(0, 1%, 60%)', boundary_country: '#6e6f71', boundary_country_case: '#181818', boundary_state: 'hsl(218, 4%, 37%)', @@ -59,7 +59,6 @@ const { walkingLabels, walkingTunnels, walkingSurface, walkingBridges } = makeWa const { roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens); const { hillshade } = makeHillshade(tokens); -const { roadLabels } = makeRoadLabels(tokens); interface styleFunction { (options?: StyleOptions): StyleSpecification; @@ -72,6 +71,7 @@ const style: styleFunction = (opts) => { } as StyleOptions; const { admin } = makeAdmin(tokens, options?.admin); + const { roadLabels } = makeRoadLabels(tokens, options?.roads?.labels); return { version: 8, @@ -160,7 +160,7 @@ const style: styleFunction = (opts) => { // 8. Labels ...(options.roads?.showLabels ? walkingLabels : []), - ...(options.roads?.showLabels ? roadLabels : []), + ...roadLabels, // 9. Building extrusions ...(options.enableBuildingExtrusions ? [buildingExtrusions] : []), diff --git a/components/src/maplibre/MapStyle/SWRDataLabLight.ts b/components/src/maplibre/MapStyle/SWRDataLabLight.ts index 3cf8acea..7008e140 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabLight.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabLight.ts @@ -48,8 +48,8 @@ const tokens: styleTokens = { street_tertiary_case: 'hsl(0, 0%, 70%)', label_primary: 'hsl(240, 10%, 2%)', label_secondary: 'hsl(0, 0%, 18%)', - label_tertiary: 'hsl(60, 1%, 25%)', - building: '#f3f2f1', + label_tertiary: 'hsl(60, 1%, 35%)', + building: '#eee', rail: '#d3d3d3', boundary_country: '#8b8a89', boundary_state: 'hsl(37, 10%, 75%)', @@ -63,7 +63,6 @@ const { placeLabels, boundaryLabels } = makePlaceLabels(tokens); const { airports, transitBridges, transitSurface, transitTunnels } = makeTransit(tokens); const { walkingLabels, walkingTunnels, walkingSurface, walkingBridges } = makeWalking(tokens); const { roadBridges, roadSurface, roadTunnels } = makeRoads(tokens); -const { roadLabels } = makeRoadLabels(tokens); const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens); const { hillshade } = makeHillshade(tokens); @@ -78,6 +77,7 @@ const style: styleFunction = (opts) => { } as StyleOptions; const { admin } = makeAdmin(tokens, options?.admin); + const { roadLabels } = makeRoadLabels(tokens, options?.roads?.labels); return { version: 8, @@ -166,7 +166,7 @@ const style: styleFunction = (opts) => { // 8. Labels ...(options.roads?.showLabels ? walkingLabels : []), - ...(options.roads?.showLabels ? roadLabels : []), + ...roadLabels, // 9. Building extrusions ...(options.enableBuildingExtrusions ? [buildingExtrusions] : []), diff --git a/components/src/maplibre/MapStyle/components/Buildings.ts b/components/src/maplibre/MapStyle/components/Buildings.ts index 72f53d0d..6cfec5d0 100644 --- a/components/src/maplibre/MapStyle/components/Buildings.ts +++ b/components/src/maplibre/MapStyle/components/Buildings.ts @@ -8,7 +8,7 @@ export default function makeBuildings(tokens: styleTokens): any { maxzoom: 20, paint: { 'fill-extrusion-color': tokens.building, - 'fill-extrusion-opacity': ['interpolate', ['linear'], ['zoom'], 15.5, 0, 16, 1], + 'fill-extrusion-opacity': ['interpolate', ['linear'], ['zoom'], 14.5, 0, 15, 1], 'fill-extrusion-height': [ 'interpolate', ['linear'], diff --git a/components/src/maplibre/MapStyle/components/PlaceLabels.ts b/components/src/maplibre/MapStyle/components/PlaceLabels.ts index dc7e8c2f..78c125c5 100644 --- a/components/src/maplibre/MapStyle/components/PlaceLabels.ts +++ b/components/src/maplibre/MapStyle/components/PlaceLabels.ts @@ -25,7 +25,7 @@ export default function makePlaceLabels(tokens: styleTokens) { [15, 13] ] }, - 'text-letter-spacing': 0.1, + 'text-letter-spacing': 0.05, 'text-transform': 'uppercase', 'text-overlap': 'never' }, @@ -38,18 +38,18 @@ export default function makePlaceLabels(tokens: styleTokens) { filter: [ 'all', ['in', 'kind', 'suburb', 'village', 'hamlet', 'town'], - ['>', 'population', 1000], + ['>=', 'population', 1000], ['<', 'population', 15_000] ], minzoom: 12, layout: { 'text-size': { stops: [ - [14, 14], - [16, 17] + [14, 11], + [16, 15] ] }, - 'text-letter-spacing': 0.1, + 'text-letter-spacing': 0.05, 'text-transform': 'uppercase' }, paint: { diff --git a/components/src/maplibre/MapStyle/components/RoadLabels.ts b/components/src/maplibre/MapStyle/components/RoadLabels.ts index 0dea2217..8a9a2e2c 100644 --- a/components/src/maplibre/MapStyle/components/RoadLabels.ts +++ b/components/src/maplibre/MapStyle/components/RoadLabels.ts @@ -1,53 +1,60 @@ import type { styleTokens } from '../../types'; import type { SymbolLayerSpecification } from 'maplibre-gl'; +import type { RoadLabelDensity } from '../types'; + +export default function makeRoadLabels(tokens: styleTokens, density: RoadLabelDensity = 'default') { + if (density === 'none') return { roadLabels: [] }; -export default function makeRoadLabels(tokens: styleTokens) { const roadLabels: SymbolLayerSpecification[] = [ - { - id: 'label-street-misc', - filter: [ - 'in', - 'kind', - 'residential', - 'pedestrian', - 'path', - 'track', - 'steps', - 'service', - 'livingstreet', - 'living_street', - 'unclassified', - 'footway' - ], - minzoom: 14, - layout: { - 'text-letter-spacing': 0.05, - 'text-overlap': 'cooperative', - 'text-size': { - stops: [ - [12, 10], - [15, 11] - ] - } - }, - paint: { - 'text-color': tokens.label_tertiary - } - }, - { - id: 'label-street-tertiary', - filter: ['==', 'kind', 'tertiary'], - minzoom: 14, - layout: { - 'text-overlap': 'cooperative', - 'text-size': { - stops: [ - [12, 10], - [15, 13] - ] - } - } - }, + ...(density === 'dense' + ? [ + { + id: 'label-street-misc', + filter: [ + 'in', + 'kind', + 'residential', + 'pedestrian', + 'path', + 'track', + 'steps', + 'service', + 'livingstreet', + 'living_street', + 'unclassified', + 'footway' + ], + minzoom: 14, + layout: { + 'text-letter-spacing': 0.05, + 'text-overlap': 'cooperative', + 'text-size': { + stops: [ + [12, 10], + [15, 11] + ] + } + }, + paint: { + 'text-color': tokens.label_tertiary + } + }, + { + id: 'label-street-tertiary', + filter: ['==', 'kind', 'tertiary'], + minzoom: 14, + layout: { + 'text-overlap': 'cooperative', + 'text-size': { + stops: [ + [12, 10], + [15, 12] + ] + } + } + } + ] + : []), { id: 'label-street-secondary', filter: ['==', 'kind', 'secondary'], @@ -56,8 +63,8 @@ export default function makeRoadLabels(tokens: styleTokens) { 'text-letter-spacing': 0.01, 'text-size': { stops: [ - [12, 10], - [15, 14] + [12, 9], + [15, 12] ] } }, @@ -65,38 +72,17 @@ export default function makeRoadLabels(tokens: styleTokens) { }, { id: 'label-street-primary', - filter: ['==', 'kind', 'primary'], + filter: ['in', 'kind', 'primary', 'trunk'], minzoom: 14, layout: { - 'text-letter-spacing': 0.05, + 'text-letter-spacing': 0.03, 'text-size': { stops: [ [12, 10], - [15, 13] + [15, 14] ] }, 'text-overlap': 'always' - }, - paint: { - 'text-color': tokens.label_secondary - } - }, - { - id: 'label-street-trunk', - filter: ['==', 'kind', 'trunk'], - minzoom: 13, - layout: { - 'text-overlap': 'always', - 'text-offset': [0, 4], - 'text-size': { - stops: [ - [12, 10], - [15, 13] - ] - } - }, - paint: { - 'text-color': tokens.label_primary } } ].map((el) => { @@ -109,6 +95,7 @@ export default function makeRoadLabels(tokens: styleTokens) { 'text-field': '{name}', 'text-font': tokens.sans_regular, 'symbol-placement': 'line', + 'text-max-angle': 20, 'text-variable-anchor': ['center', 'left', 'right'], ...el.layout }, diff --git a/components/src/maplibre/MapStyle/components/Roads.ts b/components/src/maplibre/MapStyle/components/Roads.ts index 0079aa0f..dcdabec2 100644 --- a/components/src/maplibre/MapStyle/components/Roads.ts +++ b/components/src/maplibre/MapStyle/components/Roads.ts @@ -971,7 +971,7 @@ export default function makeRoads(tokens: styleTokens) { id: 'street-residential:case', filter: [ 'all', - ['==', 'kind', 'residential'], + ['in', 'kind', 'residential', 'footway'], ['!=', 'bridge', true], ['!=', 'tunnel', true] ], @@ -1163,10 +1163,10 @@ export default function makeRoads(tokens: styleTokens) { }, { id: 'street-footway', - filter: ['all', ['in', 'kind', 'footway'], ['!=', 'bridge', true], ['!=', 'tunnel', true]], + filter: ['all', ['in', 'kind', 'footway']], paint: { 'line-color': street_residential.line_color, - 'line-width': 2, + 'line-width': street_residential.line_width, 'line-opacity': street_residential.line_opacity }, layout: street_layout @@ -1175,7 +1175,7 @@ export default function makeRoads(tokens: styleTokens) { id: 'street-residential', filter: [ 'all', - ['in', 'kind', 'residential', 'livingstreet'], + ['in', 'kind', 'residential', 'living_street'], ['!=', 'bridge', true], ['!=', 'tunnel', true] ], diff --git a/components/src/maplibre/MapStyle/types.ts b/components/src/maplibre/MapStyle/types.ts index d392934c..a28935e2 100644 --- a/components/src/maplibre/MapStyle/types.ts +++ b/components/src/maplibre/MapStyle/types.ts @@ -2,6 +2,9 @@ enum AdminLevel { COUNTRY = 2, BUNDESLAND = 4 } + +type RoadLabelDensity = 'none' | 'default' | 'dense'; + interface StyleOptions { enableBuildingExtrusions?: boolean; enableHillshade?: boolean; @@ -13,8 +16,8 @@ interface StyleOptions { showLabels?: boolean; }; roads?: { - showLabels?: boolean; + labels?: RoadLabelDensity; }; } -export type { StyleOptions }; +export type { StyleOptions, RoadLabelDensity }; From 75f56c25cf41ec0aeccc963eaa3dfc1212537021 Mon Sep 17 00:00:00 2001 From: Max Kohler Date: Sun, 28 Jun 2026 15:06:15 +0200 Subject: [PATCH 4/6] tweak colours --- .../MapStyle/SWRDataLabDark.stories.svelte | 2 +- .../src/maplibre/MapStyle/SWRDataLabDark.ts | 4 +-- .../MapStyle/components/PlaceLabels.ts | 12 ++++--- .../MapStyle/components/RoadLabels.ts | 4 +-- .../src/maplibre/MapStyle/components/Roads.ts | 35 +++++++++++-------- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte index 498302a8..34d4fa73 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte @@ -333,7 +333,7 @@ Date: Sun, 28 Jun 2026 15:14:16 +0200 Subject: [PATCH 5/6] update stories --- .../maplibre/MapStyle/SWRDataLabDark.stories.svelte | 2 +- components/src/maplibre/MapStyle/SWRDataLabDark.ts | 2 +- .../maplibre/MapStyle/SWRDataLabLight.stories.svelte | 11 +++++++---- components/src/maplibre/MapStyle/SWRDataLabLight.ts | 2 +- components/src/maplibre/MapStyle/defaultOptions.ts | 3 --- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte index 34d4fa73..68687931 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.stories.svelte @@ -72,7 +72,7 @@
diff --git a/components/src/maplibre/MapStyle/SWRDataLabDark.ts b/components/src/maplibre/MapStyle/SWRDataLabDark.ts index 49aec865..f1334f39 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabDark.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabDark.ts @@ -159,7 +159,7 @@ const style: styleFunction = (opts) => { ...admin, // 8. Labels - ...(options.roads?.showLabels ? walkingLabels : []), + ...(options.roads?.labels !== 'none' ? walkingLabels : []), ...roadLabels, // 9. Building extrusions diff --git a/components/src/maplibre/MapStyle/SWRDataLabLight.stories.svelte b/components/src/maplibre/MapStyle/SWRDataLabLight.stories.svelte index c36d317d..c052e977 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabLight.stories.svelte +++ b/components/src/maplibre/MapStyle/SWRDataLabLight.stories.svelte @@ -279,7 +279,7 @@
- +
@@ -290,8 +290,11 @@
- +
@@ -330,7 +333,7 @@
diff --git a/components/src/maplibre/MapStyle/SWRDataLabLight.ts b/components/src/maplibre/MapStyle/SWRDataLabLight.ts index 7008e140..6efc7fd1 100644 --- a/components/src/maplibre/MapStyle/SWRDataLabLight.ts +++ b/components/src/maplibre/MapStyle/SWRDataLabLight.ts @@ -165,7 +165,7 @@ const style: styleFunction = (opts) => { ...admin, // 8. Labels - ...(options.roads?.showLabels ? walkingLabels : []), + ...(options.roads?.labels !== 'none' ? walkingLabels : []), ...roadLabels, // 9. Building extrusions diff --git a/components/src/maplibre/MapStyle/defaultOptions.ts b/components/src/maplibre/MapStyle/defaultOptions.ts index fc0d4e74..38d413b0 100644 --- a/components/src/maplibre/MapStyle/defaultOptions.ts +++ b/components/src/maplibre/MapStyle/defaultOptions.ts @@ -5,9 +5,6 @@ const opts: StyleOptions = { places: { showLabels: true }, - roads: { - showLabels: true - }, admin: { show: true, showLabels: true From 1a1fabb6f8256b3e1ce1045d655de76d5831bc31 Mon Sep 17 00:00:00 2001 From: Max Kohler Date: Sun, 28 Jun 2026 15:26:01 +0200 Subject: [PATCH 6/6] tweak colours --- components/src/maplibre/MapStyle/components/PlaceLabels.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/src/maplibre/MapStyle/components/PlaceLabels.ts b/components/src/maplibre/MapStyle/components/PlaceLabels.ts index e189da02..1b2b0855 100644 --- a/components/src/maplibre/MapStyle/components/PlaceLabels.ts +++ b/components/src/maplibre/MapStyle/components/PlaceLabels.ts @@ -31,7 +31,7 @@ export default function makePlaceLabels(tokens: styleTokens) { 'text-font': tokens.sans_regular }, paint: { - 'text-halo-color': tokens.building, + 'text-halo-color': tokens.background, 'text-color': tokens.label_secondary } }, @@ -49,7 +49,7 @@ export default function makePlaceLabels(tokens: styleTokens) { 'text-size': { stops: [ [14, 11], - [16, 15] + [16, 18] ] }, 'text-letter-spacing': 0.1, @@ -57,7 +57,7 @@ export default function makePlaceLabels(tokens: styleTokens) { }, paint: { 'text-color': tokens.label_secondary, - 'text-halo-color': tokens.building + 'text-halo-color': tokens.background } }, {