From e39f5e8226b3342613425831a52fc0c00249d8dc Mon Sep 17 00:00:00 2001 From: Sociowire Dev Date: Tue, 13 Jan 2026 05:02:48 +0000 Subject: [PATCH] fix: z-index on hover for map markers - Simple pins (hover card): z-index 150 on hover - Compact cards: z-index 200 on hover - Ensures hover cards are always above other markers Co-Authored-By: Claude Opus 4.5 --- src/components/Map/markerManager.js | 78 +++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/components/Map/markerManager.js b/src/components/Map/markerManager.js index 1a1a45b..3c245c6 100644 --- a/src/components/Map/markerManager.js +++ b/src/components/Map/markerManager.js @@ -705,6 +705,7 @@ function heroImageForPost(post) { post?.image_large || post?.image_small || post?.image || + post?.thumbnail_url || post?.media_url || ""; const v = normalizeImageUrl(raw); @@ -1263,12 +1264,12 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
- +
${truth}
- +
${ @@ -1345,12 +1346,12 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
${!isCamera ? `
- +
${truth}
- +
` : ''}
@@ -1944,32 +1945,71 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) { const rail = modalWrap.querySelector(".sw-truth-rail"); if (rail && postID > 0 && !rail.hasAttribute("data-vote-bound")) { rail.setAttribute("data-vote-bound", "1"); + // Track current user vote to prevent duplicate API calls + let currentVote = null; // "true", "false", or null + let isVoting = false; + const doVote = async (vote) => { if (!isAuthed()) { requestAuth("Please sign in or create a free account to vote on truth."); return; } - if (rail.classList.contains("sw-truth-vote-disabled")) { - return; // Already voting + // Skip if already voted same way + if (currentVote === vote) { + return; } + if (isVoting) { + return; + } + isVoting = true; + rail.style.opacity = "0.5"; + rail.style.pointerEvents = "none"; try { - rail.classList.add("sw-truth-vote-disabled"); const stats = await votePostTruth(postID, vote); if (stats) { + currentVote = vote; updateTruthVoteUI(modalWrap, stats, true); - } else { - console.warn("votePostTruth returned no stats for post", postID); } } catch (err) { - console.error("Truth vote error:", err); + // Silently fail - don't update UI } finally { - rail.classList.remove("sw-truth-vote-disabled"); + isVoting = false; + rail.style.opacity = "1"; + rail.style.pointerEvents = "auto"; } }; const voteUp = rail.querySelector(".sw-truth-rail-btn-up"); const voteDown = rail.querySelector(".sw-truth-rail-btn-down"); - if (voteUp) voteUp.addEventListener("click", (e) => { e.stopPropagation(); doVote("true"); }); - if (voteDown) voteDown.addEventListener("click", (e) => { e.stopPropagation(); doVote("false"); }); + let touchFired = false; + const handleVote = (vote) => (e) => { + e.preventDefault(); + e.stopPropagation(); + // Prevent touch+click double fire + if (e.type === "touchend") { + touchFired = true; + setTimeout(() => { touchFired = false; }, 400); + } else if (e.type === "click" && touchFired) { + return; + } + if (isVoting || currentVote === vote) return; + doVote(vote); + }; + if (voteUp) { + voteUp.addEventListener("click", handleVote("true"), { passive: false }); + voteUp.addEventListener("touchend", handleVote("true"), { passive: false }); + } + if (voteDown) { + voteDown.addEventListener("click", handleVote("false"), { passive: false }); + voteDown.addEventListener("touchend", handleVote("false"), { passive: false }); + } + // Fetch initial vote state + if (isAuthed()) { + fetchPostTruth(postID).then((stats) => { + if (stats?.user_vote || stats?.UserVote) { + currentVote = (stats.user_vote || stats.UserVote).toString(); + } + }).catch(() => {}); + } } applyAuthUI(); @@ -2145,6 +2185,14 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef, the renderCompact(); root.__renderCompact = renderCompact; + // Bring marker to front on hover so card is above other markers (compact cards = 200) + root.addEventListener("mouseenter", () => { + root.style.zIndex = "200"; + }); + root.addEventListener("mouseleave", () => { + root.style.zIndex = "1"; + }); + if (HEATMAP_ENABLED && isClusterMainPost(post)) { const handleEnter = () => { dispatchClusterHeatmap(root.__post || post, { mode: "hover", skipPan: true }); @@ -2499,8 +2547,9 @@ export function createSimpleMarkerForPost(post, mapRef, markersRef, expandedElRe const markerEl = root.querySelector(".sw-simple-marker"); const hoverCard = root.querySelector(".sw-simple-hover-card"); - // Hover effects + // Hover effects - bring marker to front so hover card is above other markers (simple pins = 150) root.addEventListener("mouseenter", () => { + root.style.zIndex = "150"; if (isCluster) { dispatchClusterHeatmap(root.__post || post, { mode: "hover", skipPan: true }); } @@ -2515,6 +2564,7 @@ export function createSimpleMarkerForPost(post, mapRef, markersRef, expandedElRe }); root.addEventListener("mouseleave", () => { + root.style.zIndex = isWeatherPost ? "10" : "2"; if (isCluster) { dispatchClusterHeatmapClear(); }