style(centralui): full-app bg-light/bg-white -> theme-aware utility sweep (M10 residual)
T34c only fixed the bounded modal-surface offenders. Bootstrap 5.3's bg-light
and bg-white are fixed light values that do NOT flip under [data-bs-theme=dark],
so every remaining use was a dark-mode contrast break. 35 swaps across 19 files:
surface / <pre> / <code> bg-light -> bg-body-secondary
panel bg-white -> bg-body
neutral badge bg-light text-dark -> bg-secondary-subtle text-secondary-emphasis
muted badge / input group bg-light text-muted -> bg-body-secondary text-body-secondary
DELIBERATELY LEFT (7 sites): the neutral member of a status-badge switch or
ternary whose siblings are all solid, non-theme-aware colours (bg-success,
bg-danger, bg-warning) — swapping only the neutral one to a subtle token breaks
the visual weight of the set, so these stay until the whole family is retoned:
Topology.razor:513 (Current badge) and :588 (InstanceState.NotDeployed)
InstanceConfigure.razor:1520 (same InstanceState switch)
NotificationReport.razor StatusBadgeClass fallback
TransportImport.razor ConflictKind badge fallback
SecuredWrites.razor text-bg-light fallback (a text-bg-* family with no
theme-aware member at all)
Health.razor:377 depth ternary
Also untouched by design: SchemaBuilder.razor:88 (already bg-light-subtle,
theme-aware), bg-dark text-light console panels, and site.css / #reconnect-modal.
InstanceConfigure.razor is edited concurrently elsewhere; its change here is 5
pure class-string swaps on existing lines, no reflow. No test asserted any of
these classes. Also marks all four M10 residuals done in the plan doc.
This commit is contained in:
@@ -459,15 +459,15 @@ Markup: two `<input type="datetime-local">` with `id="@(IdPrefix)-from"`/`-to`,
|
||||
## Deferred / out of scope (log as FOLLOWUPs at INT)
|
||||
- Unified offset+keyset pagination framework (blocked by total-count mismatch).
|
||||
- `Deployments.razor` PagerWindow → OffsetPager (different windowed UX; intentionally left).
|
||||
- Complex `TemplateEdit` page-embedded modals → host migration.
|
||||
- TreeView arrow-key navigation (R7).
|
||||
- ~~Complex `TemplateEdit` page-embedded modals → host migration.~~ **DONE 2026-08-01.**
|
||||
- ~~TreeView arrow-key navigation (R7).~~ **DONE 2026-08-01.**
|
||||
- Theme-package side-rail dark theming, IF the spike verdict is "rail stays light" (coordination follow-up).
|
||||
|
||||
## Follow-ups logged at delivery (INT findings)
|
||||
- **#207 — FIXED (2026-08-01 bookkeeping sync).** ~~(pre-existing, open since M6/K14):~~ `QueryStringDrillInTests` now registers the `IKpiHistoryQueryService` substitute in its fixture (lines ~165-167), so the 3 `SiteCallsReport` drill-in tests are green.
|
||||
- **#163 (pre-existing):** `InstanceConfigureListOverrideTests` codec roundtrip red; pre-dates M10.
|
||||
- **NotificationReport `OffsetPager` always-visible:** pager is now always visible when results exist (previously hidden on sub-page-size sets); buttons are correctly disabled on a single page — product decision whether to re-add an `@if (_totalCount > _pageSize)` guard.
|
||||
- **NotificationReport `OffsetPager` always-visible — DECIDED + DONE (2026-08-01).** A pager whose only controls are permanently disabled is noise, so the conventional behaviour ships: the bar is hidden on a provably single page. Implemented **reusably but opt-in** — `OffsetPager.HideWhenSinglePage` (default `false`, so no consumer changes behaviour implicitly), set `true` at the `NotificationReport` call site. It is NOT defaulted on because the pager's summary span doubles as the "N total" result-count readout on `ConfigurationAuditLog`, which has no other place to show it (and whose Playwright fixture asserts `3 total` on a 3-row single page). The guard only fires when single-page-ness is *positively* established (`PageCount <= 1` **and** `Page <= 1` **and** `!HasNextPage`), so a null `TotalCount` still renders the bar.
|
||||
- **`Deployments.razor` PagerWindow intentionally kept:** windowed numbered-button UX is deliberate; NOT migrated to `OffsetPager`.
|
||||
- **`TemplateEdit` inline modals NOT migrated:** the page-embedded modals (wave-3 T34c already tokenized their backdrops); full migration to the host is deferred.
|
||||
- **TreeView full arrow-key navigation (R7) still deferred.**
|
||||
- **Full-app `bg-light`/`bg-white` → theme-aware utility sweep deferred:** only the bounded modal-surface offenders were addressed in T34c; INT dark-mode smoke may surface additional instances.
|
||||
- **`TemplateEdit` inline modals — MIGRATED (2026-08-01).** All four page-embedded modals (Attribute, Alarm, Native Alarm Source, Script) now open through `IDialogService.ShowAsync`, so the host owns the backdrop, focus trap, Escape and focus restoration. Each body was extracted to its own component next to the page — `TemplateAttributeDialog`, `TemplateAlarmDialog`, `TemplateNativeAlarmSourceDialog`, `TemplateScriptDialog` — following the `MoveDataConnectionDialog` pattern: the body owns the form state and renders validation/server errors INLINE while staying open, closing with `Close(true)` only on a successful save. Persistence stayed on the page (it owns `TemplateService` and the inherited-member rules) and is reached through an `OnSaveAsync` delegate returning `null` on success or the message to display. The script dialog keeps all four tab panels mounted (Monaco/JSONJoy must not tear down on tab switch) and hosts the Test Run panel, which needs the live unsaved buffer. Extraction moved markup that three structural source-scanning tests pinned (`TemplateNativeAlarmSourceEditorTests`, `AttributeListEditorTests`, `TestRunWarningTests`) — all three were repointed at the new files.
|
||||
- **~~TreeView full arrow-key navigation (R7) still deferred.~~ DONE 2026-08-01** — the WAI-ARIA tree pattern (roving tabindex, Arrow/Home/End movement, Enter/Space activation, `aria-level`) now ships on `TreeView<TItem>`; see `docs/components/TreeView.md`.
|
||||
- **Full-app `bg-light`/`bg-white` → theme-aware utility sweep — DONE 2026-08-01.** 35 class swaps across 19 Central UI files: surfaces/`<pre>`/`<code>` `bg-light` → `bg-body-secondary`, panel `bg-white` → `bg-body`, neutral `badge bg-light text-dark` → `badge bg-secondary-subtle text-secondary-emphasis`, `bg-light text-muted border` → `bg-body-secondary text-body-secondary border`. **Deliberately left** (7 sites): the neutral member of a *status-badge* switch/ternary whose siblings are all solid non-theme-aware colours (`bg-success`/`bg-danger`/`bg-warning`), where swapping only the neutral one breaks the set's visual weight — `Topology.razor:513,588`, `InstanceConfigure.razor:1520`, `NotificationReport.razor` `StatusBadgeClass` fallback, `TransportImport.razor` ConflictKind fallback, `SecuredWrites.razor` `text-bg-light` fallback, `Health.razor:377`. `SchemaBuilder.razor:88` was already `bg-light-subtle` (theme-aware). `bg-dark text-light` console panels and `site.css`/`#reconnect-modal` are intentional fixed colours.
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Event.ErrorDetail))
|
||||
{
|
||||
<pre class="bg-light border rounded p-2 mb-0 drawer-pre">@Event.ErrorDetail</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 mb-0 drawer-pre">@Event.ErrorDetail</pre>
|
||||
}
|
||||
</section>
|
||||
}
|
||||
@@ -119,7 +119,7 @@
|
||||
{
|
||||
<section class="mb-3" data-test="section-extra">
|
||||
<h6 class="text-uppercase text-muted small fw-semibold mb-1">Extra</h6>
|
||||
<pre class="bg-light border rounded p-2 mb-0 drawer-pre json">@PrettyPrintJson(Event.Extra!)</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 mb-0 drawer-pre json">@PrettyPrintJson(Event.Extra!)</pre>
|
||||
</section>
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<small class="text-muted ms-1">@match.Path</small>
|
||||
@if (!string.IsNullOrEmpty(node.DataType))
|
||||
{
|
||||
<span class="badge bg-light text-muted border ms-1">@node.DataType</span>
|
||||
<span class="badge bg-body-secondary text-body-secondary border ms-1">@node.DataType</span>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</a>
|
||||
@if (!string.IsNullOrEmpty(Node.DataType))
|
||||
{
|
||||
<span class="badge bg-light text-muted border ms-1" data-test="node-type">@Node.DataType</span>
|
||||
<span class="badge bg-body-secondary text-body-secondary border ms-1" data-test="node-type">@Node.DataType</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
@if (result.FailureKind == VerifyFailureKind.UntrustedCertificate
|
||||
&& result.Cert is { } cert)
|
||||
{
|
||||
<div class="border rounded bg-light p-2 mt-2 small" data-test="verify-cert-panel">
|
||||
<div class="border rounded bg-body-secondary p-2 mt-2 small" data-test="verify-cert-panel">
|
||||
<div class="text-muted mb-1">Untrusted server certificate</div>
|
||||
<dl class="row mb-1 small">
|
||||
<dt class="col-sm-3">Subject</dt>
|
||||
|
||||
+2
-2
@@ -155,7 +155,7 @@
|
||||
{
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<pre class="bg-light p-2 rounded small mb-0" style="max-height: 200px; overflow: auto;">@FormatJson(entry.AfterStateJson!)</pre>
|
||||
<pre class="bg-body-secondary p-2 rounded small mb-0" style="max-height: 200px; overflow: auto;">@FormatJson(entry.AfterStateJson!)</pre>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@@ -179,7 +179,7 @@
|
||||
<button type="button" class="btn-close" @onclick="CloseStateModal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre class="bg-light p-2 rounded small mb-0">@FormatJson(_modalEntry.AfterStateJson!)</pre>
|
||||
<pre class="bg-body-secondary p-2 rounded small mb-0">@FormatJson(_modalEntry.AfterStateJson!)</pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" @onclick="CloseStateModal">Close</button>
|
||||
|
||||
+5
-5
@@ -240,13 +240,13 @@
|
||||
<tr data-test="override-row-@attr.Name">
|
||||
<td class="small">@attr.Name</td>
|
||||
<td>
|
||||
<span class="badge bg-light text-dark">@attr.DataType</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis">@attr.DataType</span>
|
||||
@if (attr.DataType == DataType.List)
|
||||
{
|
||||
@* Element type is fixed by the base attribute — shown
|
||||
read-only here (the List editor renders it hidden via
|
||||
ShowElementType="false"). *@
|
||||
<span class="badge bg-light text-dark border ms-1"
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis border ms-1"
|
||||
data-test="override-element-type">
|
||||
of @(attr.ElementDataType ?? DataType.String)
|
||||
</span>
|
||||
@@ -326,7 +326,7 @@
|
||||
<tr data-test="alarm-override-row-@alarm.Name">
|
||||
<td class="small">@alarm.Name</td>
|
||||
<td>
|
||||
<span class="badge bg-light text-dark border">@alarm.TriggerType</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis border">@alarm.TriggerType</span>
|
||||
</td>
|
||||
<td class="small text-muted text-truncate font-monospace" style="max-width: 280px;"
|
||||
title="@alarm.TriggerConfiguration">
|
||||
@@ -373,14 +373,14 @@
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">
|
||||
Edit override: @_editingAlarm.Name
|
||||
<span class="badge bg-light text-dark border ms-1">@_editingAlarm.TriggerType</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis border ms-1">@_editingAlarm.TriggerType</span>
|
||||
</h6>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="CancelEditOverride"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3 small">
|
||||
<div class="text-muted text-uppercase fw-semibold mb-1">Inherited from template</div>
|
||||
<code class="d-block bg-light p-2 rounded text-break">@(_editingAlarm.TriggerConfiguration ?? "(none)")</code>
|
||||
<code class="d-block bg-body-secondary p-2 rounded text-break">@(_editingAlarm.TriggerConfiguration ?? "(none)")</code>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
|
||||
@@ -148,9 +148,9 @@
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-success mb-1">
|
||||
Return value <span class="badge bg-light text-dark ms-1">@_runResult.ReturnTypeName</span>
|
||||
Return value <span class="badge bg-secondary-subtle text-secondary-emphasis ms-1">@_runResult.ReturnTypeName</span>
|
||||
</label>
|
||||
<pre class="bg-light border rounded p-2 small mb-0 font-monospace" style="white-space: pre-wrap;">@_runResult.ReturnValueJson</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 small mb-0 font-monospace" style="white-space: pre-wrap;">@_runResult.ReturnValueJson</pre>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@
|
||||
Backup endpoint
|
||||
@if (!_showBackup)
|
||||
{
|
||||
<span class="badge bg-light text-muted border ms-2">Optional</span>
|
||||
<span class="badge bg-body-secondary text-body-secondary border ms-2">Optional</span>
|
||||
}
|
||||
</h6>
|
||||
@if (!_showBackup)
|
||||
|
||||
@@ -175,8 +175,8 @@
|
||||
<p class="small text-muted text-truncate mb-1" title="@es.EndpointUrl">@es.EndpointUrl</p>
|
||||
<div>
|
||||
<span class="badge bg-secondary me-1">@es.AuthType</span>
|
||||
<span class="badge bg-light text-dark me-1">Max @es.MaxRetries retries</span>
|
||||
<span class="badge bg-light text-dark">Delay @es.RetryDelay.TotalSeconds s</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis me-1">Max @es.MaxRetries retries</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis">Delay @es.RetryDelay.TotalSeconds s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -248,8 +248,8 @@
|
||||
@* Connection strings carry credentials — never rendered here (not even for admins). Shown only on the create/edit form. *@
|
||||
<p class="small text-muted fst-italic mb-1">Connection string hidden — edit to view</p>
|
||||
<div>
|
||||
<span class="badge bg-light text-dark me-1">Max @dc.MaxRetries retries</span>
|
||||
<span class="badge bg-light text-dark">Delay @dc.RetryDelay.TotalSeconds s</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis me-1">Max @dc.MaxRetries retries</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis">Delay @dc.RetryDelay.TotalSeconds s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -325,7 +325,7 @@
|
||||
<pre class="small text-muted font-monospace mb-2"
|
||||
style="white-space: pre-wrap; word-break: break-all;"
|
||||
title="@m.Script">@preview</pre>
|
||||
<span class="badge bg-light text-dark">Timeout @m.TimeoutSeconds s</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis">Timeout @m.TimeoutSeconds s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -141,9 +141,9 @@
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-success mb-1">
|
||||
Return value <span class="badge bg-light text-dark ms-1">@_runResult.ReturnTypeName</span>
|
||||
Return value <span class="badge bg-secondary-subtle text-secondary-emphasis ms-1">@_runResult.ReturnTypeName</span>
|
||||
</label>
|
||||
<pre class="bg-light border rounded p-2 small mb-0 font-monospace" style="white-space: pre-wrap;">@_runResult.ReturnValueJson</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 small mb-0 font-monospace" style="white-space: pre-wrap;">@_runResult.ReturnValueJson</pre>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
|
||||
@@ -87,8 +87,8 @@
|
||||
title="@s.Code">@preview</pre>
|
||||
|
||||
<div>
|
||||
<span class="badge bg-light text-dark me-1">@paramCount params</span>
|
||||
<span class="badge bg-light text-dark">
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis me-1">@paramCount params</span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis">
|
||||
@(returnLabel == "void" ? "void" : $"returns {returnLabel}")
|
||||
</span>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -295,7 +295,7 @@
|
||||
</dl>
|
||||
|
||||
<div class="text-muted text-uppercase small fw-semibold mb-1">Error</div>
|
||||
<pre class="bg-light border rounded p-2 small mb-0 parked-error-pre">@_drawerMessage.ErrorMessage</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 small mb-0 parked-error-pre">@_drawerMessage.ErrorMessage</pre>
|
||||
</div>
|
||||
<div class="border-top p-3 d-flex gap-2">
|
||||
<button class="btn btn-outline-success btn-sm flex-grow-1"
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@
|
||||
var contact = list.Type == NotificationType.Sms
|
||||
? r.PhoneNumber
|
||||
: r.EmailAddress;
|
||||
<span class="badge bg-light text-dark me-1 mb-1">@r.Name <@contact></span>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis me-1 mb-1">@r.Name <@contact></span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
RangeViolation { attributeName, min, max }
|
||||
RateOfChange { attributeName, thresholdPerSecond, windowSeconds, direction } *@
|
||||
|
||||
<div class="border rounded bg-white p-3">
|
||||
<div class="border rounded bg-body p-3">
|
||||
|
||||
@* ── Monitored attribute ───────────────────────────────────────────── *@
|
||||
@* Expression triggers reference attributes inside the C# expression itself,
|
||||
@@ -54,7 +54,7 @@
|
||||
</select>
|
||||
@if (_selectedDataType is { } dt)
|
||||
{
|
||||
<span class="input-group-text bg-light text-muted small">@dt</span>
|
||||
<span class="input-group-text bg-body-secondary text-body-secondary small">@dt</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="small text-muted mb-1">Before</div>
|
||||
<pre class="border rounded p-2 small bg-light mb-0" style="max-height: 50vh; overflow: auto; white-space: pre-wrap;">@Before</pre>
|
||||
<pre class="border rounded p-2 small bg-body-secondary mb-0" style="max-height: 50vh; overflow: auto; white-space: pre-wrap;">@Before</pre>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="small text-muted mb-1">After</div>
|
||||
<pre class="border rounded p-2 small bg-light mb-0" style="max-height: 50vh; overflow: auto; white-space: pre-wrap;">@After</pre>
|
||||
<pre class="border rounded p-2 small bg-body-secondary mb-0" style="max-height: 50vh; overflow: auto; white-space: pre-wrap;">@After</pre>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ else
|
||||
/// </summary>
|
||||
private RenderFragment PropertyList(SchemaNode node, bool isRoot = false) => __builder =>
|
||||
{
|
||||
<div class="border rounded bg-white p-2">
|
||||
<div class="border rounded bg-body p-2">
|
||||
@if (node.Properties.Count == 0)
|
||||
{
|
||||
<div class="text-muted small fst-italic px-1 py-2">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
Expression { expression, mode }
|
||||
Call { } *@
|
||||
|
||||
<div class="border rounded bg-white p-3">
|
||||
<div class="border rounded bg-body p-3">
|
||||
|
||||
@* ── Trigger type ──────────────────────────────────────────────────── *@
|
||||
<div class="mb-3">
|
||||
@@ -61,7 +61,7 @@
|
||||
Unrecognized trigger type <code>@_rawType</code>. Its stored
|
||||
configuration is shown below and left untouched — pick a known
|
||||
trigger type above to reconfigure it.
|
||||
<pre class="bg-light border rounded p-2 mt-2 mb-0">@(string.IsNullOrWhiteSpace(TriggerConfig) ? "(empty)" : TriggerConfig)</pre>
|
||||
<pre class="bg-body-secondary border rounded p-2 mt-2 mb-0">@(string.IsNullOrWhiteSpace(TriggerConfig) ? "(empty)" : TriggerConfig)</pre>
|
||||
</div>
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user