forked from Keelrleek/SoulStream
navigation: state the bar's geometry instead of collapsing a margin for it
Hoisting the glass bar out of the pages (8017c0d) dropped the artist page's
hero 24px, so the artwork began below the bar instead of running under it.
The bar used to be each page's FIRST CHILD, and its `margin-top: -24px`
collapsed through the page root -- pulling `.artist-page` itself up to the
top of the pane, where the hero could sit behind the bar. As a sibling it
cannot do that, so the root fell back to the pane's padding edge and took
the artwork with it: `.artist-page` is `position: relative` and the whole
`.hero-bg` stack is positioned against its box.
Diffing every element in the page against the previous build, 16 moved and
all by exactly +24: .hero-bg, .hero-seed, .gpu-hero, canvas.banner (the
visible one), the twins, .seam-clip/.seam-tail and .sheetclip. The other 94
did not move at all -- the flow content was never the problem, which is why
this did not show up as content shifting.
That geometry is now stated rather than emergent. The bar's margin-bottom
is -bar-h, so its net flow contribution is -pane-pad: it consumes no height
of its own AND cancels the pane's top padding, leaving the page's box flush
with the top of the pane. Each page under the bar hands that inset back with
`padding-top: var(--pane-pad)`, which is a no-op for the hero (padding does
not move a positioned ancestor's padding-box top) and restores every flow
child. The pane's 24px is now a named custom property rather than a number
repeated in four rules with a comment warning they are tied.
Verified against the pre-hoist build element by element: 87 artist-page
elements compared, ZERO moved, including canvas.banner back at 84 and the
Fanart wordmark at 883. Album page root 38, hero 62, tracklist 514 --
identical. The bar still paints above the hero (elementFromPoint at its
centre returns the bar), arrival still animates only the arriving crumb,
Back still animates nothing, and a page with no bar is untouched at the
pane's padding edge. 85 JS tests pass.
The verification that let this through checked the page's top against my own
model of the layout rather than against the previous build, and the model
omitted margin collapsing. The before/after element diff above is the check
that would have caught it.
This commit is contained in:
1 parent
8017c0d877
commit
35729c1f9e
4 files changed
+59
-15
No files matched your search
+14
-4
@@ -44,7 +44,12 @@
|
||||
here and lives above whichever view is current — see the note at the top
|
||||
of GlassBar.svelte for what a per-view instance cost. Views that do not
|
||||
show it yet hide it; the component is never unmounted, so its crumb
|
||||
memory survives every navigation, including out to Home and back. */
|
||||
memory survives every navigation, including out to Home and back.
|
||||
|
||||
A page added here MUST also take `padding-top: var(--pane-pad)`: the bar
|
||||
cancels the pane's top padding so a page's artwork can run underneath it,
|
||||
and the page restores that inset for its own content. Without it the page
|
||||
renders 24px too high; with it but not listed here, 24px too low. */
|
||||
const BAR_VIEWS = new Set(["catalogArtist", "catalogAlbum"]);
|
||||
|
||||
initEvents();
|
||||
@@ -72,8 +77,9 @@
|
||||
<main class="content" use:floatScroll inert={previewUi.open || undefined}>
|
||||
<!-- First child of the scroll pane: the bar's sticky pin and its
|
||||
negative bleed margins are measured against THIS element's
|
||||
padding, and its net flow height is zero, so the page below still
|
||||
starts exactly where it did when each view carried its own. -->
|
||||
padding. It consumes no flow height of its own AND cancels the
|
||||
pane's top padding, so the page after it begins flush with the top
|
||||
of the pane and its artwork runs under the bar. -->
|
||||
<GlassBar hidden={!BAR_VIEWS.has(ui.view)} />
|
||||
<CurrentView />
|
||||
</main>
|
||||
@@ -137,12 +143,16 @@
|
||||
away with the content, keeping the seam colors identical at every
|
||||
scroll position. */
|
||||
background-attachment: local;
|
||||
/* The pane's top padding, named because three other rules are tied to
|
||||
it: the glass bar bleeds up over it, cancels it for what follows, and
|
||||
each page under the bar restores it as its own padding-top. */
|
||||
--pane-pad: 24px;
|
||||
border-radius: var(--radius);
|
||||
overflow-y: auto;
|
||||
overflow-anchor: none;
|
||||
/* Main scroll pane: no elastic rubber-band at its edges. Inner regions
|
||||
deliberately do NOT set this, so their wheel chains here. */
|
||||
overscroll-behavior: none;
|
||||
padding: 24px 28px;
|
||||
padding: var(--pane-pad) 28px;
|
||||
}
|
||||
</style>
|
||||
@@ -125,23 +125,43 @@
|
||||
|
||||
<style>
|
||||
.glassbar {
|
||||
--bar-h: 46px;
|
||||
/* Sticky rather than absolute, so the bar pins to the top of the pane
|
||||
and stays there as the page scrolls. The negative margins reproduce
|
||||
an absolute bleed while keeping the bar in normal flow: -24/-28 bleed
|
||||
it up over the pane's 24px top padding and out to its left/right
|
||||
edges, and margin-bottom -22 makes its net flow height ZERO
|
||||
(-24 + 46 - 22 = 0) so the hero beneath it is not pushed down.
|
||||
`top: -24px` pins it flush against the very top of the pane, over
|
||||
that padding. All four numbers are tied to the pane's own 24/28px
|
||||
padding — change one and the seam opens. */
|
||||
and stays there as the page scrolls, and `top` pins it flush against
|
||||
the very top of the pane over that padding.
|
||||
|
||||
The negative margins reproduce an absolute bleed while keeping the
|
||||
bar in normal flow, and they do TWO jobs:
|
||||
|
||||
margin-top -pane-pad : bleed up over the pane's top padding
|
||||
(and -28 out to its left/right edges)
|
||||
margin-bottom -bar-h : consume no flow height of its own, and
|
||||
cancel the pane's top padding for what follows
|
||||
|
||||
so the net flow contribution is -pane-pad, and the PAGE's box after
|
||||
it starts flush with the top of the pane — which is what lets a hero
|
||||
run underneath the bar rather than beginning below it. Each page
|
||||
under the bar restores its own content inset with
|
||||
`padding-top: var(--pane-pad)`; see the note by BAR_VIEWS in
|
||||
App.svelte.
|
||||
|
||||
This used to come from margin collapsing instead: the bar was each
|
||||
page's first child, and its negative top margin collapsed through the
|
||||
page root and pulled it up. Hoisting the bar out ended the collapse
|
||||
and dropped every artist-page hero layer 24px (the `.hero-bg` stack
|
||||
is absolutely positioned against `.artist-page`), so the geometry is
|
||||
stated here rather than emerging from where the bar happens to sit.
|
||||
|
||||
All of these are tied to the pane's own padding — change one and the
|
||||
seam opens. */
|
||||
position: sticky;
|
||||
top: -24px;
|
||||
margin: -24px -28px -22px;
|
||||
top: calc(-1 * var(--pane-pad));
|
||||
margin: calc(-1 * var(--pane-pad)) -28px calc(-1 * var(--bar-h));
|
||||
/* Above the artist page's pinned identity (30) and hero (20): the bar
|
||||
keeps the top of the pane to itself and the parked wordmark slides
|
||||
under it. */
|
||||
z-index: 40;
|
||||
height: 46px;
|
||||
height: var(--bar-h);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
@@ -758,6 +758,14 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* The glass bar cancels the pane's top padding so a page's box starts
|
||||
flush with the top of the pane and its artwork can run under the bar.
|
||||
This page's hero is in normal flow rather than positioned against the
|
||||
root, so it only needs that inset handed back. */
|
||||
.album-page {
|
||||
padding-top: var(--pane-pad);
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: var(--text-secondary);
|
||||
padding-top: 10vh;
|
||||
|
||||
@@ -4932,6 +4932,12 @@
|
||||
.artist-page {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
/* The glass bar cancels the pane's top padding so this page's box
|
||||
starts flush with the top of the pane — that is what lets the hero
|
||||
run UNDER the bar, and the `.hero-bg` stack is positioned against
|
||||
this box. The inset the pane would have given us comes back here, so
|
||||
the flow content below the hero is unmoved. */
|
||||
padding-top: var(--pane-pad);
|
||||
|
||||
/* Written by heroScroll(). --p is the ride-up progress, 0 at the top
|
||||
of the page; the three lengths are measured from the DOM and are all
|
||||
|
||||
Reference in new issue
Block a user