Make airport markers minimal and de-cluttered for global airport density (#5)

* Initial plan

* chore: outline plan for global airport dataset update

Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>

* feat: expand airport dataset to 9k+ global airports

Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>

* feat: make airport dots subtle and resilient

Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>
This commit is contained in:
Copilot
2026-02-16 01:41:02 +05:30
committed by GitHub
parent 06956f8b59
commit 5125107d5b
3 changed files with 70706 additions and 1165 deletions

View File

@ -15,18 +15,34 @@ type AirportLayerProps = {
isDark: boolean; isDark: boolean;
}; };
function isValidCoordinates(
coordinates: readonly [number, number],
): coordinates is [number, number] {
const [lng, lat] = coordinates;
return (
Number.isFinite(lng) &&
Number.isFinite(lat) &&
lng >= -180 &&
lng <= 180 &&
lat >= -90 &&
lat <= 90
);
}
const airportGeoJson: GeoJSON.FeatureCollection = { const airportGeoJson: GeoJSON.FeatureCollection = {
type: "FeatureCollection", type: "FeatureCollection",
features: AIRPORTS.map((a) => ({ features: AIRPORTS.filter((a) => isValidCoordinates([a.lng, a.lat])).map(
type: "Feature" as const, (a) => ({
geometry: { type: "Point" as const, coordinates: [a.lng, a.lat] }, type: "Feature" as const,
properties: { geometry: { type: "Point" as const, coordinates: [a.lng, a.lat] },
iata: a.iata, properties: {
name: a.name, iata: a.iata,
city: a.city, name: a.name,
country: a.country, city: a.city,
}, country: a.country,
})), },
}),
),
}; };
const LAYER_CSS = ` const LAYER_CSS = `
@ -75,8 +91,9 @@ export function AirportLayer({
injectCSS(); injectCSS();
const m = map; const m = map;
const dotColor = isDark ? "rgba(74,222,128,0.6)" : "rgba(22,163,74,0.55)"; const dotColor = isDark
const strokeColor = isDark ? "rgba(74,222,128,0.8)" : "rgba(22,163,74,0.7)"; ? "rgba(167,243,208,0.28)"
: "rgba(15,118,110,0.22)";
function addSourceAndLayers() { function addSourceAndLayers() {
if (m.getSource(SOURCE_ID)) return; if (m.getSource(SOURCE_ID)) return;
@ -89,21 +106,29 @@ export function AirportLayer({
source: SOURCE_ID, source: SOURCE_ID,
paint: { paint: {
"circle-radius": [ "circle-radius": [
"step",
["zoom"],
0.55,
6,
0.8,
10,
1.05,
14,
1.35,
],
"circle-color": dotColor,
"circle-opacity": [
"interpolate", "interpolate",
["linear"], ["linear"],
["zoom"], ["zoom"],
3,
2, 2,
6, 0.14,
3, 8,
10, 0.22,
4.5,
14, 14,
7, 0.34,
], ],
"circle-color": dotColor, "circle-stroke-width": 0,
"circle-stroke-width": 1,
"circle-stroke-color": strokeColor,
}, },
}); });
} }
@ -127,11 +152,12 @@ export function AirportLayer({
m.getCanvas().style.cursor = "pointer"; m.getCanvas().style.cursor = "pointer";
const f = e.features?.[0]; const f = e.features?.[0];
if (f?.properties) { if (f?.properties) {
const iata = String(f.properties.iata ?? "").toUpperCase();
const city = String(f.properties.city ?? "");
if (!iata) return;
popup popup
.setLngLat(e.lngLat) .setLngLat(e.lngLat)
.setHTML( .setText(city ? `${iata} · ${city}` : iata)
`<strong>${f.properties.iata}</strong> · ${f.properties.city}`,
)
.addTo(m); .addTo(m);
} }
} }
@ -147,8 +173,9 @@ export function AirportLayer({
}, },
) { ) {
const f = e.features?.[0]; const f = e.features?.[0];
if (f?.properties?.iata) { const iata = String(f?.properties?.iata ?? "");
const city = resolveCity(f.properties.iata as string); if (iata) {
const city = resolveCity(iata);
callbackRef.current(city); callbackRef.current(city);
} }
} }
@ -183,6 +210,7 @@ export function AirportLayer({
'<div class="airport-beacon-ring"></div>' + '<div class="airport-beacon-ring"></div>' +
'<div class="airport-beacon-ring"></div>' + '<div class="airport-beacon-ring"></div>' +
'<div class="airport-beacon-core"></div>'; '<div class="airport-beacon-core"></div>';
if (!isValidCoordinates(activeCity.coordinates)) return;
const marker = new maplibregl.Marker({ element: el }) const marker = new maplibregl.Marker({ element: el })
.setLngLat(activeCity.coordinates) .setLngLat(activeCity.coordinates)

View File

@ -484,7 +484,7 @@ function SearchContent({
{!query && ( {!query && (
<p className="px-3 pt-3 pb-1 text-center text-[10px] font-medium text-white/10"> <p className="px-3 pt-3 pb-1 text-center text-[10px] font-medium text-white/10">
Search 400+ airports worldwide Search 9,000+ airports worldwide
</p> </p>
)} )}
</div> </div>

File diff suppressed because it is too large Load Diff