Add mobile tables inspector sheet
This commit is contained in:
@@ -68,6 +68,7 @@ It is intentionally implementation-focused:
|
||||
| 2026-03-21 | P3.5 | Completed | Reworked the canvas with sticky headers, a sticky roll-band column, row and column emphasis driven by selection and roll-jump state, selected-cell treatment, and a comfortable/dense density toggle. |
|
||||
| 2026-03-21 | P3.6 | Completed | Removed the always-visible cell button stack from resting cells, leaving status-only hints by default and limiting compact edit/curation buttons to the currently selected cell. |
|
||||
| 2026-03-21 | P3.7 | Completed | Added a dedicated desktop inspector column that reads from the shared selected-cell state and keeps the selected result readable beside the grid. |
|
||||
| 2026-03-21 | P3.8 | Completed | Reused the inspector body inside a mobile bottom sheet with its own backdrop and close affordance so touch users keep the same selection-driven inspector model as desktop. |
|
||||
|
||||
### Lessons Learned
|
||||
|
||||
@@ -105,6 +106,7 @@ It is intentionally implementation-focused:
|
||||
- Canvas emphasis becomes maintainable once selection, roll-jump, and density are all fed through one explicit state model. That lets the grid respond to context without hiding selection logic inside CSS-only heuristics.
|
||||
- Resting-cell quietness should be enforced structurally, not only visually. Showing actions only for the selected cell prevents future CSS regressions from reintroducing button clutter across the whole grid.
|
||||
- The inspector should be its own sibling surface in the page layout, not nested inside the table shell. That keeps the content reusable for both desktop and the later mobile sheet without coupling it to canvas markup.
|
||||
- The inspector content itself should be shared independently of its container. Once the body is separated from the desktop column chrome, the mobile bottom sheet can reuse it with almost no behavioral drift.
|
||||
|
||||
## Target Outcomes
|
||||
|
||||
@@ -472,7 +474,7 @@ Build the shared interaction infrastructure needed by multiple destinations befo
|
||||
| `P3.5` | Completed | The canvas now supports sticky headers and roll bands, row and column emphasis from selection and roll-jump state, selected-cell treatment, and a comfortable/dense density toggle. |
|
||||
| `P3.6` | Completed | Resting cells now show only status hints; compact edit/curation buttons appear only for the selected cell. |
|
||||
| `P3.7` | Completed | Desktop now has a dedicated inspector column driven by the shared selected-cell state instead of forcing result reading back into the grid alone. |
|
||||
| `P3.8` | Pending | Add the mobile bottom-sheet inspector variant. |
|
||||
| `P3.8` | Completed | Mobile now uses a bottom-sheet inspector that reuses the same selected-cell content as the desktop inspector column. |
|
||||
| `P3.9` | Pending | Move legend/help to an on-demand secondary surface. |
|
||||
| `P3.10` | Pending | Hide maintenance and developer noise in default reference mode. |
|
||||
| `P3.11` | Pending | Preserve editor and curation entry points through the inspector. |
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
</aside>
|
||||
}
|
||||
</div>
|
||||
|
||||
<TablesInspectorSheet SelectedCellDetail="SelectedCellDetail" OnClose="ClearSelectedCell" />
|
||||
}
|
||||
</section>
|
||||
|
||||
@@ -700,6 +702,12 @@
|
||||
selectedCell = selection;
|
||||
}
|
||||
|
||||
private Task ClearSelectedCell()
|
||||
{
|
||||
selectedCell = null;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void NormalizeViewStateForCurrentDetail()
|
||||
{
|
||||
referenceMode = NormalizeMode(referenceMode);
|
||||
|
||||
@@ -1,50 +1,6 @@
|
||||
@if (SelectedCellDetail is null)
|
||||
{
|
||||
<aside class="tables-inspector" aria-label="Selected result inspector">
|
||||
<InspectorSection Title="Inspector" Description="Select a result in the table to inspect its details here.">
|
||||
<p class="tables-inspector-empty">Choose a cell to see its roll band, severity, and readable result without leaving the grid.</p>
|
||||
</InspectorSection>
|
||||
<TablesInspectorContent SelectedCellDetail="SelectedCellDetail" />
|
||||
</aside>
|
||||
}
|
||||
else
|
||||
{
|
||||
var cell = SelectedCellDetail;
|
||||
|
||||
<aside class="tables-inspector" aria-label="Selected result inspector">
|
||||
<InspectorSection Title="Selected Result" Description="Read the selected cell and its context without opening a modal.">
|
||||
<div class="tables-inspector-summary">
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Roll band</p>
|
||||
<strong>@cell.RollBand</strong>
|
||||
</div>
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Severity</p>
|
||||
<strong>@cell.ColumnLabel</strong>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(cell.GroupLabel))
|
||||
{
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Variant</p>
|
||||
<strong>@cell.GroupLabel</strong>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Status</p>
|
||||
<StatusChip Tone="@(cell.IsCurated ? "success" : "warning")">
|
||||
@(cell.IsCurated ? "Curated" : "Needs Curation")
|
||||
</StatusChip>
|
||||
</div>
|
||||
</div>
|
||||
</InspectorSection>
|
||||
|
||||
<InspectorSection Title="Result" Description="The selected critical result stays readable while you browse the grid.">
|
||||
<CompactCriticalCell
|
||||
Description="@(cell.Description ?? string.Empty)"
|
||||
Effects="@(cell.Effects ?? Array.Empty<CriticalEffectLookupResponse>())"
|
||||
Branches="@(cell.Branches ?? Array.Empty<CriticalBranchLookupResponse>())" />
|
||||
</InspectorSection>
|
||||
</aside>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
@if (SelectedCellDetail is null)
|
||||
{
|
||||
<InspectorSection Title="Inspector" Description="Select a result in the table to inspect its details here.">
|
||||
<p class="tables-inspector-empty">Choose a cell to see its roll band, severity, and readable result without leaving the grid.</p>
|
||||
</InspectorSection>
|
||||
}
|
||||
else
|
||||
{
|
||||
var cell = SelectedCellDetail;
|
||||
|
||||
<InspectorSection Title="Selected Result" Description="Read the selected cell and its context without opening a modal.">
|
||||
<div class="tables-inspector-summary">
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Roll band</p>
|
||||
<strong>@cell.RollBand</strong>
|
||||
</div>
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Severity</p>
|
||||
<strong>@cell.ColumnLabel</strong>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(cell.GroupLabel))
|
||||
{
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Variant</p>
|
||||
<strong>@cell.GroupLabel</strong>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<p class="tables-inspector-kicker">Status</p>
|
||||
<StatusChip Tone="@(cell.IsCurated ? "success" : "warning")">
|
||||
@(cell.IsCurated ? "Curated" : "Needs Curation")
|
||||
</StatusChip>
|
||||
</div>
|
||||
</div>
|
||||
</InspectorSection>
|
||||
|
||||
<InspectorSection Title="Result" Description="The selected critical result stays readable while you browse the grid.">
|
||||
<CompactCriticalCell
|
||||
Description="@(cell.Description ?? string.Empty)"
|
||||
Effects="@(cell.Effects ?? Array.Empty<CriticalEffectLookupResponse>())"
|
||||
Branches="@(cell.Branches ?? Array.Empty<CriticalBranchLookupResponse>())" />
|
||||
</InspectorSection>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public CriticalTableCellDetail? SelectedCellDetail { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
@if (SelectedCellDetail is not null)
|
||||
{
|
||||
<div class="tables-inspector-sheet" role="dialog" aria-modal="true" aria-label="Selected result inspector">
|
||||
<button type="button" class="tables-inspector-sheet-backdrop" @onclick="OnClose"></button>
|
||||
|
||||
<section class="tables-inspector-sheet-panel">
|
||||
<div class="tables-inspector-sheet-handle" aria-hidden="true"></div>
|
||||
<header class="tables-inspector-sheet-header">
|
||||
<div>
|
||||
<p class="tables-page-eyebrow">Selected Result</p>
|
||||
<h2 class="panel-title">Mobile Inspector</h2>
|
||||
</div>
|
||||
<button type="button" class="btn btn-link" @onclick="OnClose">Close</button>
|
||||
</header>
|
||||
|
||||
<div class="tables-inspector-sheet-body">
|
||||
<TablesInspectorContent SelectedCellDetail="SelectedCellDetail" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public CriticalTableCellDetail? SelectedCellDetail { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnClose { get; set; }
|
||||
}
|
||||
@@ -1351,6 +1351,10 @@ pre,
|
||||
gap: 0.85rem;
|
||||
}
|
||||
|
||||
.tables-inspector-sheet {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tables-inspector-empty {
|
||||
margin: 0;
|
||||
color: var(--ink-soft);
|
||||
@@ -1483,6 +1487,53 @@ pre,
|
||||
.tables-reference-inspector-shell {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tables-inspector-sheet {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
align-items: end;
|
||||
z-index: 60;
|
||||
}
|
||||
|
||||
.tables-inspector-sheet-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border: none;
|
||||
background: rgba(17, 18, 19, 0.38);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tables-inspector-sheet-panel {
|
||||
position: relative;
|
||||
display: grid;
|
||||
gap: 0.85rem;
|
||||
max-height: min(78vh, 42rem);
|
||||
padding: 0.85rem 1rem 1rem;
|
||||
border-radius: 24px 24px 0 0;
|
||||
background: var(--surface-card-strong);
|
||||
border: 1px solid rgba(127, 96, 55, 0.18);
|
||||
box-shadow: 0 -12px 32px rgba(18, 14, 9, 0.18);
|
||||
}
|
||||
|
||||
.tables-inspector-sheet-handle {
|
||||
width: 3.2rem;
|
||||
height: 0.32rem;
|
||||
margin: 0 auto;
|
||||
border-radius: 999px;
|
||||
background: rgba(127, 96, 55, 0.22);
|
||||
}
|
||||
|
||||
.tables-inspector-sheet-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 0.85rem;
|
||||
}
|
||||
|
||||
.tables-inspector-sheet-body {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.table-shell .table-scroll {
|
||||
|
||||
Reference in New Issue
Block a user