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 <noreply@anthropic.com>
This commit is contained in:
Sociowire Dev 2026-01-13 05:02:48 +00:00
parent fa8134fd41
commit e39f5e8226
1 changed files with 64 additions and 14 deletions

View File

@ -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 }) {
<div class="sw-cluster-left">
<div class="sw-cluster-hero">
<div class="sw-truth-rail" data-score="${truth}">
<button class="sw-truth-rail-btn sw-truth-rail-btn-up" type="button">TRUE</button>
<button class="sw-truth-rail-btn sw-truth-rail-btn-up" type="button" title="Vote TRUE"></button>
<div class="sw-truth-rail-bar">
<div class="sw-truth-rail-marker" style="top:${100 - truth}%"></div>
</div>
<div class="sw-truth-rail-score">${truth}</div>
<button class="sw-truth-rail-btn sw-truth-rail-btn-down" type="button">FALSE</button>
<button class="sw-truth-rail-btn sw-truth-rail-btn-down" type="button" title="Vote FALSE"></button>
</div>
<div class="sw-cluster-hero-media">
${
@ -1345,12 +1346,12 @@ export function openCenteredOverlay({ map, post, theme, fullScreen = false }) {
<div class="sw-modal-hero-row">
${!isCamera ? `
<div class="sw-truth-rail" data-score="${truth}">
<button class="sw-truth-rail-btn sw-truth-rail-btn-up" type="button">TRUE</button>
<button class="sw-truth-rail-btn sw-truth-rail-btn-up" type="button" title="Vote TRUE"></button>
<div class="sw-truth-rail-bar">
<div class="sw-truth-rail-marker" style="top:${100 - truth}%"></div>
</div>
<div class="sw-truth-rail-score">${truth}</div>
<button class="sw-truth-rail-btn sw-truth-rail-btn-down" type="button">FALSE</button>
<button class="sw-truth-rail-btn sw-truth-rail-btn-down" type="button" title="Vote FALSE"></button>
</div>
` : ''}
<div class="sw-modal-hero" ${(isCamera || isVideo) ? 'style="flex:1;max-width:100%;"' : ''}>
@ -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();
}