attribution icon tweaks

Hunter
Sunday, August 30th, 2026 at 10:04 PM

resources/map.js+35-4
resources/styles.css+24-1

resources/map.js
 74  
 75  		map.getCanvas().setAttribute("tabindex", "-1");
 76  
    -		map.addControl(new maplibregl.AttributionControl({ compact: true }), "bottom-left");
    -		collapseAttribution();
 77 +		map.addControl(new maplibregl.AttributionControl({ compact: true }), "top-right");
 78 +		initAttribution();
 79  
 80  		var endWheelGesture = initSmoothWheel();
 81  

238  		return settle;
239  	}
240  
    -	function collapseAttribution() {
241 +	// Collapses the compact attribution once the style names its sources, then takes
242 +	// the button over from maplibre so a tap anywhere else can dismiss it.
243 +	function initAttribution() {
244  		var el = map.getContainer().querySelector(".maplibregl-ctrl-attrib");
245  		if (!el) { return; }
246 +		var button = el.querySelector(".maplibregl-ctrl-attrib-button");
247 +
248 +		function shown() { return el.classList.contains("maplibregl-compact-show"); }
249 +
250 +		// maplibre's own handler pre-flips `open` so the native <details> toggle lands
251 +		// on the right value; we suppress both, so `open` just tracks the panel
252 +		function setShown(show) {
253 +			el.classList.toggle("maplibregl-compact-show", show);
254 +			if (show) { el.setAttribute("open", ""); } else { el.removeAttribute("open"); }
255 +		}
256 +
257 +		if (button) {
258 +			// capture on the container beats maplibre's own listener on the button;
259 +			// preventDefault also keeps the native <details> from double-toggling
260 +			el.addEventListener("click", function (e) {
261 +				if (!button.contains(e.target)) { return; }
262 +				e.preventDefault();
263 +				e.stopPropagation();
264 +				setShown(!shown());
265 +			}, true);
266 +		}
267 +
268 +		// anything else on the page dismisses it; capture on the document so a
269 +		// stopPropagation further in (the event pins do it) can't swallow the tap
270 +		document.addEventListener("click", function (e) {
271 +			if (button && button.contains(e.target)) { return; }
272 +			if (shown()) { setShown(false); }
273 +		}, true);
274 +
275  		function collapse() {
276  			if (!el.classList.contains("maplibregl-compact")) { return; } // no text yet
    -			el.classList.remove("maplibregl-compact-show");
277 +			setShown(false);
278  			map.off("sourcedata", collapse);
279  			map.off("styledata", collapse);
280  		}
resources/styles.css
254  	inset: 0;
255  }
256  
257 +.maplibregl-canvas-container {
258 +	isolation: isolate;
259 +}
260 +
261  .maplibregl-ctrl-attrib.maplibregl-compact {
262  	margin: 12px;
263  	background: rgba(255, 255, 255, 0.7);

266  	box-shadow: 0 1px 3px #00000040;
267  	-webkit-tap-highlight-color: transparent;
268  }
269 +/* the standalone status-bar tint band is the real top edge; sit below it */
270 +@media (display-mode: standalone) {
271 +	.maplibregl-ctrl-attrib.maplibregl-compact {
272 +		margin-top: calc(12px + var(--status-tint-h));
273 +	}
274 +}
275  .maplibregl-ctrl-attrib-button {
276  	background-color: transparent;
    -	background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%237a7f85' fill-rule='evenodd' viewBox='0 0 20 20'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E");
277 +	background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%237a7f85' fill-opacity='0.8' fill-rule='evenodd' viewBox='0 0 20 20'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E");
278  }
279  
280  .maplibregl-ctrl-attrib.maplibregl-compact-show .maplibregl-ctrl-attrib-button,

290  	box-shadow: 0 0 2px 2px #0096ff;
291  }
292  
293 +/* mirrors the compass: pad the tap target out to the map corner */
294 +@media (pointer: coarse) {
295 +	.maplibregl-ctrl-attrib-button::after {
296 +		content: "";
297 +		position: absolute;
298 +		top: -12px;
299 +		right: -12px;
300 +		bottom: 0;
301 +		left: 0;
302 +		border-radius: 0 0 0 12px;
303 +	}
304 +}
305 +
306  #compass {
307  	display: none;
308  	position: absolute;