Join the tab row to the frozen date row
The tab row was painted in the page ground while the day bar above it is a card, and the two sat as separate bars with the day bar's rounded corners cutting between them — so the frozen top of the screen read as two mismatched strips rather than one thing. It takes the same card now: surface colour, radius and shadow. Once the log buttons have scrolled away and the two bars meet, they lose the seam and share one frame — the day bar squares its bottom corners and gives up its shadow, the tab row squares its top, and the pair casts a single shadow below. Scrolled back to the top they are two cards again, which is right: the log buttons genuinely sit between them there. CSS has no way to ask whether a sticky element is currently stuck, so a class is toggled from JS on the simplest available test — whether the two are touching. It rides the rAF-throttled scroll handler that already existed for the timer pill, so it adds no listener, and it is re-checked on a tab switch (a shorter tab can leave the page too short to stay scrolled) and when the day bar changes height. The tab row's sticky offset is now a pixel less than the day bar's height. The safe-area inset is free to be fractional while the measured height is a whole number, and that shortfall would show as a hairline of page ground between the two; the overlap it costs is invisible, since the day bar paints on top in the same colour.
This commit is contained in:
+25
-2
@@ -170,13 +170,36 @@ main {
|
||||
fallback keeps the bar usable for the frame before that lands. */
|
||||
.tabs {
|
||||
position: sticky;
|
||||
top: calc(env(safe-area-inset-top, 0px) + var(--day-bar-h, 52px));
|
||||
/* One pixel under the day bar's height rather than exactly it: the inset is
|
||||
free to be fractional while the measured height is a whole number, and a
|
||||
sub-pixel shortfall would show as a hairline of page ground between the
|
||||
two. The overlap is invisible — the day bar paints on top, same colour. */
|
||||
top: calc(env(safe-area-inset-top, 0px) + var(--day-bar-h, 52px) - 1px);
|
||||
z-index: 55; /* under the day bar, over the panels */
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 6px 4px;
|
||||
margin: -8px 0 0;
|
||||
background: var(--bg);
|
||||
/* Same card as the day bar rather than the page ground, so the two read as
|
||||
one thing once they are frozen together. */
|
||||
background: var(--surface);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
/* At rest the two are separate cards with the log buttons between them. Scroll
|
||||
the log buttons away and they meet, so the seam goes: the day bar squares its
|
||||
bottom and gives up its shadow, the tab bar squares its top, and the pair
|
||||
sits inside one rounded frame casting one shadow. JS adds .merged the moment
|
||||
they touch — CSS has no way to ask whether a sticky element is stuck. */
|
||||
.day-bar.merged {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.tabs.merged {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
.tabs .tab {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user