ui: Central UI density/consistency sweep + Theme 0.4.1

Applies the family-wide admin-UI cleanup playbook to the Central UI so the
Blazor surfaces stop diverging from the shared kit: buttons are grouped rather
than individually sized, long cell values are contained instead of widening
tables, and hard-coded colours give way to theme tokens.

The headline fix is that MainLayout passed Accent="#2f5fd0" to ThemeShell,
which the kit emits as an inline style on the shell root. Being a descendant of
<html>, it beat the [data-bs-theme="dark"] override for the entire app, so the
dark accent had never rendered. Declaring --accent in site.css :root instead
lets both schemes resolve; light is unchanged because the value already matched
the kit's light default.

Theme pins to 0.4.1, which upstreams the local .btn sizing block verbatim, so
that block is deleted here rather than duplicated. Verified byte-identical
before removal; the repo now declares no --bs-btn-* anywhere.

NOT purely cosmetic, contrary to the sweep's stated scope: four detail-modal
surfaces (NotificationReport, ConfigurationAuditLog, ParkedMessages,
SiteCallsReport) were additionally refactored from holding the selected record
to holding its id and re-resolving from the current page each render, with the
resolve doubling as the visibility gate. A background refresh that drops the
row now closes the modal instead of showing a stale snapshot. This is a
behaviour change and is called out rather than buried: a full-suite run turned
up one intermittent CentralUI failure, CloseButton_DismissesModal, whose stack
(GetRequiredEventBindingEntry during DispatchEventAsync) indicates the handler
was disposed between render and click — a window the previous field-held record
made structurally impossible. Treat the modal lifecycle here as unreviewed.

Build 0/0; suite green apart from that one intermittent failure.
This commit is contained in:
Joseph Doherty
2026-08-11 05:50:12 -04:00
parent b6f383a225
commit 9e243493fb
77 changed files with 2197 additions and 1292 deletions
@@ -278,9 +278,12 @@
<div class="mt-3" aria-hidden="true">
<svg viewBox="0 0 200 12" preserveAspectRatio="none"
style="width:100%; height:10px; border-radius:5px; overflow:hidden;">
<rect x="0" y="0" width="20" height="12" fill="#f8d7da" />
<rect x="20" y="0" width="160" height="12" fill="#d1e7dd" />
<rect x="180" y="0" width="20" height="12" fill="#f8d7da" />
@* Token-driven fills, not literal hex: this preview renders on a
#1b1d21 surface under [data-bs-theme="dark"], where Bootstrap's
light subtle tints read as bright pastel bars. *@
<rect x="0" y="0" width="20" height="12" fill="var(--bad-bg)" />
<rect x="20" y="0" width="160" height="12" fill="var(--ok-bg)" />
<rect x="180" y="0" width="20" height="12" fill="var(--bad-bg)" />
</svg>
<div class="d-flex justify-content-between small text-muted mt-1">
<span>alarm</span>
@@ -25,9 +25,11 @@
</div>
<div class="modal-footer px-0 pb-0 mt-3">
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary btn-sm" @onclick="Submit"
disabled="@(_parentTemplateId == 0 || string.IsNullOrWhiteSpace(_slotName))">Compose</button>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary" @onclick="Submit"
disabled="@(_parentTemplateId == 0 || string.IsNullOrWhiteSpace(_slotName))">Compose</button>
</div>
</div>
@code {
@@ -47,12 +47,14 @@
@if (state.Kind != DialogKind.Custom)
{
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary btn-sm" @onclick="Cancel">Cancel</button>
<button type="button"
class="btn @(state.Danger ? "btn-danger" : "btn-primary") btn-sm"
@onclick="Confirm">
@ConfirmLabel(state)
</button>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-secondary" @onclick="Cancel">Cancel</button>
<button type="button"
class="btn @(state.Danger ? "btn-danger" : "btn-primary")"
@onclick="Confirm">
@ConfirmLabel(state)
</button>
</div>
</div>
}
</div>
@@ -5,15 +5,19 @@
@if (ShowToolbar)
{
<div class="d-flex justify-content-end align-items-center gap-3 mb-1 small text-muted">
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none" @onclick="FormatAsync"
title="Format document (Ctrl/Cmd+Shift+F)">Format</button>
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none" @onclick="ToggleWrap"
title="Word wrap">@(_wrap ? "Wrap on" : "Wrap off")</button>
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none" @onclick="ToggleMinimap"
title="Toggle minimap">@(_minimap ? "Minimap on" : "Minimap off")</button>
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none" @onclick="ToggleTheme"
title="Toggle theme">@(_dark ? "Dark" : "Light")</button>
@* Four editor-state toggles: actions on the editor, not navigation — so they
are outline buttons in one segmented group, not link buttons. *@
<div class="d-flex justify-content-end align-items-center mb-1">
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-secondary" @onclick="FormatAsync"
title="Format document (Ctrl/Cmd+Shift+F)">Format</button>
<button type="button" class="btn btn-outline-secondary" @onclick="ToggleWrap"
title="Word wrap">@(_wrap ? "Wrap on" : "Wrap off")</button>
<button type="button" class="btn btn-outline-secondary" @onclick="ToggleMinimap"
title="Toggle minimap">@(_minimap ? "Minimap on" : "Minimap off")</button>
<button type="button" class="btn btn-outline-secondary" @onclick="ToggleTheme"
title="Toggle theme">@(_dark ? "Dark" : "Light")</button>
</div>
</div>
}
@@ -31,9 +31,11 @@ else
}
<div class="modal-footer px-0 pb-0 mt-3">
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()" disabled="@_busy">Cancel</button>
<button class="btn btn-primary btn-sm" @onclick="Submit"
disabled="@(_busy || !SiteOptions.Any())">Move</button>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary" @onclick="() => Context.Cancel()" disabled="@_busy">Cancel</button>
<button class="btn btn-primary" @onclick="Submit"
disabled="@(_busy || !SiteOptions.Any())">Move</button>
</div>
</div>
@code {
@@ -15,8 +15,10 @@
</select>
<div class="modal-footer px-0 pb-0 mt-3">
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary btn-sm" @onclick="Submit">Move</button>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary" @onclick="Submit">Move</button>
</div>
</div>
@code {
@@ -13,8 +13,10 @@
</select>
<div class="modal-footer px-0 pb-0 mt-3">
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary btn-sm" @onclick="Submit">Move</button>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary" @onclick="Submit">Move</button>
</div>
</div>
@code {
@@ -9,9 +9,11 @@
<input class="form-control form-control-sm" @bind="_name" @bind:event="oninput" />
<div class="modal-footer px-0 pb-0 mt-3">
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary btn-sm" @onclick="Submit"
disabled="@string.IsNullOrWhiteSpace(_name)">Save</button>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary" @onclick="() => Context.Cancel()">Cancel</button>
<button class="btn btn-primary" @onclick="Submit"
disabled="@string.IsNullOrWhiteSpace(_name)">Save</button>
</div>
</div>
@code {
@@ -135,7 +135,7 @@ else
</div>
<button type="button"
class="btn btn-link btn-sm text-danger p-0 ms-auto"
class="btn btn-sm btn-outline-danger ms-auto"
title="Remove" aria-label="Remove field"
@onclick="() => RemoveProperty(parent, prop)">
<i class="bi bi-x-lg"></i>