Harden shell and tables interactions

This commit is contained in:
2026-04-12 22:38:18 +02:00
parent 222abc155b
commit 0dd1f42fac
18 changed files with 299 additions and 664 deletions

View File

@@ -1,9 +1,9 @@
<section class="tables-index-rail" aria-labelledby="tables-index-heading">
<section class="tables-index-rail" aria-labelledby="tables-index-heading" tabindex="0" @onkeydown="HandleRailKeyDown">
<div class="tables-index-rail-header">
<h2 id="tables-index-heading" class="tables-index-title">Table Index</h2>
</div>
<div class="tables-index-controls" @onkeydown="HandleRailKeyDown">
<div class="tables-index-controls">
<label class="tables-index-search-label" for="tables-index-search">Search tables</label>
<input
id="tables-index-search"
@@ -11,7 +11,8 @@
type="search"
placeholder="Search tables"
value="@searchText"
@oninput="HandleSearchInput"/>
@oninput="HandleSearchInput"
@onkeydown:stopPropagation="true"/>
@if (familyFilters.Count > 1)
{
@@ -40,7 +41,7 @@
<h3>Pinned</h3>
<span class="tables-index-section-count">@pinnedTables.Count</span>
</div>
<div class="tables-index-list" role="listbox" aria-label="Pinned critical tables">
<div class="tables-index-list" aria-label="Pinned critical tables">
@foreach (var table in pinnedTables)
{
@RenderTableOption(table)
@@ -56,7 +57,7 @@
<h3>Recent</h3>
<span class="tables-index-section-count">@recentTables.Count</span>
</div>
<div class="tables-index-list" role="listbox" aria-label="Recent critical tables">
<div class="tables-index-list" aria-label="Recent critical tables">
@foreach (var table in recentTables)
{
@RenderTableOption(table)
@@ -77,7 +78,7 @@
}
else
{
<div class="tables-index-list" role="listbox" aria-label="Critical tables">
<div class="tables-index-list" aria-label="Critical tables">
@foreach (var table in filteredTables)
{
@RenderTableOption(table)
@@ -250,6 +251,18 @@
return;
}
if (string.Equals(args.Key, "Home", StringComparison.Ordinal))
{
MoveActiveOptionToBoundary(useLast: false);
return;
}
if (string.Equals(args.Key, "End", StringComparison.Ordinal))
{
MoveActiveOptionToBoundary(useLast: true);
return;
}
if (string.Equals(args.Key, "Enter", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(activeOptionSlug))
{
_ = OnSelectTable.InvokeAsync(activeOptionSlug);
@@ -275,6 +288,17 @@
activeOptionSlug = keyboardOptions[nextIndex].Key;
}
private void MoveActiveOptionToBoundary(bool useLast)
{
if (keyboardOptions.Count == 0)
{
activeOptionSlug = null;
return;
}
activeOptionSlug = useLast ? keyboardOptions[^1].Key : keyboardOptions[0].Key;
}
private void EnsureActiveOption()
{
if (keyboardOptions.Count == 0)
@@ -326,8 +350,7 @@
private RenderFragment RenderTableOption(CriticalTableReference table) => @<button
type="button"
role="option"
aria-selected="@string.Equals(table.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)"
aria-current="@(string.Equals(table.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase) ? "true" : null)"
class="table-index-option @GetTableOptionCssClass(table)"
@onfocus="() => SetActiveOption(table.Key)"
@onclick="() => OnSelectTable.InvokeAsync(table.Key)">