Skip to content

Commit aedf8ff

Browse files
authored
Embed pin: right-side overlay that does not shift the map (#29)
When a country is pinned inside an embedded /embed iframe, render the detail panel as an absolute overlay anchored at the canvas top-right instead of pushing the map sideways or stacking it underneath. Key properties: - position: absolute so the pin is entirely out of the layout flow. Opening the pin does not change the canvas size, position or the rendered map (verified: Sweden's bounding rect is byte-identical before and after the pin opens in /embed?chrome=minimal). - Top offset is calc(36px + 0.5rem) when the toolbar is visible and 0.5rem when the toolbar is hidden, so the pin sits flush with the canvas top with equal 0.5rem inset from the right edge in both modes. - 'Open full profile -> ' link opens in a new tab so embedding hosts do not navigate away when a reader explores a country.
1 parent 4058fdd commit aedf8ff

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

src/components/EuropeMap.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ export default function EuropeMap({filterStatus = null, pinnedIso = null, onPin}
407407
<a
408408
className="europe-map__pin-cta"
409409
href={`/tracker/${slug(pinnedCountry.name)}`}
410+
target="_blank"
411+
rel="noopener"
410412
>
411413
Open full profile <span aria-hidden></span>
412414
</a>

src/css/custom.css

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2130,7 +2130,12 @@ body.is-embed .europe-map__zoom {
21302130
/* Iframe embed mode: strip chrome, fill the iframe viewport */
21312131
body.is-embed {
21322132
background: var(--ifm-background-color);
2133-
overflow: auto;
2133+
/* No body scroll in embed mode - the map provides its own zoom + pan
2134+
controls, and a scrollbar inside the host's iframe is visual noise. */
2135+
overflow: hidden;
2136+
}
2137+
html:has(body.is-embed) {
2138+
overflow: hidden;
21342139
}
21352140
body.is-embed .navbar,
21362141
body.is-embed .footer,
@@ -2202,6 +2207,45 @@ body.is-embed.embed--no-legend.embed--no-chrome .europe-map {
22022207
body.is-embed .europe-map__toolbar {
22032208
padding: 0.1rem 0.3rem 0.2rem;
22042209
}
2210+
2211+
/* In embed mode the country detail panel slides in as an absolute overlay
2212+
on the right side of the canvas. Using `position: absolute` keeps the
2213+
pin completely out of the flex/grid layout flow so it does NOT change
2214+
the canvas size when toggled on. Anchor the panel to the canvas (which
2215+
is made `position: relative`) so its top edge sits exactly at the
2216+
canvas top, regardless of toolbar height. */
2217+
body.is-embed .europe-map-frame--pin-open {
2218+
display: flex !important;
2219+
flex-direction: column;
2220+
position: relative;
2221+
}
2222+
body.is-embed .europe-map-frame--pin-open > .europe-map__canvas {
2223+
position: relative;
2224+
width: 100%;
2225+
}
2226+
body.is-embed .europe-map-frame--pin-open > .europe-map__pin {
2227+
position: absolute;
2228+
/* Anchor to the bottom of the toolbar (toolbar lives above canvas in
2229+
flex flow). With toolbar visible the toolbar's rendered height is the
2230+
pin's natural offset; absolute positioning relative to frame means we
2231+
add the toolbar height + 0.5rem inset. */
2232+
top: 0.5rem;
2233+
right: 0.5rem;
2234+
margin: 0;
2235+
width: min(320px, calc(100% - 1rem));
2236+
max-height: calc(100% - 1rem);
2237+
overflow-y: auto;
2238+
z-index: 6;
2239+
background: var(--tracker-surface);
2240+
border: 1px solid var(--tracker-hairline-strong);
2241+
border-radius: var(--tracker-card-radius);
2242+
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
2243+
}
2244+
/* When the toolbar is visible, drop the overlay below it (toolbar is
2245+
~36px). 36 + 8 (0.5rem inset) = 44px from frame top. */
2246+
body.is-embed:not(.embed--no-toolbar):not(.embed--no-chrome) .europe-map-frame--pin-open > .europe-map__pin {
2247+
top: calc(36px + 0.5rem);
2248+
}
22052249
.embed-attribution {
22062250
display: flex;
22072251
justify-content: space-between;

0 commit comments

Comments
 (0)