From 0daef1f7696fdb40eeef719ad5e3cf62162ad5b0 Mon Sep 17 00:00:00 2001 From: Frank Tovar Date: Sat, 21 Mar 2026 15:13:36 +0100 Subject: [PATCH] Add mobile tables inspector sheet --- ...s_frontend_overhaul_implementation_plan.md | 4 +- .../Components/Pages/Tables.razor | 8 +++ .../Components/Tables/TablesInspector.razor | 50 ++---------------- .../Tables/TablesInspectorContent.razor | 48 +++++++++++++++++ .../Tables/TablesInspectorSheet.razor | 29 +++++++++++ src/RolemasterDb.App/wwwroot/app.css | 51 +++++++++++++++++++ 6 files changed, 142 insertions(+), 48 deletions(-) create mode 100644 src/RolemasterDb.App/Components/Tables/TablesInspectorContent.razor create mode 100644 src/RolemasterDb.App/Components/Tables/TablesInspectorSheet.razor diff --git a/docs/tables_frontend_overhaul_implementation_plan.md b/docs/tables_frontend_overhaul_implementation_plan.md index 2b222af..9c28015 100644 --- a/docs/tables_frontend_overhaul_implementation_plan.md +++ b/docs/tables_frontend_overhaul_implementation_plan.md @@ -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. | diff --git a/src/RolemasterDb.App/Components/Pages/Tables.razor b/src/RolemasterDb.App/Components/Pages/Tables.razor index 9b55054..55ff75c 100644 --- a/src/RolemasterDb.App/Components/Pages/Tables.razor +++ b/src/RolemasterDb.App/Components/Pages/Tables.razor @@ -91,6 +91,8 @@ } + + } @@ -700,6 +702,12 @@ selectedCell = selection; } + private Task ClearSelectedCell() + { + selectedCell = null; + return Task.CompletedTask; + } + private void NormalizeViewStateForCurrentDetail() { referenceMode = NormalizeMode(referenceMode); diff --git a/src/RolemasterDb.App/Components/Tables/TablesInspector.razor b/src/RolemasterDb.App/Components/Tables/TablesInspector.razor index 5a9a0b0..f5ea6cc 100644 --- a/src/RolemasterDb.App/Components/Tables/TablesInspector.razor +++ b/src/RolemasterDb.App/Components/Tables/TablesInspector.razor @@ -1,50 +1,6 @@ -@if (SelectedCellDetail is null) -{ - -} -else -{ - var cell = SelectedCellDetail; - - -} + @code { [Parameter] diff --git a/src/RolemasterDb.App/Components/Tables/TablesInspectorContent.razor b/src/RolemasterDb.App/Components/Tables/TablesInspectorContent.razor new file mode 100644 index 0000000..fe2bd48 --- /dev/null +++ b/src/RolemasterDb.App/Components/Tables/TablesInspectorContent.razor @@ -0,0 +1,48 @@ +@if (SelectedCellDetail is null) +{ + +

Choose a cell to see its roll band, severity, and readable result without leaving the grid.

+
+} +else +{ + var cell = SelectedCellDetail; + + +
+
+

Roll band

+ @cell.RollBand +
+
+

Severity

+ @cell.ColumnLabel +
+ @if (!string.IsNullOrWhiteSpace(cell.GroupLabel)) + { +
+

Variant

+ @cell.GroupLabel +
+ } +
+

Status

+ + @(cell.IsCurated ? "Curated" : "Needs Curation") + +
+
+
+ + + + +} + +@code { + [Parameter] + public CriticalTableCellDetail? SelectedCellDetail { get; set; } +} diff --git a/src/RolemasterDb.App/Components/Tables/TablesInspectorSheet.razor b/src/RolemasterDb.App/Components/Tables/TablesInspectorSheet.razor new file mode 100644 index 0000000..fcdb89d --- /dev/null +++ b/src/RolemasterDb.App/Components/Tables/TablesInspectorSheet.razor @@ -0,0 +1,29 @@ +@if (SelectedCellDetail is not null) +{ + +} + +@code { + [Parameter] + public CriticalTableCellDetail? SelectedCellDetail { get; set; } + + [Parameter] + public EventCallback OnClose { get; set; } +} diff --git a/src/RolemasterDb.App/wwwroot/app.css b/src/RolemasterDb.App/wwwroot/app.css index 5a356d8..b5aa2ab 100644 --- a/src/RolemasterDb.App/wwwroot/app.css +++ b/src/RolemasterDb.App/wwwroot/app.css @@ -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 {