[FEAT] collage: empty nest blooms in, and clicking it no longer opens a bird (#26)

This commit is contained in:
Teddy Warner
2026-07-06 18:55:56 -07:00
committed by GitHub
parent 54d241e184
commit 57e146fa0b
2 changed files with 28 additions and 0 deletions
+16
View File
@@ -412,6 +412,12 @@
function renderCollage(items, animate) {
collage.innerHTML = '';
// Drop the previous render's hit-test tiles up front so a click or hover on
// the empty-nest state (or a collage that hasn't laid out yet) resolves to
// nothing, not to a stale bird from the last populated render. The populated
// path repopulates collagePlaced once the new tiles are placed.
collagePlaced = [];
collageHovered = null;
if (!items.length) {
// No birds heard yet: show an empty nest where the collage would be, with
// the status line beneath it. The frame (shoot.py) overrides the .empty
@@ -419,6 +425,16 @@
collage.innerHTML = '<div class="empty-nest">' +
'<img class="nest-img" src="nest.webp" alt="an empty nest" decoding="async">' +
'<p class="empty">no birds heard in this window.</p></div>';
// Bloom the nest in on the same cues as the collage (first load, window
// change, view switch); a silent poll/resize renders without animate. The
// class self-clears after the worst case so a throttled tab still ends
// with the nest visible, mirroring the tile entrance's safety net.
if (animate) {
var enest = collage.firstChild;
enest.classList.add('entering');
clearTimeout(collageEntranceT);
collageEntranceT = setTimeout(function () { enest.classList.remove('entering'); }, 900);
}
return;
}
var W = collage.clientWidth, H = collage.clientHeight;
+12
View File
@@ -602,6 +602,18 @@
}
.empty-nest .nest-img { width: 78%; max-width: 470px; height: auto; }
.empty-nest .empty { padding: 0; margin: 0; }
/* Bloom the empty nest in on the same cues as the collage, reusing the tile
keyframe (gtile-in): the nest fades + scales, the status line trails it. */
.empty-nest.entering .nest-img {
animation: gtile-in 420ms cubic-bezier(.2, .7, .3, 1) backwards;
}
.empty-nest.entering .empty {
animation: gtile-in 420ms cubic-bezier(.2, .7, .3, 1) 130ms backwards;
}
@media (prefers-reduced-motion: reduce) {
.empty-nest.entering .nest-img,
.empty-nest.entering .empty { animation: none; }
}
/* Page header is now shared at .stage > .static-head - see top of CSS. */
/* Stats grid: charts stack on the LEFT, text sections on the RIGHT.