From d4258d2ff185ebcfc8adbab3d96c8e1bf090956c Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 20 Mar 2026 08:35:42 -0400 Subject: [PATCH] feat: replace showcase tag overlays with ghost count badge, refine nav hint Co-Authored-By: Claude Sonnet 4.6 --- app/static/js/showcase.js | 13 ++++++------- app/static/style.css | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/app/static/js/showcase.js b/app/static/js/showcase.js index 00d8753..0d422fe 100644 --- a/app/static/js/showcase.js +++ b/app/static/js/showcase.js @@ -156,14 +156,13 @@ } item.appendChild(imgEl); - // Filter out archive tags from display (they're still visible in modal) - const visibleTags = (img.tags || []).filter(t => t.kind !== 'archive'); + // Filter out archive and source tags from display (they're still visible in modal) + const visibleTags = (img.tags || []).filter(t => t.kind !== 'archive' && t.kind !== 'source'); if (visibleTags.length > 0) { - const overlay = document.createElement('div'); - overlay.className = 'tag-overlay'; - // Use shared utility to create tag chips - overlay.innerHTML = visibleTags.map(t => createTagChipHtml(t)).join(''); - item.appendChild(overlay); + const badge = document.createElement('span'); + badge.className = 'tag-count-badge'; + badge.textContent = `#${visibleTags.length}`; + item.appendChild(badge); } if (img.is_video) { diff --git a/app/static/style.css b/app/static/style.css index 63cb4ef..7fc6fb6 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -1291,12 +1291,18 @@ header { } .showcase-nav .nav-hint { - color: rgba(255,255,255,0.4); + opacity: 0; + transition: opacity 0.2s ease; font-size: 0.8rem; + color: var(--text-muted); margin-top: 0.25rem; pointer-events: none; } +.showcase-nav:hover .nav-hint { + opacity: 1; +} + /* Masonry container - JS-managed columns */ .masonry-container { display: flex; @@ -1349,6 +1355,35 @@ header { z-index: 2; } +/* Ghost tag count badge on showcase items */ +.tag-count-badge { + position: absolute; + bottom: 8px; + right: 8px; + padding: 2px 7px; + border-radius: 999px; + background: rgba(0, 0, 0, 0.45); + border: 1px solid rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.55); + font-size: 0.7rem; + font-weight: 500; + z-index: 2; + pointer-events: none; + opacity: 0; + transition: opacity 0.2s ease; +} + +.masonry-item:hover .tag-count-badge { + opacity: 1; +} + +/* Touch devices: always show badge */ +@media (hover: none) { + .tag-count-badge { + opacity: 1; + } +} + /* Loading state for shuffle */ .masonry-container.loading { opacity: 0.5;