artist page: put the load status in the chip row it hands over to
The floating pill worked but sat in the wrong place and at the wrong scale: top right of the pane, far from the content it describes, 30px tall with 12px text against a row of 27px chips at 11.5px. The stat chips are gated on `!page.art_preview` -- they do not exist yet while the page resolves. So the status simply takes their slot and hands the row over when they arrive: same container, same `.chip` metrics, with only a spinning accent ring and a softer label colour of its own. Measured across the handover, the status chip and the first real chip occupy the identical box (x 230, y 1145, height 27), and neither the row top nor the play button moves. That also keeps the property the floating version was chosen for. Nothing reflows when the status goes, because it is the only thing in the row and the chips that replace it start at the same origin -- no absolute positioning, no z-index fight with the sticky .results-head, and no element parked outside the layout it belongs to.
This commit is contained in:
1 parent
d67df6f55e
commit
8e623e3d8d
1 file changed
+27
-45
@@ -3423,14 +3423,6 @@
|
||||
single pixel of content. It must NOT live in .fade-flow with the
|
||||
rest of the body: that carries a transform and sits inside the
|
||||
clipped .fade-frame, which would both re-anchor and mask it. -->
|
||||
{#if page.art_preview}
|
||||
<div class="stage-pill" role="status" aria-live="polite">
|
||||
<span class="ring" aria-hidden="true"></span>
|
||||
{page.albums.length || popularTracks.length
|
||||
? "Refining release details"
|
||||
: "Loading songs and releases"}
|
||||
</div>
|
||||
{/if}
|
||||
<!-- ROUND 12, "three layers" (the user's own model, mocked and
|
||||
approved as research/artist-header-scroll/v12-three-layers.html
|
||||
build 5). Content on top (z 3) → the page background SHEET with
|
||||
@@ -3752,6 +3744,22 @@
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- The stat chips do not exist yet while the page is
|
||||
resolving, so the load status simply occupies
|
||||
their slot and hands the row over when they
|
||||
arrive. Same container, same chip metrics: the
|
||||
row's height never changes, so nothing below it
|
||||
moves — which is what the old in-flow paragraph
|
||||
above the actions got wrong. -->
|
||||
<div class="stat-chips">
|
||||
<span class="chip stage-chip" role="status" aria-live="polite">
|
||||
<span class="ring" aria-hidden="true"></span>
|
||||
{page.albums.length || popularTracks.length
|
||||
? "Refining release details"
|
||||
: "Loading songs and releases"}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -6259,61 +6267,35 @@
|
||||
contain-intrinsic-size: auto 360px;
|
||||
}
|
||||
|
||||
/* Transient load status, pinned to the pane's top-right and out of flow.
|
||||
It shares the top band with the sticky .results-head (z-index 40), which
|
||||
is why this has to clear 40 rather than merely clearing .scrollbody's 3 —
|
||||
at any lower value the bar paints straight over it and the pill is
|
||||
invisible with no other symptom. */
|
||||
.stage-pill {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 20px;
|
||||
z-index: 41;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
height: 30px;
|
||||
padding: 0 14px;
|
||||
border-radius: 15px;
|
||||
background: rgba(14, 14, 16, 0.72);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 6px 22px rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(14px);
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
/* Load status wearing the stat chip's own metrics — it stands in for those
|
||||
chips while they resolve, so it must measure exactly like them or the row
|
||||
changes height as it hands over. Inherits .chip for everything but the
|
||||
spinner and the slightly softer label colour. */
|
||||
.stage-chip {
|
||||
gap: 8px;
|
||||
color: rgba(255, 255, 255, 0.62);
|
||||
pointer-events: none;
|
||||
animation: stage-pill-in 180ms ease-out;
|
||||
}
|
||||
|
||||
.stage-pill .ring {
|
||||
.stage-chip .ring {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--accent);
|
||||
border-right-color: transparent;
|
||||
animation: stage-pill-spin 0.9s linear infinite;
|
||||
animation: stage-chip-spin 0.9s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes stage-pill-spin {
|
||||
@keyframes stage-chip-spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes stage-pill-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
|
||||
/* The spinner is decoration; honour a reduced-motion preference by holding
|
||||
it still rather than removing the only signal that work is happening. */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.stage-pill,
|
||||
.stage-pill .ring {
|
||||
.stage-chip .ring {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user