Feed tabs say what they are
Below xl every feed tab but the selected one was a lone icon with no name, for a screen reader or a finger. DTab takes an AccessibleName, which DTabs renders as the tab's label and tooltip, and FeedTabs names each tab; on a phone every tab shows its name too. The strip is marked as one that scrolls sideways (data-scroll-x), says it holds the feeds, and on a phone fades at the edge where more tabs wait (edge-fade-x, a scroll-driven animation where the browser has one); the selected tab is brought into view when it changes (window.revealActive). Explore's tabs get the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
1c9773bab0
commit
dd38002682
9 files changed
+97
-6
No files matched your search
@@ -9,6 +9,8 @@
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
[Parameter] public bool Disabled { get; set; }
|
||||
[Parameter] public string Class { get; set; }
|
||||
/// <summary>The tab's name for a screen reader and as its tooltip, when its Header shows only an icon.</summary>
|
||||
[Parameter] public string AccessibleName { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
var index = i;
|
||||
var tab = tabs[i];
|
||||
<button type="button" role="tab" aria-selected="@(index == Active ? "true" : "false")" disabled="@tab.Disabled"
|
||||
aria-label="@tab.AccessibleName" title="@tab.AccessibleName"
|
||||
class="@Cx("tab", index == Active ? "tab-active" : null, tab.Disabled ? "tab-disabled" : null, tab.Class)"
|
||||
@onclick="() => Select(index)">
|
||||
@tab.Header
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
read; the buttons on the right open the composer and, on narrow screens, the globe. *@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<div class="flex-1 min-w-0 overflow-x-auto">
|
||||
<DTabs Active="ActiveIndex" ActiveChanged="Select" Variant="DTabsVariant.Box" Size="DSize.Sm" ContentClass="hidden" class="flex-nowrap w-max">
|
||||
@* a sideways strip on a phone, every tab named, the selected one brought into view and the edges faded where more
|
||||
tabs wait; from md only the selected tab shows its name until xl *@
|
||||
<div @ref="strip" class="flex-1 min-w-0 overflow-x-auto max-md:edge-fade-x" data-scroll-x>
|
||||
<DTabs Active="ActiveIndex" ActiveChanged="Select" Variant="DTabsVariant.Box" Size="DSize.Sm" ContentClass="hidden" class="flex-nowrap w-max"
|
||||
aria-label="@Localizer["Feeds"]">
|
||||
@foreach (var type in Types)
|
||||
{
|
||||
<DTab Class="gap-1 whitespace-nowrap">
|
||||
<DTab Class="gap-1 whitespace-nowrap" AccessibleName="@TabName(type)">
|
||||
<Header>
|
||||
<i class="@type.GetTimelineTypeIcon()" aria-hidden="true"></i>
|
||||
<span class="@(type == Filter.TimelineType ? null : "hidden xl:inline")">@TabName(type)</span>
|
||||
<span class="@(type == Filter.TimelineType ? null : "hidden max-md:inline xl:inline")">@TabName(type)</span>
|
||||
@if (type is TimelineType.Notifications && UnreadNotifications > 0)
|
||||
{
|
||||
<DBadge Size="DSize.Xs" Color="DColor.Primary" title="@Localizer["{0} unread", UnreadNotifications]" data-unread>@UnreadNotifications</DBadge>
|
||||
@@ -127,6 +130,17 @@
|
||||
|
||||
int ActiveIndex => Types.IndexOf(Filter.TimelineType);
|
||||
|
||||
ElementReference strip;
|
||||
int revealed = -1;
|
||||
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (ActiveIndex == revealed)
|
||||
return;
|
||||
revealed = ActiveIndex;
|
||||
CascadingState.Status.RevealActive(strip);
|
||||
}
|
||||
|
||||
ViewGroup SelectedGroup => Groups.FirstOrDefault(g => g.Id == Filter.GroupId);
|
||||
|
||||
[Inject] DiscoveryService DiscoveryService { get; set; }
|
||||
|
||||
Reference in new issue
Block a user