map: mount without waiting on the 500-call window; legend collapsible, hidden under open layers list
The Live map was held behind useCalls(500), measured at ~9.2s to first map paint on prod; it now mounts as soon as the saved view is known (nodes are awaited only when there is no view). The legend painted over the expanded Leaflet layers list (z-1001 vs the map's z-0 stacking context): it is now a <details> that hides while the list is open and starts folded on short viewports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
df837d7d81
commit
cc41d1badb
@@ -193,6 +193,13 @@ html:not(.dark) .border-indigo-800 { border-color: #c8ccf6 !important; }
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The legend floats above the map's stacking context, so it would cover the
|
||||||
|
* expanded layers list (both live in the right-hand column). Hide it while the
|
||||||
|
* list is open. */
|
||||||
|
.relative:has(.leaflet-control-layers-expanded) > .drb-legend {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* "Dark" base layer (#136): the prod tile URL is bright OSM, so dark-theme
|
/* "Dark" base layer (#136): the prod tile URL is bright OSM, so dark-theme
|
||||||
* overlay cards sat on a bright, busy map. Inverting the raster keeps the
|
* overlay cards sat on a bright, busy map. Inverting the raster keeps the
|
||||||
* keyless OSM source (CARTO's dark_all CDN proved flaky, #117) while giving
|
* keyless OSM source (CARTO's dark_all CDN proved flaky, #117) while giving
|
||||||
|
|||||||
@@ -560,7 +560,11 @@ export function LiveView() {
|
|||||||
{/* Degraded → grey the map and its incident rail (the rail lives inside
|
{/* Degraded → grey the map and its incident rail (the rail lives inside
|
||||||
MapView, so it is wrapped here rather than edited). */}
|
MapView, so it is wrapped here rather than edited). */}
|
||||||
<div className={`w-full h-full transition-[filter,opacity] ${health.degraded ? "grayscale opacity-60" : ""}`}>
|
<div className={`w-full h-full transition-[filter,opacity] ${health.degraded ? "grayscale opacity-60" : ""}`}>
|
||||||
{nodesLoading || callsLoading || !mapState ? (
|
{/* Mount the map as soon as its starting view is known. The 500-call
|
||||||
|
window took ~9s on prod and used to hold the whole map back;
|
||||||
|
calls and paths now stream in once it lands. Nodes are only
|
||||||
|
awaited when there's no saved view, since they pick the centre. */}
|
||||||
|
{!mapState || (!mapState.view && nodesLoading) ? (
|
||||||
<div className="w-full h-full flex items-center justify-center text-ink-muted text-sm">Loading map…</div>
|
<div className="w-full h-full flex items-center justify-center text-ink-muted text-sm">Loading map…</div>
|
||||||
) : (
|
) : (
|
||||||
<MapView
|
<MapView
|
||||||
|
|||||||
@@ -1620,6 +1620,9 @@ function MapView({
|
|||||||
const [wxShown, setWxShown] = useState(() => startLayers.has("wx"));
|
const [wxShown, setWxShown] = useState(() => startLayers.has("wx"));
|
||||||
const [radarLoop, setRadarLoop] = useState(false); // off by default (#237); not persisted
|
const [radarLoop, setRadarLoop] = useState(false); // off by default (#237); not persisted
|
||||||
const loopClock = useMemo(createLoopClock, []);
|
const loopClock = useMemo(createLoopClock, []);
|
||||||
|
// Short viewports (laptops, the 352px incident-page map) start with the
|
||||||
|
// legend folded to a chip so it doesn't cover the right side of the map.
|
||||||
|
const [legendOpenAtStart] = useState(() => typeof window === "undefined" || window.innerHeight >= 760);
|
||||||
|
|
||||||
// The altitude key only belongs in the legend while the opt-in Aircraft
|
// The altitude key only belongs in the legend while the opt-in Aircraft
|
||||||
// overlay is actually on (server-26#185); same for the outage key (#184).
|
// overlay is actually on (server-26#185); same for the outage key (#184).
|
||||||
@@ -1931,7 +1934,14 @@ function MapView({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ── Legend — shape-first, both themes. Never a bare colour swatch. ──── */}
|
{/* ── Legend — shape-first, both themes. Never a bare colour swatch. ──── */}
|
||||||
<div className="absolute bottom-8 right-3 z-[1001] bg-surface/90 border border-line rounded-lg px-3 py-2.5 text-xs pointer-events-none space-y-2 max-h-[calc(100%-4rem)] overflow-y-auto">
|
{/* Collapsible (one click to a "Legend" chip) and hidden while the Leaflet
|
||||||
|
layers list is expanded: the map sits in a z-0 stacking context, so the
|
||||||
|
legend at z-1001 used to paint over the bottom of that list. */}
|
||||||
|
<details open={legendOpenAtStart} className="drb-legend group/legend absolute bottom-8 right-3 z-[1001] bg-surface/90 border border-line rounded-lg text-xs pointer-events-none max-h-[calc(100%-4rem)] overflow-y-auto">
|
||||||
|
<summary className="pointer-events-auto cursor-pointer list-none select-none px-3 py-1.5 text-ink-muted font-medium text-[10px] uppercase tracking-wide flex items-center gap-1.5">
|
||||||
|
<span className="group-open/legend:hidden">▸</span><span className="hidden group-open/legend:inline">▾</span> Legend
|
||||||
|
</summary>
|
||||||
|
<div className="px-3 pb-2.5 space-y-2">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<p className="text-ink-muted font-medium text-[10px] uppercase tracking-wide">Severity</p>
|
<p className="text-ink-muted font-medium text-[10px] uppercase tracking-wide">Severity</p>
|
||||||
{(["major", "moderate", "minor", "routine"] as Severity[]).map((sev) => (
|
{(["major", "moderate", "minor", "routine"] as Severity[]).map((sev) => (
|
||||||
@@ -2070,7 +2080,8 @@ function MapView({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
{/* ── Incident overlay panel ───────────────────────────────────────────── */}
|
{/* ── Incident overlay panel ───────────────────────────────────────────── */}
|
||||||
{incidents.length > 0 && (
|
{incidents.length > 0 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user