Move the service pills out of the header into a Status section
All checks were successful
Deploy / deploy (push) Successful in 22s

The pills occupied a second full-width row of the header at every width,
which is a lot of permanent chrome for something you glance at. They now
open <main> as their own "Status" section, directly above Right now —
where you'd look for them, and consistent with every other band on the
page carrying a heading.

The header drops to a single row (brand left, clock and settings right),
so it no longer needs flex-wrap or the order: 1/2/3 shuffle that kept
the pill row beneath the brand. Pills go to var(--tap) height now
they're content rather than header furniture, and left-align with every
other section instead of centring.

Behaviour is unchanged: the pills keep their svc-<key> ids, so the
polling in dashboard.js needed no edit, and they still wrap rather than
scroll so no service is ever hidden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Barely Removable 2026-08-27 07:59:26 -07:00
parent f572d95bd0
commit 377524c037
2 changed files with 35 additions and 34 deletions

View file

@ -1,10 +1,10 @@
/* ── Header ─────────────────────────────────────────── */ /* ── Header ─────────────────────────────────────────── */
/* Two deliberate rows at every width: identity + controls on top, /* Identity on the left, clock + settings on the right, one row at every
service pills on their own full-width row beneath. Letting the pills width. The service pills used to occupy a second full-width row here;
share row one made the header wrap into ragged rows and orphan the they now live in the Status section at the top of <main>, which is
clock as soon as the six of them stopped fitting. Scrolls away with where someone looks for them. Scrolls away with the page — a status
the page — a status bar isn't worth permanent screen real estate. */ bar isn't worth permanent screen real estate. */
header { header {
background: var(--surface); background: var(--surface);
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
@ -12,10 +12,8 @@ header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.75rem var(--gap); gap: 0.75rem var(--gap);
flex-wrap: wrap;
} }
.brand { .brand {
order: 1;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.65rem; gap: 0.65rem;
@ -31,25 +29,24 @@ header {
white-space: nowrap; white-space: nowrap;
} }
/* Service status pills — own row, wrapping among themselves so every /* Service status pills — the Status section's only content, left-aligned
service stays visible at any width. Never scroll or clip: a hidden with every other section's content and wrapping among themselves so
pill is a service whose status you can't see. */ every service stays visible at any width. Never scroll or clip: a
hidden pill is a service whose status you can't see. */
.svc-strip { .svc-strip {
order: 3;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.4rem; gap: 0.5rem;
flex: 0 0 100%;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center;
min-width: 0; min-width: 0;
} }
/* Full --tap height now they're content rather than header furniture. */
.svc-pill { .svc-pill {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 0.45rem; gap: 0.45rem;
padding: 0.35rem 0.7rem; padding: 0.35rem 0.9rem;
min-height: 34px; min-height: var(--tap);
background: var(--surface-2); background: var(--surface-2);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 100px; border-radius: 100px;
@ -74,7 +71,6 @@ header {
.status-light.warn { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-dim); } .status-light.warn { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-dim); }
.header-right { .header-right {
order: 2;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.75rem; gap: 0.75rem;
@ -712,12 +708,10 @@ footer .version {
.row.cols-3 > :first-child { grid-column: auto; } .row.cols-3 > :first-child { grid-column: auto; }
} }
@media (max-width: 700px) { @media (max-width: 700px) {
/* Row order and the full-width pill row are set in the base rules. */
header { padding: 0.7rem 1rem; gap: 0.6rem; } header { padding: 0.7rem 1rem; gap: 0.6rem; }
.brand { flex: 1 1 auto; } .brand { flex: 1 1 auto; }
.brand h1 { font-size: var(--fs-base); } .brand h1 { font-size: var(--fs-base); }
.header-clock { display: none; } .header-clock { display: none; }
.svc-strip { justify-content: flex-start; }
main { padding: 1rem; } main { padding: 1rem; }
.card-body { padding: 0.9rem; } .card-body { padding: 0.9rem; }
.card-header { padding: 0.75rem 0.9rem; } .card-header { padding: 0.75rem 0.9rem; }

View file

@ -58,6 +58,22 @@
<h1>Media Centre</h1> <h1>Media Centre</h1>
</div> </div>
<div class="header-right">
<div class="header-clock" id="header-clock">—</div>
<a href="{{ url_for('settings_page') }}" class="icon-btn" aria-label="Settings">
<span aria-hidden="true">⚙</span>
</a>
</div>
</header>
<main>
<!-- ══ Status — is everything reachable? ══ -->
<section class="section" aria-labelledby="h-status">
<h2 id="h-status">Status</h2>
{# Every service stays visible at every width — these wrap onto more
rows rather than scrolling or truncating. A hidden pill is a service
whose status you can't see. #}
<nav class="svc-strip" aria-label="Service status"> <nav class="svc-strip" aria-label="Service status">
{{ svc_pill('sonarr', 'Sonarr', service_urls.sonarr, sonarr.status == 'ok', {{ svc_pill('sonarr', 'Sonarr', service_urls.sonarr, sonarr.status == 'ok',
(sonarr.total_series ~ ' series') if sonarr.status == 'ok' else 'offline') }} (sonarr.total_series ~ ' series') if sonarr.status == 'ok' else 'offline') }}
@ -72,16 +88,7 @@
{{ svc_pill('ombi', 'Ombi', service_urls.ombi, ombi.status == 'ok', {{ svc_pill('ombi', 'Ombi', service_urls.ombi, ombi.status == 'ok',
(ombi.total_pending ~ ' pending') if ombi.status == 'ok' else 'offline') }} (ombi.total_pending ~ ' pending') if ombi.status == 'ok' else 'offline') }}
</nav> </nav>
</section>
<div class="header-right">
<div class="header-clock" id="header-clock">—</div>
<a href="{{ url_for('settings_page') }}" class="icon-btn" aria-label="Settings">
<span aria-hidden="true">⚙</span>
</a>
</div>
</header>
<main>
<!-- ══ Right now — the time-sensitive row, above the fold ══ --> <!-- ══ Right now — the time-sensitive row, above the fold ══ -->
<section class="section hero" aria-labelledby="h-now"> <section class="section hero" aria-labelledby="h-now">