Add public TabIndex to RadzenUpload on the Choose button

RadzenUpload inherits RadzenComponent, which has no TabIndex parameter,
so a tabindex value fell through the unmatched-attributes splat onto the
root wrapper div instead of the interactive Choose element. That made the
wrapper a dead focus stop and broke keyboard activation of the file
dialog. Add a public TabIndex parameter (mirroring FormComponent) and
apply it to the .rz-fileupload-choose span, which owns the keydown
handler, so tab order and Enter/Space activation work together.
This commit is contained in:
Atanas Korchev
2026-06-23 12:23:08 +03:00
parent 462711f03f
commit 507aa37f87
3 changed files with 48 additions and 1 deletions

View File

@@ -90,6 +90,44 @@ namespace Radzen.Blazor.Tests
Assert.Contains("accept=\"image/*\"", component.Markup);
}
[Fact]
public void Upload_Renders_DefaultTabIndex_OnChooseButton()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>();
Assert.Equal("0", component.Find(".rz-fileupload-choose").GetAttribute("tabindex"));
}
[Fact]
public void Upload_Renders_TabIndex_OnChooseButton_NotWrapper()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.TabIndex, 22);
});
Assert.Equal("22", component.Find(".rz-fileupload-choose").GetAttribute("tabindex"));
Assert.False(component.Find(".rz-fileupload").HasAttribute("tabindex"));
}
[Fact]
public void Upload_Renders_DisabledTabIndex_OnChooseButton()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenUpload>(parameters =>
{
parameters.Add(p => p.TabIndex, 22);
parameters.Add(p => p.Disabled, true);
});
Assert.Equal("-1", component.Find(".rz-fileupload-choose").GetAttribute("tabindex"));
}
}
}

View File

@@ -8,7 +8,7 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class="@ChooseClassList" tabindex="@(Disabled ? -1 : 0)" role="button" aria-label="@ChooseText"
<span class="@ChooseClassList" tabindex="@(Disabled ? -1 : TabIndex)" role="button" aria-label="@ChooseText"
aria-disabled="@(Disabled ? "true" : "false")" aria-controls="@(Name ?? GetId())"
>
@RenderInput()

View File

@@ -202,6 +202,15 @@ namespace Radzen.Blazor
[Parameter]
public bool Disabled { get; set; }
/// <summary>
/// Gets or sets the tab order index for keyboard navigation.
/// Controls the order in which the Choose button receives focus when the user presses the Tab key.
/// Lower values receive focus first. Use -1 to exclude from tab navigation.
/// </summary>
/// <value>The tab index. Default is 0 (natural tab order).</value>
[Parameter]
public int TabIndex { get; set; } = 0;
/// <summary>
/// Gets the choose class list.
/// </summary>