ui(density): truncation sweep — Abbreviate + title on unbounded backend/free text (§1d Task 1)

This commit is contained in:
Joseph Doherty
2026-08-10 18:01:07 -04:00
parent ef55ff3977
commit 88aaf1d947
19 changed files with 41 additions and 32 deletions
@@ -38,7 +38,7 @@
}
else if (_error is not null)
{
<p class="mb-0" style="color:var(--bad)">SignalR error: @_error</p>
<p class="mb-0" style="color:var(--bad)" title="@_error">SignalR error: @DisplayText.Abbreviate(_error, 60)</p>
}
else if (_snapshot is null)
{
@@ -166,7 +166,7 @@
@if (_opResultMessage is not null)
{
<span class="chip @(_opResultOk ? "chip-ok" : "chip-bad")" style="font-size:0.8rem">@_opResultMessage</span>
<span class="chip @(_opResultOk ? "chip-ok" : "chip-bad")" style="font-size:0.8rem" title="@_opResultMessageFull">@_opResultMessage</span>
}
</div>
@@ -212,7 +212,11 @@
private bool _busyReconnect;
private bool _busyRestart;
private bool _showRestartConfirm;
// Display text for the op-result chip (truncated at the ShowOpResult choke point) plus the
// untruncated original, which rides the chip's title attribute so the full message stays
// reachable on hover.
private string? _opResultMessage;
private string? _opResultMessageFull;
private bool _opResultOk;
private System.Threading.Timer? _opResultClearTimer;
@@ -303,6 +307,7 @@
{
_busyReconnect = true;
_opResultMessage = null;
_opResultMessageFull = null;
StateHasChanged();
try
{
@@ -315,7 +320,7 @@
}
catch (Exception ex)
{
ShowOpResult(false, ex.Message.Length > 60 ? ex.Message[..60] + "…" : ex.Message);
ShowOpResult(false, ex.Message);
}
finally
{
@@ -329,6 +334,7 @@
_showRestartConfirm = false;
_busyRestart = true;
_opResultMessage = null;
_opResultMessageFull = null;
StateHasChanged();
try
{
@@ -341,7 +347,7 @@
}
catch (Exception ex)
{
ShowOpResult(false, ex.Message.Length > 60 ? ex.Message[..60] + "…" : ex.Message);
ShowOpResult(false, ex.Message);
}
finally
{
@@ -367,13 +373,17 @@
private void ShowOpResult(bool ok, string message)
{
_opResultOk = ok;
_opResultMessage = message;
// Single truncation choke point: callers pass the untruncated message, the chip renders the
// abbreviation and carries the original on its title attribute.
_opResultMessageFull = message;
_opResultMessage = DisplayText.Abbreviate(message, 60);
// Auto-clear the result chip after 8 s. System.Threading.Timer is used (not
// System.Timers.Timer) so DisposeAsync can drain any in-flight callback.
_opResultClearTimer?.Dispose();
_opResultClearTimer = new System.Threading.Timer(_ =>
{
_opResultMessage = null;
_opResultMessageFull = null;
InvokeAsync(StateHasChanged);
}, null, TimeSpan.FromSeconds(8), Timeout.InfiniteTimeSpan);
}
@@ -18,7 +18,7 @@
<div class="modal-footer">
@if (!string.IsNullOrEmpty(CurrentAddress))
{
<code class="me-auto mono">@CurrentAddress</code>
<code class="me-auto mono" title="@CurrentAddress">@DisplayText.Abbreviate(CurrentAddress, 60)</code>
}
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary" @onclick="OnCloseAsync">Close</button>
@@ -72,7 +72,7 @@
<div class="mt-3">
<span class="text-muted small">Result:</span>
<code class="mono ms-2">@_built</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
</div>
@code {
@@ -106,7 +106,7 @@
}
else
{
<code class="mono ms-2">@_built</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
}
</div>
@@ -92,7 +92,7 @@
<div class="mt-3">
<span class="text-muted small">Result:</span>
<code class="mono ms-2">@_built</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
</div>
@code {
@@ -54,7 +54,7 @@
<div class="mt-3">
<span class="text-muted small">Result:</span>
<code class="mono ms-2">@_built</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
</div>
@code {
@@ -155,11 +155,9 @@ else
<span class="chip chip-ok">Browser open</span>
<button type="button" class="btn btn-outline-secondary btn-sm" @onclick="CloseBrowseAsync">Close</button>
}
@* Same open-error chip the five sibling pickers use: abbreviated inline, full text on title. *@
@if (_openError is not null) { <span class="chip chip-bad" title="@_openError">@DisplayText.Abbreviate(_openError, 60)</span> }
</div>
@if (_openError is not null)
{
<div class="text-danger small mt-2">@_openError</div>
}
@if (_token != Guid.Empty)
{
@@ -207,7 +205,7 @@ else
<div class="mt-3">
<span class="text-muted small">TagConfig:</span>
<code class="mono ms-2">@(_built.Length == 0 ? "—" : _built)</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
</div>
@code {
@@ -61,7 +61,7 @@
<div class="mt-3">
<span class="text-muted small">Result:</span>
<code class="mono ms-2">@_built</code>
<code class="mono ms-2" title="@_built">@DisplayText.Abbreviate(_built, 64)</code>
</div>
@code {