From 02dd83e51643432bdfb0b97d6baf64c77150c583 Mon Sep 17 00:00:00 2001 From: Teddy Warner Date: Thu, 11 Jun 2026 18:55:07 -0700 Subject: [PATCH] [FEAT] atlas: sticky sort bar + 1K card counts + trimmed empty hint (#7) --- avian/frontend/apt.js | 17 +++++++++++------ avian/frontend/styles.css | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/avian/frontend/apt.js b/avian/frontend/apt.js index b401b23..63c83b4 100644 --- a/avian/frontend/apt.js +++ b/avian/frontend/apt.js @@ -806,6 +806,11 @@ if (n >= 10000) return (n / 1000).toFixed(1) + 'k'; return n.toLocaleString(); } + // Compact count for atlas cards (1K, 1.2K); the modal keeps the exact number. + function fmtNK(n) { + if (n == null) return '-'; + return n < 1000 ? n.toLocaleString() : +(n / 1000).toFixed(1) + 'K'; + } // Human label for the current time-window picker selection - replaces // a bare "window" with the span it actually covers. Thresholds match // the winPick buttons (1H / 12H / 24H / 7D / ALL). @@ -1118,7 +1123,7 @@ if (!filtered.length) { grid.innerHTML = '
' + '

No detections in this window.

' + - '

Try a longer time window - the lifelist is still here under ALL.

' + + '

Try a longer time window.

' + '
'; return; } @@ -1158,9 +1163,9 @@ // all-time count - collapse to a single stat rather than print the // same number twice. Otherwise label the count with its span. var statRows = currentHours >= 1000000 - ? '
' + fmtN(total) + 'all time
' - : '
' + fmtN(win) + '' + windowLabel(currentHours) + '
' - + '
' + fmtN(total) + 'all time
'; + ? '
' + fmtNK(total) + 'all time
' + : '
' + fmtNK(win) + '' + windowLabel(currentHours) + '
' + + '
' + fmtNK(total) + 'all time
'; return '' + '
' + (isLifer ? 'lifer' : '') @@ -2070,9 +2075,9 @@ loadSpecies.then(function (j) { var s = j.summary || {}; document.getElementById('modalCommon').textContent = s.com || sci; - document.getElementById('modalAllTime').textContent = fmtN(+s.total || 0); + document.getElementById('modalAllTime').textContent = (+s.total || 0).toLocaleString(); var winRow = ((DATA.recent && DATA.recent.species) || []).filter(function (x) { return x.sci === sci; })[0]; - document.getElementById('modalWindow').textContent = fmtN(winRow ? +winRow.n : 0); + document.getElementById('modalWindow').textContent = (winRow ? +winRow.n : 0).toLocaleString(); document.getElementById('modalFirstSeen').textContent = s.first_seen ? fmtRecTime(s.first_seen.split(' ')[0], s.first_seen.split(' ')[1]) : '-'; var rar = rarityLabel(+s.total || 0, s.first_seen); var rarEl = document.getElementById('modalRarity'); diff --git a/avian/frontend/styles.css b/avian/frontend/styles.css index be45bdb..6071205 100644 --- a/avian/frontend/styles.css +++ b/avian/frontend/styles.css @@ -792,9 +792,15 @@ names, window/all-time detection counts, and small action chips for audio playback, Wikipedia, and eBird. */ .atlas-controls { + /* The bar is transparent and floats (z-index) over the scrolling cards; + only the pill is opaque. Cards scroll behind it and clip at the top of + the view, under the title, as they did before it was pinned. */ + position: sticky; top: 0; z-index: 2; max-width: 1280px; margin: 0 auto 18px; display: flex; justify-content: flex-end; align-items: center; + pointer-events: none; } + .atlas-sort { pointer-events: auto; } .atlas-sort { display: inline-flex; padding: 3px; position: relative; background: var(--paper-2); border-radius: 999px;