Harden shell and tables interactions
This commit is contained in:
@@ -2,14 +2,17 @@
|
||||
@foreach (var item in Items)
|
||||
{
|
||||
var isSelected = string.Equals(item.Value, SelectedValue, StringComparison.Ordinal);
|
||||
var tabIndex = isSelected || (!HasSelectedValue && string.Equals(item.Value, FirstEnabledValue, StringComparison.Ordinal)) ? 0 : -1;
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="segmented-tabs-button @(isSelected ? "is-selected" : null)"
|
||||
role="tab"
|
||||
aria-selected="@isSelected"
|
||||
tabindex="@tabIndex"
|
||||
disabled="@item.IsDisabled"
|
||||
@onclick="() => SelectAsync(item.Value)">
|
||||
@onclick="() => SelectAsync(item.Value)"
|
||||
@onkeydown="args => HandleKeyDownAsync(args, item.Value)">
|
||||
<span>@item.Label</span>
|
||||
@if (!string.IsNullOrWhiteSpace(item.Badge))
|
||||
{
|
||||
@@ -20,6 +23,7 @@
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
[Parameter]
|
||||
public IReadOnlyList<SegmentedTabItem> Items { get; set; } = [];
|
||||
|
||||
@@ -35,11 +39,47 @@
|
||||
[Parameter]
|
||||
public string? CssClass { get; set; }
|
||||
|
||||
private bool HasSelectedValue =>
|
||||
!string.IsNullOrWhiteSpace(SelectedValue) && Items.Any(item => !item.IsDisabled && string.Equals(item.Value, SelectedValue, StringComparison.Ordinal));
|
||||
|
||||
private string? FirstEnabledValue =>
|
||||
Items.FirstOrDefault(item => !item.IsDisabled)?.Value;
|
||||
|
||||
private string BuildCssClass() =>
|
||||
string.IsNullOrWhiteSpace(CssClass)
|
||||
? "segmented-tabs"
|
||||
: $"segmented-tabs {CssClass}";
|
||||
string.IsNullOrWhiteSpace(CssClass) ? "segmented-tabs" : $"segmented-tabs {CssClass}";
|
||||
|
||||
private Task SelectAsync(string value) =>
|
||||
SelectedValueChanged.InvokeAsync(value);
|
||||
}
|
||||
|
||||
private async Task HandleKeyDownAsync(KeyboardEventArgs args, string currentValue)
|
||||
{
|
||||
var enabledItems = Items.Where(item => !item.IsDisabled).ToList();
|
||||
if (enabledItems.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentIndex = enabledItems.FindIndex(item => string.Equals(item.Value, currentValue, StringComparison.Ordinal));
|
||||
if (currentIndex < 0)
|
||||
{
|
||||
currentIndex = 0;
|
||||
}
|
||||
|
||||
var nextValue = args.Key switch
|
||||
{
|
||||
"ArrowRight" or "ArrowDown" => enabledItems[Math.Min(currentIndex + 1, enabledItems.Count - 1)].Value,
|
||||
"ArrowLeft" or "ArrowUp" => enabledItems[Math.Max(currentIndex - 1, 0)].Value,
|
||||
"Home" => enabledItems[0].Value,
|
||||
"End" => enabledItems[^1].Value,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(nextValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SelectAsync(nextValue);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user