Tighten tables layout and grid behavior
This commit is contained in:
@@ -74,6 +74,7 @@ It is intentionally implementation-focused:
|
|||||||
| 2026-03-21 | P3.11 | Completed | Moved the live editor and curation entry points into the shared inspector content and removed the last remaining grid-owned action buttons. |
|
| 2026-03-21 | P3.11 | Completed | Moved the live editor and curation entry points into the shared inspector content and removed the last remaining grid-owned action buttons. |
|
||||||
| 2026-03-21 | P3.12 | Completed | Added keyboard-selectable cells, visible focus treatment, and selection normalization so changing filters or modes cannot leave the inspector pointing at hidden cells. |
|
| 2026-03-21 | P3.12 | Completed | Added keyboard-selectable cells, visible focus treatment, and selection normalization so changing filters or modes cannot leave the inspector pointing at hidden cells. |
|
||||||
| 2026-03-21 | Post-P3 fix 1 | Completed | Added a defensive visible-column fallback in the table canvas and tightened view-state normalization so a stale severity filter cannot collapse the grid to roll bands only. |
|
| 2026-03-21 | Post-P3 fix 1 | Completed | Added a defensive visible-column fallback in the table canvas and tightened view-state normalization so a stale severity filter cannot collapse the grid to roll bands only. |
|
||||||
|
| 2026-04-11 | Post-P3 fix 2 | Completed | Simplified `/tables` by removing static prose and context controls, dropped the redundant selected-result inspector in favor of a floating action menu, and moved the canvas onto its own scroll region so sticky headers layer correctly beneath the context bar. |
|
||||||
|
|
||||||
### Lessons Learned
|
### Lessons Learned
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<PageTitle>Critical Tables</PageTitle>
|
<PageTitle>Critical Tables</PageTitle>
|
||||||
|
|
||||||
<section class="panel tables-page">
|
<section class="panel tables-page">
|
||||||
<TablesPageHeader />
|
<TablesPageHeader/>
|
||||||
|
|
||||||
@if (referenceData is null)
|
@if (referenceData is null)
|
||||||
{
|
{
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
PinnedTableSlugs="PinnedTablesState.Items.Select(item => item.Slug).ToArray()"
|
PinnedTableSlugs="PinnedTablesState.Items.Select(item => item.Slug).ToArray()"
|
||||||
RecentTableSlugs="RecentTablesState.Items.Select(item => item.Slug).ToArray()"
|
RecentTableSlugs="RecentTablesState.Items.Select(item => item.Slug).ToArray()"
|
||||||
IsPinned="PinnedTablesState.IsPinned"
|
IsPinned="PinnedTablesState.IsPinned"
|
||||||
OnSelectTable="SelectTableAsync" />
|
OnSelectTable="SelectTableAsync"/>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div class="tables-reference-main">
|
<div class="tables-reference-main">
|
||||||
@@ -57,19 +57,9 @@
|
|||||||
<TablesContextBar
|
<TablesContextBar
|
||||||
Detail="detail"
|
Detail="detail"
|
||||||
IsPinned="PinnedTablesState.IsPinned(detail.Slug)"
|
IsPinned="PinnedTablesState.IsPinned(detail.Slug)"
|
||||||
CurrentMode="referenceMode"
|
|
||||||
SelectedGroupKey="selectedGroupKey"
|
|
||||||
SelectedColumnKey="selectedColumnKey"
|
|
||||||
RollJumpValue="rollJumpValue"
|
|
||||||
DensityMode="densityMode"
|
|
||||||
OnTogglePin="TogglePinnedTableAsync"
|
OnTogglePin="TogglePinnedTableAsync"
|
||||||
IsLegendOpen="isLegendOpen"
|
IsLegendOpen="isLegendOpen"
|
||||||
OnToggleLegend="ToggleLegend"
|
OnToggleLegend="ToggleLegend"/>
|
||||||
OnModeChanged="UpdateReferenceModeAsync"
|
|
||||||
OnGroupChanged="UpdateSelectedGroupAsync"
|
|
||||||
OnColumnChanged="UpdateSelectedColumnAsync"
|
|
||||||
OnRollJumpChanged="UpdateRollJumpAsync"
|
|
||||||
OnDensityChanged="UpdateDensityModeAsync" />
|
|
||||||
|
|
||||||
<TablesCanvas
|
<TablesCanvas
|
||||||
Detail="detail"
|
Detail="detail"
|
||||||
@@ -79,32 +69,21 @@
|
|||||||
RollJumpValue="rollJumpValue"
|
RollJumpValue="rollJumpValue"
|
||||||
DensityMode="densityMode"
|
DensityMode="densityMode"
|
||||||
SelectedCell="selectedCell"
|
SelectedCell="selectedCell"
|
||||||
OnSelectCell="SelectCell" />
|
OnSelectCell="SelectCell"/>
|
||||||
|
|
||||||
@if (isLegendOpen)
|
@if (isLegendOpen)
|
||||||
{
|
{
|
||||||
<TablesLegend LegendEntries="@(detail.Legend ?? Array.Empty<CriticalTableLegendEntry>())" />
|
<TablesLegend LegendEntries="@(detail.Legend ?? Array.Empty<CriticalTableLegendEntry>())"/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (tableDetail is not null)
|
|
||||||
{
|
|
||||||
<aside class="tables-reference-inspector-shell">
|
|
||||||
<TablesInspector
|
|
||||||
SelectedCellDetail="SelectedCellDetail"
|
|
||||||
OnEdit="OpenSelectedCellEditorAsync"
|
|
||||||
OnCurate="OpenSelectedCellCurationAsync" />
|
|
||||||
</aside>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TablesInspectorSheet
|
<TablesSelectionMenu
|
||||||
SelectedCellDetail="SelectedCellDetail"
|
SelectedCellDetail="SelectedCellDetail"
|
||||||
OnClose="ClearSelectedCell"
|
|
||||||
OnEdit="OpenSelectedCellEditorAsync"
|
OnEdit="OpenSelectedCellEditorAsync"
|
||||||
OnCurate="OpenSelectedCellCurationAsync" />
|
OnCurate="OpenSelectedCellCurationAsync"/>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -125,7 +104,7 @@
|
|||||||
OnEdit="OpenEditorFromCurationAsync"
|
OnEdit="OpenEditorFromCurationAsync"
|
||||||
OnEnterQuickParse="EnterCurationQuickParseMode"
|
OnEnterQuickParse="EnterCurationQuickParseMode"
|
||||||
OnCancelQuickParse="CancelCurationQuickParseMode"
|
OnCancelQuickParse="CancelCurationQuickParseMode"
|
||||||
OnReparse="ReparseCurationCellAsync" />
|
OnReparse="ReparseCurationCellAsync"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (isEditorOpen)
|
@if (isEditorOpen)
|
||||||
@@ -142,7 +121,7 @@
|
|||||||
SaveErrorMessage="@editorSaveError"
|
SaveErrorMessage="@editorSaveError"
|
||||||
OnClose="CloseCellEditorAsync"
|
OnClose="CloseCellEditorAsync"
|
||||||
OnReparse="ReparseCellEditorAsync"
|
OnReparse="ReparseCellEditorAsync"
|
||||||
OnSave="SaveCellEditorAsync" />
|
OnSave="SaveCellEditorAsync"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@@ -151,9 +130,7 @@
|
|||||||
private CriticalTableDetail? tableDetail;
|
private CriticalTableDetail? tableDetail;
|
||||||
private string selectedTableSlug = string.Empty;
|
private string selectedTableSlug = string.Empty;
|
||||||
private bool isDetailLoading;
|
private bool isDetailLoading;
|
||||||
private bool isReferenceDataLoading = true;
|
|
||||||
private string? detailError;
|
private string? detailError;
|
||||||
private bool IsTableSelectionDisabled => isReferenceDataLoading || (referenceData?.CriticalTables.Count ?? 0) == 0;
|
|
||||||
private bool isEditorOpen;
|
private bool isEditorOpen;
|
||||||
private bool isEditorLoading;
|
private bool isEditorLoading;
|
||||||
private bool isEditorReparsing;
|
private bool isEditorReparsing;
|
||||||
@@ -181,17 +158,16 @@
|
|||||||
private TablesCellSelection? selectedCell;
|
private TablesCellSelection? selectedCell;
|
||||||
private bool isLegendOpen;
|
private bool isLegendOpen;
|
||||||
private bool hasResolvedStoredTableSelection;
|
private bool hasResolvedStoredTableSelection;
|
||||||
|
|
||||||
private CriticalTableReference? SelectedTableReference =>
|
private CriticalTableReference? SelectedTableReference =>
|
||||||
referenceData?.CriticalTables.FirstOrDefault(item => string.Equals(item.Key, selectedTableSlug, StringComparison.OrdinalIgnoreCase));
|
referenceData?.CriticalTables.FirstOrDefault(item => string.Equals(item.Key, selectedTableSlug, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
private CriticalTableCellDetail? SelectedCellDetail =>
|
private CriticalTableCellDetail? SelectedCellDetail =>
|
||||||
selectedCell is null
|
selectedCell is null ? null : tableDetail?.Cells.FirstOrDefault(cell => cell.ResultId == selectedCell.ResultId);
|
||||||
? null
|
|
||||||
: tableDetail?.Cells.FirstOrDefault(cell => cell.ResultId == selectedCell.ResultId);
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
referenceData = await LookupService.GetReferenceDataAsync();
|
referenceData = await LookupService.GetReferenceDataAsync();
|
||||||
isReferenceDataLoading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SelectTableAsync(string tableSlug)
|
private async Task SelectTableAsync(string tableSlug)
|
||||||
@@ -247,17 +223,12 @@
|
|||||||
|
|
||||||
if (!hasResolvedStoredTableSelection && referenceData?.CriticalTables.Count > 0)
|
if (!hasResolvedStoredTableSelection && referenceData?.CriticalTables.Count > 0)
|
||||||
{
|
{
|
||||||
var initialContext = await TableContextState.RestoreAsync(
|
var initialContext = await TableContextState.RestoreAsync(NavigationManager.Uri, ContextDestination, referenceData.CriticalTables, RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
||||||
NavigationManager.Uri,
|
|
||||||
ContextDestination,
|
|
||||||
referenceData.CriticalTables,
|
|
||||||
RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
|
||||||
|
|
||||||
hasResolvedStoredTableSelection = true;
|
hasResolvedStoredTableSelection = true;
|
||||||
|
|
||||||
var resolvedTableSlug = initialContext.TableSlug ?? string.Empty;
|
var resolvedTableSlug = initialContext.TableSlug ?? string.Empty;
|
||||||
if (string.IsNullOrWhiteSpace(selectedTableSlug) ||
|
if (string.IsNullOrWhiteSpace(selectedTableSlug) || !string.Equals(resolvedTableSlug, selectedTableSlug, StringComparison.OrdinalIgnoreCase))
|
||||||
!string.Equals(resolvedTableSlug, selectedTableSlug, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
selectedTableSlug = resolvedTableSlug;
|
selectedTableSlug = resolvedTableSlug;
|
||||||
await LoadTableDetailAsync();
|
await LoadTableDetailAsync();
|
||||||
@@ -489,11 +460,7 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var orderedCells = tableDetail.Cells
|
var orderedCells = tableDetail.Cells.OrderBy(cell => GetGroupSortOrder(cell.GroupKey)).ThenBy(cell => GetColumnSortOrder(cell.ColumnKey)).ThenBy(cell => GetRollBandSortOrder(cell.RollBand)).ToList();
|
||||||
.OrderBy(cell => GetGroupSortOrder(cell.GroupKey))
|
|
||||||
.ThenBy(cell => GetColumnSortOrder(cell.ColumnKey))
|
|
||||||
.ThenBy(cell => GetRollBandSortOrder(cell.RollBand))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var currentIndex = orderedCells.FindIndex(cell => cell.ResultId == currentResultId);
|
var currentIndex = orderedCells.FindIndex(cell => cell.ResultId == currentResultId);
|
||||||
for (var index = currentIndex + 1; index < orderedCells.Count; index++)
|
for (var index = currentIndex + 1; index < orderedCells.Count; index++)
|
||||||
@@ -514,9 +481,7 @@
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableDetail.Groups
|
return tableDetail.Groups.FirstOrDefault(group => string.Equals(group.Key, groupKey, StringComparison.OrdinalIgnoreCase))?.SortOrder ?? int.MaxValue;
|
||||||
.FirstOrDefault(group => string.Equals(group.Key, groupKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
?.SortOrder ?? int.MaxValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetColumnSortOrder(string columnKey)
|
private int GetColumnSortOrder(string columnKey)
|
||||||
@@ -526,9 +491,7 @@
|
|||||||
return int.MaxValue;
|
return int.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableDetail.Columns
|
return tableDetail.Columns.FirstOrDefault(column => string.Equals(column.Key, columnKey, StringComparison.OrdinalIgnoreCase))?.SortOrder ?? int.MaxValue;
|
||||||
.FirstOrDefault(column => string.Equals(column.Key, columnKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
?.SortOrder ?? int.MaxValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetRollBandSortOrder(string rollBandLabel)
|
private int GetRollBandSortOrder(string rollBandLabel)
|
||||||
@@ -538,9 +501,7 @@
|
|||||||
return int.MaxValue;
|
return int.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableDetail.RollBands
|
return tableDetail.RollBands.FirstOrDefault(rollBand => string.Equals(rollBand.Label, rollBandLabel, StringComparison.OrdinalIgnoreCase))?.SortOrder ?? int.MaxValue;
|
||||||
.FirstOrDefault(rollBand => string.Equals(rollBand.Label, rollBandLabel, StringComparison.OrdinalIgnoreCase))
|
|
||||||
?.SortOrder ?? int.MaxValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CloseCellEditorAsync()
|
private async Task CloseCellEditorAsync()
|
||||||
@@ -634,11 +595,7 @@
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PinnedTablesState.ToggleAsync(
|
return PinnedTablesState.ToggleAsync(selectedTable.Key, selectedTable.Label, selectedTable.Family, selectedTable.CurationPercentage);
|
||||||
selectedTable.Key,
|
|
||||||
selectedTable.Label,
|
|
||||||
selectedTable.Family,
|
|
||||||
selectedTable.CurationPercentage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task RecordRecentTableVisitAsync()
|
private Task RecordRecentTableVisitAsync()
|
||||||
@@ -648,11 +605,7 @@
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RecentTablesState.RecordVisitAsync(
|
return RecentTablesState.RecordVisitAsync(selectedTable.Key, selectedTable.Label, selectedTable.Family, selectedTable.CurationPercentage);
|
||||||
selectedTable.Key,
|
|
||||||
selectedTable.Label,
|
|
||||||
selectedTable.Family,
|
|
||||||
selectedTable.CurationPercentage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PersistAndSyncTableContextAsync()
|
private async Task PersistAndSyncTableContextAsync()
|
||||||
@@ -670,42 +623,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RolemasterDb.App.Frontend.AppState.TableContextSnapshot BuildCurrentTableContext() =>
|
private RolemasterDb.App.Frontend.AppState.TableContextSnapshot BuildCurrentTableContext() =>
|
||||||
new(
|
new(TableSlug: selectedTableSlug, Mode: RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
||||||
TableSlug: selectedTableSlug,
|
|
||||||
Mode: RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
|
||||||
|
|
||||||
private Task UpdateReferenceModeAsync(string mode)
|
|
||||||
{
|
|
||||||
referenceMode = NormalizeMode(mode);
|
|
||||||
NormalizeSelectedCellForCurrentView();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task UpdateSelectedGroupAsync(string groupKey)
|
|
||||||
{
|
|
||||||
selectedGroupKey = NormalizeOptionalFilter(groupKey);
|
|
||||||
NormalizeSelectedCellForCurrentView();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task UpdateSelectedColumnAsync(string columnKey)
|
|
||||||
{
|
|
||||||
selectedColumnKey = NormalizeOptionalFilter(columnKey);
|
|
||||||
NormalizeSelectedCellForCurrentView();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task UpdateRollJumpAsync(string rollValue)
|
|
||||||
{
|
|
||||||
rollJumpValue = NormalizeRollInput(rollValue);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task UpdateDensityModeAsync(string mode)
|
|
||||||
{
|
|
||||||
densityMode = NormalizeDensityMode(mode);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SelectCell(TablesCellSelection selection)
|
private void SelectCell(TablesCellSelection selection)
|
||||||
{
|
{
|
||||||
@@ -718,21 +636,11 @@
|
|||||||
selectedCell = selection;
|
selectedCell = selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ClearSelectedCell()
|
|
||||||
{
|
|
||||||
selectedCell = null;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task OpenSelectedCellEditorAsync() =>
|
private Task OpenSelectedCellEditorAsync() =>
|
||||||
selectedCell is null
|
selectedCell is null ? Task.CompletedTask : OpenCellEditorAsync(selectedCell.ResultId);
|
||||||
? Task.CompletedTask
|
|
||||||
: OpenCellEditorAsync(selectedCell.ResultId);
|
|
||||||
|
|
||||||
private Task OpenSelectedCellCurationAsync() =>
|
private Task OpenSelectedCellCurationAsync() =>
|
||||||
selectedCell is null
|
selectedCell is null ? Task.CompletedTask : OpenCellCurationAsync(selectedCell.ResultId);
|
||||||
? Task.CompletedTask
|
|
||||||
: OpenCellCurationAsync(selectedCell.ResultId);
|
|
||||||
|
|
||||||
private Task ToggleLegend()
|
private Task ToggleLegend()
|
||||||
{
|
{
|
||||||
@@ -759,10 +667,7 @@
|
|||||||
selectedGroupKey = string.Empty;
|
selectedGroupKey = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchingColumns = tableDetail.Columns
|
var matchingColumns = tableDetail.Columns.Where(column => string.IsNullOrWhiteSpace(selectedColumnKey) || string.Equals(column.Key, selectedColumnKey, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
.Where(column => string.IsNullOrWhiteSpace(selectedColumnKey)
|
|
||||||
|| string.Equals(column.Key, selectedColumnKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (matchingColumns.Count == 0)
|
if (matchingColumns.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -784,17 +689,12 @@
|
|||||||
mode switch
|
mode switch
|
||||||
{
|
{
|
||||||
TablesReferenceMode.NeedsCuration => TablesReferenceMode.NeedsCuration,
|
TablesReferenceMode.NeedsCuration => TablesReferenceMode.NeedsCuration,
|
||||||
TablesReferenceMode.Curated => TablesReferenceMode.Curated,
|
TablesReferenceMode.Curated => TablesReferenceMode.Curated,
|
||||||
_ => TablesReferenceMode.Reference
|
_ => TablesReferenceMode.Reference
|
||||||
};
|
};
|
||||||
|
|
||||||
private static string NormalizeOptionalFilter(string? value) =>
|
|
||||||
string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
|
|
||||||
|
|
||||||
private static string NormalizeDensityMode(string? mode) =>
|
private static string NormalizeDensityMode(string? mode) =>
|
||||||
string.Equals(mode, TablesDensityMode.Dense, StringComparison.Ordinal)
|
string.Equals(mode, TablesDensityMode.Dense, StringComparison.Ordinal) ? TablesDensityMode.Dense : TablesDensityMode.Comfortable;
|
||||||
? TablesDensityMode.Dense
|
|
||||||
: TablesDensityMode.Comfortable;
|
|
||||||
|
|
||||||
private static string NormalizeRollInput(string? value)
|
private static string NormalizeRollInput(string? value)
|
||||||
{
|
{
|
||||||
@@ -823,14 +723,12 @@
|
|||||||
|
|
||||||
private bool MatchesCurrentView(CriticalTableCellDetail cell)
|
private bool MatchesCurrentView(CriticalTableCellDetail cell)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(selectedGroupKey) &&
|
if (!string.IsNullOrWhiteSpace(selectedGroupKey) && !string.Equals(cell.GroupKey, selectedGroupKey, StringComparison.OrdinalIgnoreCase))
|
||||||
!string.Equals(cell.GroupKey, selectedGroupKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(selectedColumnKey) &&
|
if (!string.IsNullOrWhiteSpace(selectedColumnKey) && !string.Equals(cell.ColumnKey, selectedColumnKey, StringComparison.OrdinalIgnoreCase))
|
||||||
!string.Equals(cell.ColumnKey, selectedColumnKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -838,8 +736,9 @@
|
|||||||
return referenceMode switch
|
return referenceMode switch
|
||||||
{
|
{
|
||||||
TablesReferenceMode.NeedsCuration => !cell.IsCurated,
|
TablesReferenceMode.NeedsCuration => !cell.IsCurated,
|
||||||
TablesReferenceMode.Curated => cell.IsCurated,
|
TablesReferenceMode.Curated => cell.IsCurated,
|
||||||
_ => true
|
_ => true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
<div class="critical-table-cell-actions">
|
<div class="critical-table-cell-actions">
|
||||||
@if (string.Equals(CurrentMode, TablesReferenceMode.Reference, StringComparison.Ordinal))
|
@if (string.Equals(CurrentMode, TablesReferenceMode.Reference, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
<StatusIndicator Tone="@(cell.IsCurated ? "success" : "warning")" CssClass="tables-cell-status-indicator" />
|
<StatusIndicator Tone="@(cell.IsCurated ? "success" : "warning")" CssClass="tables-cell-status-indicator"/>
|
||||||
}
|
}
|
||||||
else if (cell.IsCurated)
|
else if (cell.IsCurated)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<CompactCriticalCell
|
<CompactCriticalCell
|
||||||
Description="@(cell.Description ?? string.Empty)"
|
Description="@(cell.Description ?? string.Empty)"
|
||||||
Effects="@(cell.Effects ?? Array.Empty<CriticalEffectLookupResponse>())"
|
Effects="@(cell.Effects ?? Array.Empty<CriticalEffectLookupResponse>())"
|
||||||
Branches="@(cell.Branches ?? Array.Empty<CriticalBranchLookupResponse>())" />
|
Branches="@(cell.Branches ?? Array.Empty<CriticalBranchLookupResponse>())"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -170,66 +170,60 @@
|
|||||||
cellIndex.TryGetValue((rollBand, groupKey, columnKey), out cell);
|
cellIndex.TryGetValue((rollBand, groupKey, columnKey), out cell);
|
||||||
|
|
||||||
private bool MatchesGroupFilter(CriticalGroupReference group) =>
|
private bool MatchesGroupFilter(CriticalGroupReference group) =>
|
||||||
string.IsNullOrWhiteSpace(SelectedGroupKey)
|
string.IsNullOrWhiteSpace(SelectedGroupKey) || string.Equals(group.Key, SelectedGroupKey, StringComparison.OrdinalIgnoreCase);
|
||||||
|| string.Equals(group.Key, SelectedGroupKey, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
private bool MatchesColumnFilter(CriticalColumnReference column) =>
|
private bool MatchesColumnFilter(CriticalColumnReference column) =>
|
||||||
string.IsNullOrWhiteSpace(SelectedColumnKey)
|
string.IsNullOrWhiteSpace(SelectedColumnKey) || string.Equals(column.Key, SelectedColumnKey, StringComparison.OrdinalIgnoreCase);
|
||||||
|| string.Equals(column.Key, SelectedColumnKey, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
private IReadOnlyList<CriticalGroupReference> ResolveVisibleGroups()
|
private IReadOnlyList<CriticalGroupReference> ResolveVisibleGroups()
|
||||||
{
|
{
|
||||||
var filteredGroups = Detail.Groups
|
var filteredGroups = Detail.Groups.Where(MatchesGroupFilter).ToList();
|
||||||
.Where(MatchesGroupFilter)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return filteredGroups.Count > 0
|
return filteredGroups.Count > 0 ? filteredGroups : Detail.Groups;
|
||||||
? filteredGroups
|
|
||||||
: Detail.Groups;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<CriticalColumnReference> ResolveVisibleColumns()
|
private IReadOnlyList<CriticalColumnReference> ResolveVisibleColumns()
|
||||||
{
|
{
|
||||||
var filteredColumns = Detail.Columns
|
var filteredColumns = Detail.Columns.Where(MatchesColumnFilter).ToList();
|
||||||
.Where(MatchesColumnFilter)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return filteredColumns.Count > 0
|
return filteredColumns.Count > 0 ? filteredColumns : Detail.Columns;
|
||||||
? filteredColumns
|
|
||||||
: Detail.Columns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MatchesModeFilter(CriticalTableCellDetail cell) =>
|
private bool MatchesModeFilter(CriticalTableCellDetail cell) =>
|
||||||
CurrentMode switch
|
CurrentMode switch
|
||||||
{
|
{
|
||||||
TablesReferenceMode.NeedsCuration => !cell.IsCurated,
|
TablesReferenceMode.NeedsCuration => !cell.IsCurated,
|
||||||
TablesReferenceMode.Curated => cell.IsCurated,
|
TablesReferenceMode.Curated => cell.IsCurated,
|
||||||
_ => true
|
_ => true
|
||||||
};
|
};
|
||||||
|
|
||||||
private string? ActiveRollBand =>
|
private string? ActiveRollBand =>
|
||||||
!string.IsNullOrWhiteSpace(SelectedCell?.RollBand)
|
!string.IsNullOrWhiteSpace(SelectedCell?.RollBand) ? SelectedCell.RollBand : ResolveRollJumpBandLabel();
|
||||||
? SelectedCell.RollBand
|
|
||||||
: ResolveRollJumpBandLabel();
|
|
||||||
|
|
||||||
private string? ActiveColumnKey =>
|
private string? ActiveColumnKey =>
|
||||||
!string.IsNullOrWhiteSpace(SelectedCell?.ColumnKey)
|
!string.IsNullOrWhiteSpace(SelectedCell?.ColumnKey) ? SelectedCell.ColumnKey : (!string.IsNullOrWhiteSpace(SelectedColumnKey) ? SelectedColumnKey : null);
|
||||||
? SelectedCell.ColumnKey
|
|
||||||
: (!string.IsNullOrWhiteSpace(SelectedColumnKey) ? SelectedColumnKey : null);
|
|
||||||
|
|
||||||
private string? ActiveGroupKey =>
|
private string? ActiveGroupKey =>
|
||||||
!string.IsNullOrWhiteSpace(SelectedCell?.GroupKey)
|
!string.IsNullOrWhiteSpace(SelectedCell?.GroupKey) ? SelectedCell.GroupKey : (!string.IsNullOrWhiteSpace(SelectedGroupKey) ? SelectedGroupKey : null);
|
||||||
? SelectedCell.GroupKey
|
|
||||||
: (!string.IsNullOrWhiteSpace(SelectedGroupKey) ? SelectedGroupKey : null);
|
|
||||||
|
|
||||||
private string BuildGridCssClass() =>
|
private string BuildGridCssClass()
|
||||||
string.Equals(DensityMode, TablesDensityMode.Dense, StringComparison.Ordinal)
|
{
|
||||||
? "is-dense"
|
var classes = new List<string>
|
||||||
: "is-comfortable";
|
{
|
||||||
|
string.Equals(DensityMode, TablesDensityMode.Dense, StringComparison.Ordinal) ? "is-dense" : "is-comfortable",
|
||||||
|
Detail.Groups.Count > 0 ? "has-groups" : "has-no-groups"
|
||||||
|
};
|
||||||
|
|
||||||
|
return string.Join(' ', classes);
|
||||||
|
}
|
||||||
|
|
||||||
private string BuildGroupHeaderCssClass(string groupKey)
|
private string BuildGroupHeaderCssClass(string groupKey)
|
||||||
{
|
{
|
||||||
var classes = new List<string> { "critical-table-grid-header-cell", "critical-table-grid-group-header" };
|
var classes = new List<string>
|
||||||
|
{
|
||||||
|
"critical-table-grid-header-cell",
|
||||||
|
"critical-table-grid-group-header"
|
||||||
|
};
|
||||||
if (string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
classes.Add("is-active-group");
|
classes.Add("is-active-group");
|
||||||
@@ -240,15 +234,18 @@
|
|||||||
|
|
||||||
private string BuildColumnHeaderCssClass(string? groupKey, string columnKey)
|
private string BuildColumnHeaderCssClass(string? groupKey, string columnKey)
|
||||||
{
|
{
|
||||||
var classes = new List<string> { "critical-table-grid-header-cell", "critical-table-grid-column-header" };
|
var classes = new List<string>
|
||||||
|
{
|
||||||
|
"critical-table-grid-header-cell",
|
||||||
|
"critical-table-grid-column-header"
|
||||||
|
};
|
||||||
|
|
||||||
if (string.Equals(columnKey, ActiveColumnKey, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(columnKey, ActiveColumnKey, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
classes.Add("is-active-column");
|
classes.Add("is-active-column");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(groupKey) &&
|
if (!string.IsNullOrWhiteSpace(groupKey) && string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
||||||
string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
classes.Add("is-active-group");
|
classes.Add("is-active-group");
|
||||||
}
|
}
|
||||||
@@ -258,7 +255,11 @@
|
|||||||
|
|
||||||
private string BuildRollBandCssClass(string rollBandLabel)
|
private string BuildRollBandCssClass(string rollBandLabel)
|
||||||
{
|
{
|
||||||
var classes = new List<string> { "critical-table-grid-header-cell", "critical-table-grid-roll-band" };
|
var classes = new List<string>
|
||||||
|
{
|
||||||
|
"critical-table-grid-header-cell",
|
||||||
|
"critical-table-grid-roll-band"
|
||||||
|
};
|
||||||
if (string.Equals(rollBandLabel, ActiveRollBand, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(rollBandLabel, ActiveRollBand, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
classes.Add("is-active-row");
|
classes.Add("is-active-row");
|
||||||
@@ -290,8 +291,7 @@
|
|||||||
classes.Add("is-active-column");
|
classes.Add("is-active-column");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(groupKey) &&
|
if (!string.IsNullOrWhiteSpace(groupKey) && string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
||||||
string.Equals(groupKey, ActiveGroupKey, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
classes.Add("is-active-group");
|
classes.Add("is-active-group");
|
||||||
}
|
}
|
||||||
@@ -340,9 +340,7 @@
|
|||||||
|
|
||||||
private Task HandleCellKeyDown(KeyboardEventArgs args, CriticalTableCellDetail cell)
|
private Task HandleCellKeyDown(KeyboardEventArgs args, CriticalTableCellDetail cell)
|
||||||
{
|
{
|
||||||
if (string.Equals(args.Key, "Enter", StringComparison.Ordinal) ||
|
if (string.Equals(args.Key, "Enter", StringComparison.Ordinal) || string.Equals(args.Key, " ", StringComparison.Ordinal) || string.Equals(args.Key, "Spacebar", StringComparison.Ordinal))
|
||||||
string.Equals(args.Key, " ", StringComparison.Ordinal) ||
|
|
||||||
string.Equals(args.Key, "Spacebar", StringComparison.Ordinal))
|
|
||||||
{
|
{
|
||||||
return SelectCell(cell);
|
return SelectCell(cell);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<header class="table-browser-header tables-context-bar">
|
<header class="table-browser-header tables-context-bar">
|
||||||
<div class="tables-context-primary">
|
<div class="tables-context-primary">
|
||||||
<div>
|
<h2 class="panel-title">@Detail.DisplayName</h2>
|
||||||
<h2 class="panel-title">@Detail.DisplayName</h2>
|
|
||||||
<p class="table-browser-reading-hint">@GetReadingHint()</p>
|
|
||||||
</div>
|
|
||||||
<div class="action-row">
|
<div class="action-row">
|
||||||
<button type="button" class="btn btn-link" @onclick="() => OnTogglePin.InvokeAsync()">
|
<button type="button" class="btn btn-link" @onclick="() => OnTogglePin.InvokeAsync()">
|
||||||
@(IsPinned ? "Unpin table" : "Pin table")
|
@(IsPinned ? "Unpin table" : "Pin table")
|
||||||
@@ -11,116 +8,11 @@
|
|||||||
<button type="button" class="btn btn-link" @onclick="() => OnToggleLegend.InvokeAsync()">
|
<button type="button" class="btn btn-link" @onclick="() => OnToggleLegend.InvokeAsync()">
|
||||||
@(IsLegendOpen ? "Hide help" : "Reading help")
|
@(IsLegendOpen ? "Hide help" : "Reading help")
|
||||||
</button>
|
</button>
|
||||||
<p class="table-browser-edit-hint">Select a result to inspect it beside the table.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tables-context-controls">
|
|
||||||
<div class="tables-context-tab-row">
|
|
||||||
<SegmentedTabs
|
|
||||||
Items="modeTabs"
|
|
||||||
SelectedValue="CurrentMode"
|
|
||||||
SelectedValueChanged="OnModeChanged"
|
|
||||||
AriaLabel="Reference mode"
|
|
||||||
CssClass="tables-context-mode-tabs" />
|
|
||||||
|
|
||||||
<SegmentedTabs
|
|
||||||
Items="densityTabs"
|
|
||||||
SelectedValue="DensityMode"
|
|
||||||
SelectedValueChanged="OnDensityChanged"
|
|
||||||
AriaLabel="Table density"
|
|
||||||
CssClass="tables-context-density-tabs" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tables-context-fields">
|
|
||||||
@if (Detail.Groups.Count > 1)
|
|
||||||
{
|
|
||||||
<label class="tables-context-field">
|
|
||||||
<span>Variant</span>
|
|
||||||
<select class="input-shell" value="@SelectedGroupKey" @onchange="HandleGroupChanged">
|
|
||||||
<option value="">All variants</option>
|
|
||||||
@foreach (var group in Detail.Groups)
|
|
||||||
{
|
|
||||||
<option value="@group.Key">@group.Label</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Detail.Columns.Count > 1)
|
|
||||||
{
|
|
||||||
<label class="tables-context-field">
|
|
||||||
<span>Severity focus</span>
|
|
||||||
<select class="input-shell" value="@SelectedColumnKey" @onchange="HandleColumnChanged">
|
|
||||||
<option value="">All severities</option>
|
|
||||||
@foreach (var column in Detail.Columns)
|
|
||||||
{
|
|
||||||
<option value="@column.Key">@column.Label</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
}
|
|
||||||
|
|
||||||
<label class="tables-context-field">
|
|
||||||
<span>Roll jump</span>
|
|
||||||
<input
|
|
||||||
class="input-shell"
|
|
||||||
inputmode="numeric"
|
|
||||||
pattern="[0-9]*"
|
|
||||||
placeholder="e.g. 66"
|
|
||||||
value="@RollJumpValue"
|
|
||||||
@oninput="HandleRollJumpChanged" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (HasActiveFilters())
|
|
||||||
{
|
|
||||||
<div class="tables-context-filter-chips" aria-label="Active table filters">
|
|
||||||
@if (!string.IsNullOrWhiteSpace(SelectedGroupLabel))
|
|
||||||
{
|
|
||||||
<button type="button" class="tables-context-filter-chip" @onclick="() => OnGroupChanged.InvokeAsync(string.Empty)">
|
|
||||||
Variant: @SelectedGroupLabel
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(SelectedColumnLabel))
|
|
||||||
{
|
|
||||||
<button type="button" class="tables-context-filter-chip" @onclick="() => OnColumnChanged.InvokeAsync(string.Empty)">
|
|
||||||
Severity: @SelectedColumnLabel
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(RollJumpValue))
|
|
||||||
{
|
|
||||||
<button type="button" class="tables-context-filter-chip" @onclick="() => OnRollJumpChanged.InvokeAsync(string.Empty)">
|
|
||||||
Roll: @RollJumpValue
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!string.Equals(CurrentMode, TablesReferenceMode.Reference, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
<button type="button" class="tables-context-filter-chip" @onclick="() => OnModeChanged.InvokeAsync(TablesReferenceMode.Reference)">
|
|
||||||
Mode: @GetModeLabel(CurrentMode)
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private readonly IReadOnlyList<SegmentedTabItem> modeTabs =
|
|
||||||
[
|
|
||||||
new(TablesReferenceMode.Reference, "Reference"),
|
|
||||||
new(TablesReferenceMode.NeedsCuration, "Needs Curation"),
|
|
||||||
new(TablesReferenceMode.Curated, "Curated")
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IReadOnlyList<SegmentedTabItem> densityTabs =
|
|
||||||
[
|
|
||||||
new(TablesDensityMode.Comfortable, "Comfortable"),
|
|
||||||
new(TablesDensityMode.Dense, "Dense")
|
|
||||||
];
|
|
||||||
|
|
||||||
[Parameter, EditorRequired]
|
[Parameter, EditorRequired]
|
||||||
public CriticalTableDetail Detail { get; set; } = default!;
|
public CriticalTableDetail Detail { get; set; } = default!;
|
||||||
@@ -128,21 +20,6 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public bool IsPinned { get; set; }
|
public bool IsPinned { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string CurrentMode { get; set; } = TablesReferenceMode.Reference;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string SelectedGroupKey { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string SelectedColumnKey { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string RollJumpValue { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string DensityMode { get; set; } = TablesDensityMode.Comfortable;
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback OnTogglePin { get; set; }
|
public EventCallback OnTogglePin { get; set; }
|
||||||
|
|
||||||
@@ -152,52 +29,4 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback OnToggleLegend { get; set; }
|
public EventCallback OnToggleLegend { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string> OnModeChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string> OnGroupChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string> OnColumnChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string> OnRollJumpChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string> OnDensityChanged { get; set; }
|
|
||||||
|
|
||||||
private string GetReadingHint() =>
|
|
||||||
Detail.Groups.Count > 0
|
|
||||||
? "Find the roll band on the left, then read across to the group and severity you need."
|
|
||||||
: "Find the roll band on the left, then read across to the severity you need.";
|
|
||||||
|
|
||||||
private string? SelectedGroupLabel =>
|
|
||||||
Detail.Groups.FirstOrDefault(group => string.Equals(group.Key, SelectedGroupKey, StringComparison.OrdinalIgnoreCase))?.Label;
|
|
||||||
|
|
||||||
private string? SelectedColumnLabel =>
|
|
||||||
Detail.Columns.FirstOrDefault(column => string.Equals(column.Key, SelectedColumnKey, StringComparison.OrdinalIgnoreCase))?.Label;
|
|
||||||
|
|
||||||
private bool HasActiveFilters() =>
|
|
||||||
!string.IsNullOrWhiteSpace(SelectedGroupKey)
|
|
||||||
|| !string.IsNullOrWhiteSpace(SelectedColumnKey)
|
|
||||||
|| !string.IsNullOrWhiteSpace(RollJumpValue)
|
|
||||||
|| !string.Equals(CurrentMode, TablesReferenceMode.Reference, StringComparison.Ordinal);
|
|
||||||
|
|
||||||
private Task HandleGroupChanged(ChangeEventArgs args) =>
|
|
||||||
OnGroupChanged.InvokeAsync(args.Value?.ToString() ?? string.Empty);
|
|
||||||
|
|
||||||
private Task HandleColumnChanged(ChangeEventArgs args) =>
|
|
||||||
OnColumnChanged.InvokeAsync(args.Value?.ToString() ?? string.Empty);
|
|
||||||
|
|
||||||
private Task HandleRollJumpChanged(ChangeEventArgs args) =>
|
|
||||||
OnRollJumpChanged.InvokeAsync(args.Value?.ToString() ?? string.Empty);
|
|
||||||
|
|
||||||
private static string GetModeLabel(string mode) =>
|
|
||||||
mode switch
|
|
||||||
{
|
|
||||||
TablesReferenceMode.NeedsCuration => "Needs Curation",
|
|
||||||
TablesReferenceMode.Curated => "Curated",
|
|
||||||
_ => "Reference"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<section class="tables-index-rail" aria-labelledby="tables-index-heading">
|
<section class="tables-index-rail" aria-labelledby="tables-index-heading">
|
||||||
<div class="tables-index-rail-header">
|
<div class="tables-index-rail-header">
|
||||||
<h2 id="tables-index-heading" class="tables-index-title">Table Index</h2>
|
<h2 id="tables-index-heading" class="tables-index-title">Table Index</h2>
|
||||||
<p class="tables-index-copy">Choose a table, then read from the roll band across to the result you need.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tables-index-controls" @onkeydown="HandleRailKeyDown">
|
<div class="tables-index-controls" @onkeydown="HandleRailKeyDown">
|
||||||
@@ -12,7 +11,7 @@
|
|||||||
type="search"
|
type="search"
|
||||||
placeholder="Search tables"
|
placeholder="Search tables"
|
||||||
value="@searchText"
|
value="@searchText"
|
||||||
@oninput="HandleSearchInput" />
|
@oninput="HandleSearchInput"/>
|
||||||
|
|
||||||
@if (familyFilters.Count > 1)
|
@if (familyFilters.Count > 1)
|
||||||
{
|
{
|
||||||
@@ -74,7 +73,7 @@
|
|||||||
|
|
||||||
@if (filteredTables.Count == 0)
|
@if (filteredTables.Count == 0)
|
||||||
{
|
{
|
||||||
<p class="tables-index-empty">No tables match the current search.</p>
|
<div class="tables-index-empty">No tables match the current search.</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -130,11 +129,7 @@
|
|||||||
familyFilters.Clear();
|
familyFilters.Clear();
|
||||||
familyFilters.Add(string.Empty);
|
familyFilters.Add(string.Empty);
|
||||||
|
|
||||||
foreach (var family in Tables
|
foreach (var family in Tables.Select(table => table.Family).Where(family => !string.IsNullOrWhiteSpace(family)).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(family => family, StringComparer.OrdinalIgnoreCase))
|
||||||
.Select(table => table.Family)
|
|
||||||
.Where(family => !string.IsNullOrWhiteSpace(family))
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.OrderBy(family => family, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
familyFilters.Add(family);
|
familyFilters.Add(family);
|
||||||
}
|
}
|
||||||
@@ -203,8 +198,7 @@
|
|||||||
|
|
||||||
private bool MatchesFilters(CriticalTableReference table)
|
private bool MatchesFilters(CriticalTableReference table)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(selectedFamily) &&
|
if (!string.IsNullOrEmpty(selectedFamily) && !string.Equals(table.Family, selectedFamily, StringComparison.OrdinalIgnoreCase))
|
||||||
!string.Equals(table.Family, selectedFamily, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -214,9 +208,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return table.Label.Contains(searchText, StringComparison.OrdinalIgnoreCase)
|
return table.Label.Contains(searchText, StringComparison.OrdinalIgnoreCase) || table.Key.Contains(searchText, StringComparison.OrdinalIgnoreCase) || table.Family.Contains(searchText, StringComparison.OrdinalIgnoreCase);
|
||||||
|| table.Key.Contains(searchText, StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| table.Family.Contains(searchText, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleSearchInput(ChangeEventArgs args)
|
private void HandleSearchInput(ChangeEventArgs args)
|
||||||
@@ -237,9 +229,7 @@
|
|||||||
string.Equals(selectedFamily, family, StringComparison.OrdinalIgnoreCase);
|
string.Equals(selectedFamily, family, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private string GetFamilyFilterCssClass(string family) =>
|
private string GetFamilyFilterCssClass(string family) =>
|
||||||
IsFamilyFilterSelected(family)
|
IsFamilyFilterSelected(family) ? "tables-family-filter is-selected" : "tables-family-filter";
|
||||||
? "tables-family-filter is-selected"
|
|
||||||
: "tables-family-filter";
|
|
||||||
|
|
||||||
private void HandleRailKeyDown(KeyboardEventArgs args)
|
private void HandleRailKeyDown(KeyboardEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -280,9 +270,7 @@
|
|||||||
currentIndex = keyboardOptions.FindIndex(item => string.Equals(item.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase));
|
currentIndex = keyboardOptions.FindIndex(item => string.Equals(item.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nextIndex = currentIndex < 0
|
var nextIndex = currentIndex < 0 ? 0 : Math.Clamp(currentIndex + offset, 0, keyboardOptions.Count - 1);
|
||||||
? 0
|
|
||||||
: Math.Clamp(currentIndex + offset, 0, keyboardOptions.Count - 1);
|
|
||||||
|
|
||||||
activeOptionSlug = keyboardOptions[nextIndex].Key;
|
activeOptionSlug = keyboardOptions[nextIndex].Key;
|
||||||
}
|
}
|
||||||
@@ -295,8 +283,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(activeOptionSlug) &&
|
if (!string.IsNullOrWhiteSpace(activeOptionSlug) && keyboardOptions.Any(item => string.Equals(item.Key, activeOptionSlug, StringComparison.OrdinalIgnoreCase)))
|
||||||
keyboardOptions.Any(item => string.Equals(item.Key, activeOptionSlug, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -338,22 +325,23 @@
|
|||||||
private void SetActiveOption(string tableSlug) => activeOptionSlug = tableSlug;
|
private void SetActiveOption(string tableSlug) => activeOptionSlug = tableSlug;
|
||||||
|
|
||||||
private RenderFragment RenderTableOption(CriticalTableReference table) => @<button
|
private RenderFragment RenderTableOption(CriticalTableReference table) => @<button
|
||||||
type="button"
|
type="button"
|
||||||
role="option"
|
role="option"
|
||||||
aria-selected="@string.Equals(table.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)"
|
aria-selected="@string.Equals(table.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)"
|
||||||
class="table-index-option @GetTableOptionCssClass(table)"
|
class="table-index-option @GetTableOptionCssClass(table)"
|
||||||
@onfocus="() => SetActiveOption(table.Key)"
|
@onfocus="() => SetActiveOption(table.Key)"
|
||||||
@onclick="() => OnSelectTable.InvokeAsync(table.Key)">
|
@onclick="() => OnSelectTable.InvokeAsync(table.Key)">
|
||||||
<span class="table-index-option-copy">
|
<span class="table-index-option-copy">
|
||||||
<strong class="table-index-option-title">@table.Label</strong>
|
<strong class="table-index-option-title">@table.Label</strong>
|
||||||
<span class="table-index-option-meta">@table.Family</span>
|
<span class="table-index-option-meta">@table.Family</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="table-index-option-chips">
|
<span class="table-index-option-chips">
|
||||||
@if (GetIsPinned(table.Key))
|
@if (GetIsPinned(table.Key))
|
||||||
{
|
{
|
||||||
<StatusChip Tone="accent">Pinned</StatusChip>
|
<StatusChip Tone="accent">Pinned</StatusChip>
|
||||||
}
|
}
|
||||||
<StatusChip Tone="@GetCurationTone(table)">@($"{table.CurationPercentage}%")</StatusChip>
|
<StatusChip Tone="@GetCurationTone(table)">@($"{table.CurationPercentage}%")</StatusChip>
|
||||||
</span>
|
</span>
|
||||||
</button>;
|
</button>;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
<div class="critical-legend">
|
<div class="critical-legend">
|
||||||
<div class="critical-legend-header">
|
<div class="critical-legend-header">
|
||||||
<h4>Reading help</h4>
|
<h4>Reading help</h4>
|
||||||
<p class="muted">These symbols show the effects attached to a result at a glance.</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="legend-grid">
|
<div class="legend-grid">
|
||||||
@foreach (var entry in LegendEntries)
|
@foreach (var entry in LegendEntries)
|
||||||
@@ -21,6 +20,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public IReadOnlyList<CriticalTableLegendEntry> LegendEntries { get; set; } = Array.Empty<CriticalTableLegendEntry>();
|
public IReadOnlyList<CriticalTableLegendEntry> LegendEntries { get; set; } = Array.Empty<CriticalTableLegendEntry>();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
<header class="tables-page-header">
|
<header class="tables-page-header">
|
||||||
<div class="tables-page-header-copy">
|
<div class="tables-page-header-copy">
|
||||||
<p class="tables-page-eyebrow">Reference</p>
|
|
||||||
<h1 class="panel-title">Critical Tables</h1>
|
<h1 class="panel-title">Critical Tables</h1>
|
||||||
<p class="tables-page-intro">Browse the index, open a table, and read the result directly from the grid without leaving the page.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@if (SelectedCellDetail is not null)
|
||||||
|
{
|
||||||
|
<div class="tables-selection-menu" aria-label="Selected result actions">
|
||||||
|
@if (!SelectedCellDetail.IsCurated)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="OnCurate">Open curation</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-primary" @onclick="OnEdit">Open editor</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public CriticalTableCellDetail? SelectedCellDetail { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback OnEdit { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback OnCurate { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
--button-secondary-bg-hover: rgba(250, 236, 210, 0.95);
|
--button-secondary-bg-hover: rgba(250, 236, 210, 0.95);
|
||||||
--button-secondary-text: #6a4b28;
|
--button-secondary-text: #6a4b28;
|
||||||
--button-secondary-border: rgba(127, 96, 55, 0.18);
|
--button-secondary-border: rgba(127, 96, 55, 0.18);
|
||||||
|
--control-height: 3rem;
|
||||||
--font-display: "Fraunces", Georgia, serif;
|
--font-display: "Fraunces", Georgia, serif;
|
||||||
--font-body: "IBM Plex Sans", "Segoe UI", sans-serif;
|
--font-body: "IBM Plex Sans", "Segoe UI", sans-serif;
|
||||||
--font-ui: "IBM Plex Sans", "Segoe UI", sans-serif;
|
--font-ui: "IBM Plex Sans", "Segoe UI", sans-serif;
|
||||||
@@ -315,11 +316,13 @@ pre,
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.95rem;
|
gap: 0.95rem;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-shell {
|
.field-shell {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.35rem;
|
gap: 0.35rem;
|
||||||
|
align-content: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.roll-input-row {
|
.roll-input-row {
|
||||||
@@ -341,12 +344,19 @@ pre,
|
|||||||
|
|
||||||
.input-shell {
|
.input-shell {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: var(--control-height);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
border: 1px solid var(--button-secondary-border);
|
border: 1px solid var(--button-secondary-border);
|
||||||
background: var(--surface-input);
|
background: var(--surface-input);
|
||||||
padding: 0.8rem 0.9rem;
|
padding: 0.8rem 0.9rem;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.input-shell,
|
||||||
|
select.input-shell {
|
||||||
|
height: var(--control-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-shell:focus {
|
.input-shell:focus {
|
||||||
@@ -425,6 +435,7 @@ pre,
|
|||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: var(--surface-card);
|
background: var(--surface-card);
|
||||||
border: 1px solid rgba(127, 96, 55, 0.14);
|
border: 1px solid rgba(127, 96, 55, 0.14);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-card h3,
|
.result-card h3,
|
||||||
@@ -510,6 +521,9 @@ pre,
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.35rem;
|
gap: 0.35rem;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-cell-status-chip,
|
.critical-cell-status-chip,
|
||||||
@@ -543,6 +557,7 @@ pre,
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.65rem;
|
gap: 0.65rem;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-cell-description {
|
.critical-cell-description {
|
||||||
@@ -550,12 +565,14 @@ pre,
|
|||||||
color: #2c1a10;
|
color: #2c1a10;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-stack {
|
.critical-branch-stack {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-card {
|
.critical-branch-card {
|
||||||
@@ -563,6 +580,7 @@ pre,
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid rgba(127, 96, 55, 0.12);
|
border: 1px solid rgba(127, 96, 55, 0.12);
|
||||||
background: rgba(255, 255, 255, 0.85);
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-header {
|
.critical-branch-header {
|
||||||
@@ -571,6 +589,7 @@ pre,
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-condition {
|
.critical-branch-condition {
|
||||||
@@ -579,6 +598,7 @@ pre,
|
|||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #6b4c29;
|
color: #6b4c29;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-description {
|
.critical-branch-description {
|
||||||
@@ -586,6 +606,7 @@ pre,
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
color: #3b2a21;
|
color: #3b2a21;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-branch-header .affix-badge-list {
|
.critical-branch-header .affix-badge-list {
|
||||||
@@ -645,6 +666,8 @@ pre,
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.affix-badge {
|
.affix-badge {
|
||||||
@@ -1146,7 +1169,7 @@ pre,
|
|||||||
|
|
||||||
.tables-reference-layout {
|
.tables-reference-layout {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(17rem, 20rem) minmax(0, 1fr) minmax(19rem, 24rem);
|
grid-template-columns: minmax(17rem, 20rem) minmax(0, 1fr);
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
@@ -1341,6 +1364,23 @@ pre,
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tables-selection-menu {
|
||||||
|
position: fixed;
|
||||||
|
right: 1rem;
|
||||||
|
bottom: calc(var(--shell-mobile-nav-height, 0rem) + 1rem);
|
||||||
|
z-index: 40;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 18px;
|
||||||
|
background: color-mix(in srgb, var(--surface-card-strong) 96%, transparent);
|
||||||
|
border: 1px solid var(--border-default);
|
||||||
|
box-shadow: var(--shadow-2);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
}
|
||||||
|
|
||||||
.tables-reference-inspector-shell {
|
.tables-reference-inspector-shell {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: calc(var(--shell-header-height) + 1rem);
|
top: calc(var(--shell-header-height) + 1rem);
|
||||||
@@ -1382,6 +1422,9 @@ pre,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-shell {
|
.table-shell {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75rem;
|
||||||
|
min-height: 0;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 1.2rem;
|
padding: 1.2rem;
|
||||||
background: var(--surface-card-strong);
|
background: var(--surface-card-strong);
|
||||||
@@ -1394,15 +1437,14 @@ pre,
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tables-context-bar {
|
.tables-context-bar {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: calc(var(--shell-header-height) + 1rem);
|
top: calc(var(--shell-header-height, 5.75rem) + 1rem);
|
||||||
z-index: 4;
|
z-index: 8;
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 0.75rem;
|
||||||
margin-bottom: 1rem;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 251, 245, 0.96), rgba(255, 251, 245, 0.92));
|
background: linear-gradient(180deg, rgba(255, 251, 245, 0.96), rgba(255, 251, 245, 0.92));
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
border-bottom: 1px solid rgba(127, 96, 55, 0.14);
|
border-bottom: 1px solid rgba(127, 96, 55, 0.14);
|
||||||
@@ -1414,14 +1456,21 @@ pre,
|
|||||||
|
|
||||||
.tables-context-primary,
|
.tables-context-primary,
|
||||||
.tables-context-controls {
|
.tables-context-controls {
|
||||||
display: grid;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
gap: 0.85rem;
|
gap: 0.85rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tables-context-controls {
|
.tables-context-controls {
|
||||||
margin-top: 0.85rem;
|
margin-top: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tables-context-primary .panel-title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.tables-context-tab-row {
|
.tables-context-tab-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -1495,6 +1544,12 @@ pre,
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tables-selection-menu {
|
||||||
|
right: 0.75rem;
|
||||||
|
left: 0.75rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.tables-inspector-sheet {
|
.tables-inspector-sheet {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@@ -1544,19 +1599,30 @@ pre,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-shell .table-scroll {
|
.table-shell .table-scroll {
|
||||||
overflow-x: auto;
|
overflow: auto;
|
||||||
|
min-width: 0;
|
||||||
|
max-height: min(72dvh, calc(100dvh - var(--shell-header-height, 5.75rem) - var(--shell-mobile-nav-height, 0rem) - 5rem));
|
||||||
|
border-radius: 18px;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
scrollbar-gutter: stable both-edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid {
|
.critical-table-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
width: 100%;
|
min-width: 100%;
|
||||||
|
width: max-content;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
border-top: 1px solid rgba(127, 96, 55, 0.2);
|
border-top: 1px solid rgba(127, 96, 55, 0.2);
|
||||||
border-left: 1px solid rgba(127, 96, 55, 0.2);
|
border-left: 1px solid rgba(127, 96, 55, 0.2);
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
|
--tables-header-row-height: 3.2rem;
|
||||||
--tables-group-header-top: 0;
|
--tables-group-header-top: 0;
|
||||||
--tables-column-header-top: 3.2rem;
|
--tables-column-header-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.critical-table-grid.has-groups {
|
||||||
|
--tables-column-header-top: var(--tables-header-row-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid-header-cell {
|
.critical-table-grid-header-cell {
|
||||||
@@ -1564,10 +1630,11 @@ pre,
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
min-height: var(--tables-header-row-height);
|
||||||
padding: 0.35rem;
|
padding: 0.35rem;
|
||||||
border-right: 1px solid rgba(127, 96, 55, 0.2);
|
border-right: 1px solid rgba(127, 96, 55, 0.2);
|
||||||
border-bottom: 1px solid rgba(127, 96, 55, 0.2);
|
border-bottom: 1px solid rgba(127, 96, 55, 0.2);
|
||||||
background: rgba(238, 223, 193, 0.45);
|
background: color-mix(in srgb, var(--surface-card-strong) 94%, var(--accent-1));
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
@@ -1582,18 +1649,18 @@ pre,
|
|||||||
.critical-table-grid-group-header {
|
.critical-table-grid-group-header {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--tables-group-header-top);
|
top: var(--tables-group-header-top);
|
||||||
z-index: 3;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid-column-header {
|
.critical-table-grid-column-header {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--tables-column-header-top);
|
top: var(--tables-column-header-top);
|
||||||
z-index: 3;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid.is-dense {
|
.critical-table-grid.is-dense {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
--tables-column-header-top: 2.6rem;
|
--tables-header-row-height: 2.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid.is-dense .critical-table-grid-header-cell {
|
.critical-table-grid.is-dense .critical-table-grid-header-cell {
|
||||||
@@ -1606,34 +1673,35 @@ pre,
|
|||||||
|
|
||||||
.critical-table-grid-corner,
|
.critical-table-grid-corner,
|
||||||
.critical-table-grid-roll-band-header {
|
.critical-table-grid-roll-band-header {
|
||||||
background: rgba(255, 247, 230, 0.52);
|
background: color-mix(in srgb, var(--surface-card-strong) 94%, var(--accent-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid-corner {
|
.critical-table-grid-corner {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--tables-group-header-top);
|
top: var(--tables-group-header-top);
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 5;
|
z-index: 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid-roll-band-header {
|
.critical-table-grid-roll-band-header {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--tables-column-header-top);
|
top: var(--tables-column-header-top);
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 5;
|
z-index: 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-grid-roll-band {
|
.critical-table-grid-roll-band {
|
||||||
background: rgba(255, 247, 230, 0.52);
|
background: color-mix(in srgb, var(--surface-card-strong) 94%, var(--accent-1));
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 2;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-table-cell {
|
.critical-table-cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
z-index: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 0.55rem;
|
padding: 0.55rem;
|
||||||
border-right: 1px solid rgba(127, 96, 55, 0.2);
|
border-right: 1px solid rgba(127, 96, 55, 0.2);
|
||||||
@@ -2412,10 +2480,6 @@ pre,
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-browser-edit-hint {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tables-context-fields {
|
.tables-context-fields {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user