Web frontend: phone header glass and full-height stage
On an iPhone the sticky group switch sat on a fixed teal fade, which was the wrong colour as soon as the ambience took on another album's tint (brown for Conni). It is now a neutral frosted blur that fades out, so it suits whatever is playing, and it reaches up under the status bar so scrolled content never shows behind the clock. After the search keyboard had been up, 100dvh in the home-screen app came back a status bar short and the white page showed as a strip along the bottom. On phones the stage is pinned to the viewport edges instead, with the sea colour behind it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -446,6 +446,7 @@ export function App() {
|
||||
return (
|
||||
<div
|
||||
className="stage"
|
||||
data-phone={phone || undefined}
|
||||
data-blur={SHOW_GLASS_BLUR ? undefined : "off"}
|
||||
data-cardblur={SHOW_CARD_BLUR ? undefined : "off"}
|
||||
>
|
||||
|
||||
@@ -13,6 +13,22 @@
|
||||
--m-dock-clearance: calc(96px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
/* iOS can leave the layout viewport shorter than the screen - after the keyboard has
|
||||
been up, `100dvh` in a home-screen app comes back one status bar short - and the
|
||||
page behind the stage showed as a white strip along the bottom. Pinning the stage to
|
||||
the viewport's edges does not depend on that height at all, and the sea colour
|
||||
underneath covers whatever might still peek through. */
|
||||
html,
|
||||
body {
|
||||
background: var(--stage-deep, #001b21);
|
||||
}
|
||||
|
||||
.stage[data-phone] {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.m-glass {
|
||||
background: var(--m-glass-fill);
|
||||
backdrop-filter: blur(14px) saturate(1.7);
|
||||
@@ -39,7 +55,8 @@
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: env(safe-area-inset-top) 0 calc(var(--m-dock-clearance) + 84px);
|
||||
/* No top inset here: the sticky bar reaches up under the status bar itself. */
|
||||
padding: 0 0 calc(var(--m-dock-clearance) + 84px);
|
||||
animation: viewEnter 180ms ease-out;
|
||||
}
|
||||
|
||||
@@ -49,7 +66,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px var(--m-gutter) 4px;
|
||||
padding: calc(14px + env(safe-area-inset-top)) var(--m-gutter) 4px;
|
||||
}
|
||||
|
||||
.m-title-mascot {
|
||||
@@ -82,21 +99,45 @@
|
||||
color: oklch(80% 0.16 30);
|
||||
}
|
||||
|
||||
/* The bar that stays put while the page scrolls under it. Fades from the top of the
|
||||
sea into transparency rather than ending in a hard edge. */
|
||||
/* The bar that stays put while the page scrolls under it. Sticks to the very top of
|
||||
the screen, under the status bar, so content never shows behind the clock.
|
||||
|
||||
Frosted rather than painted: the background behind it is the ambience canvas,
|
||||
which takes its colour from whatever is playing, so any fixed fill was the wrong
|
||||
colour as soon as an album with different art started. A blur with a neutral
|
||||
darkening suits every one of them, and the mask fades it out instead of ending in
|
||||
a hard edge. */
|
||||
.m-sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
padding: 10px var(--m-gutter) 14px;
|
||||
background: linear-gradient(180deg, #2f6f7aee 0%, #2f6f7a99 65%, #2f6f7a00 100%);
|
||||
padding: calc(10px + env(safe-area-inset-top)) var(--m-gutter) 14px;
|
||||
}
|
||||
|
||||
/* Under the title row, overlap the row by the status bar's height: the bar keeps its
|
||||
place in the layout but already covers the status bar once it sticks. */
|
||||
.m-title-row + .m-sticky {
|
||||
margin-top: calc(-1 * env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
.m-sticky::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
background: oklch(0% 0 0 / 0.16);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
-webkit-mask-image: linear-gradient(180deg, #000 70%, transparent);
|
||||
mask-image: linear-gradient(180deg, #000 70%, transparent);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.m-navbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding-top: 12px;
|
||||
padding-top: calc(12px + env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
.m-navbar-title {
|
||||
|
||||
Reference in New Issue
Block a user