Stop event banner size shifting
This commit is contained in:
fraxle
2026-08-02 17:06:31 +01:00
parent 249f284593
commit ec211314e0
2 changed files with 53 additions and 19 deletions
+20 -4
View File
@@ -257,18 +257,34 @@ body {
background: rgba(0, 0, 0, 0.55);
}
/* Slide stack. Every active event is rendered and every slide is placed in the
same single grid cell, so the strip's height is set by the TALLEST slide and
stays put as the rotation cycles — a one-line event followed by a message
that wraps to two lines no longer grows the banner and shunts the page. */
.event-note-stack {
display: grid;
grid-template-columns: minmax(0, 1fr);
align-items: start;
flex: 1;
min-width: 0;
}
.event-note-slide {
grid-area: 1 / 1; /* stack all slides on top of each other */
display: flex;
align-items: baseline;
flex-wrap: wrap;
gap: 4px 10px;
flex: 1;
min-width: 0;
opacity: 1;
opacity: 0; /* only .is-active is visible */
pointer-events: none;
user-select: none; /* keeps hidden copy out of a drag-selection */
transition: opacity 0.35s ease;
}
.event-note-slide.is-fading {
opacity: 0;
.event-note-slide.is-active {
opacity: 1;
pointer-events: auto;
user-select: auto;
}
.event-note-emoji {
+33 -15
View File
@@ -692,9 +692,18 @@ export function UTCIForecast() {
const fmtDate = (iso) => iso
? new Date(iso + 'T00:00Z').toLocaleDateString('en-GB', { day: 'numeric', month: 'short', timeZone: 'UTC' })
: null;
const startFmt = fmtDate(ev.start);
const peakFmt = fmtDate(ev.peak);
const endFmt = fmtDate(ev.end);
// Date line for one event — computed per slide because every event is
// rendered (see the stack below), not just the visible one.
const dateLineFor = (e) => {
const startFmt = fmtDate(e.start);
const peakFmt = fmtDate(e.peak);
const endFmt = fmtDate(e.end);
if (!startFmt || !endFmt) return null;
if (startFmt === endFmt) return peakFmt ? `Peak ${peakFmt}` : startFmt;
return (peakFmt && peakFmt !== startFmt && peakFmt !== endFmt)
? `${startFmt} ${endFmt} · Peak ${peakFmt}`
: `${startFmt} ${endFmt}`;
};
// Warning banners take their background from the day tabs' weather
// palette (ev.tint, set in events/weather-checks.js) so a heat alert
// reads the same orange as a hot day tab and a rain alert the same
@@ -709,21 +718,30 @@ export function UTCIForecast() {
borderColor: `rgb(${ev.tint.map(c => Math.round(c * 0.72)).join(',')})`,
};
})() : undefined;
const dateLine = (startFmt && endFmt)
? (startFmt === endFmt
? (peakFmt ? `Peak ${peakFmt}` : startFmt)
: (peakFmt && peakFmt !== startFmt && peakFmt !== endFmt
? `${startFmt} ${endFmt} · Peak ${peakFmt}`
: `${startFmt} ${endFmt}`))
: null;
return html`
<div class=${`event-note${isPriority ? ' is-priority' : ''}${noteTintStyle ? ' is-tinted' : ''}`} style=${noteTintStyle}>
<span class="event-note-accent" style=${{ background: ev.color === '#fdf8ee' ? '#c8922a' : ev.color }} />
<div class=${`event-note-slide${noteFading ? ' is-fading' : ''}`}>
<span class="event-note-emoji">${ev.emoji}</span>
<span class="event-note-title">${ev.title}</span>
<span class="event-note-msg">${ev.message}</span>
${dateLine && html`<span class="event-note-dates">${dateLine}</span>`}
${/* Every slide is rendered, all stacked in one CSS grid cell, so the
strip is always as tall as the LONGEST event's copy. Rotating to
a two-line message then back no longer resizes the banner and
shunts the page up and down. Only the active slide is visible;
the rest sit at opacity 0 and are hidden from assistive tech. */''}
<div class="event-note-stack">
${activeEvents.map((e, i) => {
const dateLine = dateLineFor(e);
const isActive = i === noteIndex && !noteFading;
return html`
<div
key=${e.id || i}
class=${`event-note-slide${isActive ? ' is-active' : ''}`}
aria-hidden=${isActive ? undefined : 'true'}
>
<span class="event-note-emoji">${e.emoji}</span>
<span class="event-note-title">${e.title}</span>
<span class="event-note-msg">${e.message}</span>
${dateLine && html`<span class="event-note-dates">${dateLine}</span>`}
</div>`;
})}
</div>
${activeEvents.length > 1 && html`
<div class="event-note-dots">