Compare commits

...

7 Commits

Author SHA1 Message Date
yordanov
0c537fa5a8 Update expand/collapse button styles in RadzenDataGrid 2026-02-04 14:46:39 +02:00
Vladimir Enchev
49bfac1d86 tests updated 2026-02-04 14:46:39 +02:00
Vladimir Enchev
dac60a1c6b RadzenFabMenu fixed 2026-02-04 14:46:39 +02:00
Vladimir Enchev
9044596b6d RadzenSwitch fixed 2026-02-04 14:46:39 +02:00
yordanov
8994bd400d Update RadzenRating styles 2026-02-04 14:46:39 +02:00
yordanov
fb9ff6227a Add rz-hidden-accessible styles 2026-02-04 14:46:38 +02:00
Vladimir Enchev
6532cba586 accessibility issues fixes
Various localizable accessibility related properties added

tests updated

side dialog close button id fixed

more accessibility improvements

tests fixed

more accessibility fixes

missing ARIA attributes added
2026-02-04 14:46:38 +02:00
117 changed files with 1300 additions and 375 deletions

View File

@@ -123,7 +123,7 @@ namespace Radzen.Blazor.Tests
});
// Find and click the accordion header link to expand
var header = component.Find(".rz-accordion-header a");
var header = component.Find(".rz-accordion-header button");
header.Click();
Assert.True(expandRaised);
@@ -156,7 +156,7 @@ namespace Radzen.Blazor.Tests
});
// Find and click the accordion header link to collapse
var header = component.Find(".rz-accordion-header a");
var header = component.Find(".rz-accordion-header button");
header.Click();
Assert.True(collapseRaised);
@@ -184,7 +184,7 @@ namespace Radzen.Blazor.Tests
});
// Try to click the disabled item
var header = component.Find(".rz-accordion-header a");
var header = component.Find(".rz-accordion-header button");
header.Click();
// Event should not be raised for disabled item

View File

@@ -155,7 +155,7 @@ namespace Radzen.Blazor.Tests
parameters.Add<bool>(p => p.AllowClear, true);
});
Assert.Contains(@$"<i class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
Assert.Contains(@$"<button type=""button"" class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
}
[Fact]

View File

@@ -152,7 +152,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Collapse, args => { raised = true; });
});
component.Find("a").Click();
component.Find("legend button").Click();
Assert.True(raised);
@@ -160,7 +160,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Expand, args => { raised = true; }));
component.Find("a").Click();
component.Find("legend button").Click();
}
[Fact]

View File

@@ -119,7 +119,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.AllowResetPassword, true);
});
Assert.Contains(@$"Forgot password?</a>", component.Markup);
Assert.Contains(@$"Forgot password?</button>", component.Markup);
}
[Fact]
@@ -134,7 +134,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.ResetPasswordText, "Test");
});
Assert.Contains(@$"Test</a>", component.Markup);
Assert.Contains(@$"Test</button>", component.Markup);
}
[Fact]
@@ -215,7 +215,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
});
component.Find("a").Click();
component.Find("button.rz-link").Click();
Assert.True(clicked);
}
@@ -234,7 +234,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
});
component.Find("a").Click();
component.Find("button.rz-link").Click();
Assert.True(clicked);
}

View File

@@ -127,10 +127,10 @@ namespace Radzen.Blazor.Tests
await component.InvokeAsync(() => component.Instance.GoToPage(0));
component.Render();
var firstPageButton = component.Find("a.rz-pager-first");
var firstPageButton = component.Find("button.rz-pager-first");
Assert.True(firstPageButton.HasAttribute("disabled"));
var prevPageButton = component.Find("a.rz-pager-prev");
var prevPageButton = component.Find("button.rz-pager-prev");
Assert.True(prevPageButton.HasAttribute("disabled"));
}
@@ -150,10 +150,10 @@ namespace Radzen.Blazor.Tests
await component.InvokeAsync(() => component.Instance.GoToPage(9));
component.Render();
var lastPageButton = component.Find("a.rz-pager-last");
var lastPageButton = component.Find("button.rz-pager-last");
Assert.True(lastPageButton.HasAttribute("disabled"));
var nextPageButton = component.Find("a.rz-pager-next");
var nextPageButton = component.Find("button.rz-pager-next");
Assert.True(nextPageButton.HasAttribute("disabled"));
}
}

View File

@@ -167,7 +167,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Collapse, args => { raised = true; });
});
component.Find("a").Click();
component.Find("button.rz-panel-titlebar-toggler").Click();
Assert.True(raised);
@@ -175,7 +175,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Expand, args => { raised = true; }));
component.Find("a").Click();
component.Find("button.rz-panel-titlebar-toggler").Click();
}
[Fact]

View File

@@ -110,7 +110,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
component.Find("div").Click();
component.Find("input[type=\"checkbox\"]").Click();
Assert.True(raised);
Assert.True(object.Equals(value, !(bool)newValue));
@@ -129,7 +129,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
component.Find("div").Click();
component.Find("input[type=\"checkbox\"]").Click();
Assert.True(raised);
Assert.True(object.Equals(value, !(bool)newValue));

View File

@@ -716,6 +716,42 @@ namespace Radzen
}
}
private string? ariaLabel = "Dialog";
/// <summary>
/// Gets or sets the dialog aria-label text when no title is rendered.
/// </summary>
/// <value>The dialog aria-label text.</value>
public string? AriaLabel
{
get => ariaLabel;
set
{
if (ariaLabel != value)
{
ariaLabel = value;
OnPropertyChanged(nameof(AriaLabel));
}
}
}
private string closeAriaLabel = "Close dialog";
/// <summary>
/// Gets or sets the close button aria-label text.
/// </summary>
/// <value>The close button aria-label text.</value>
public string CloseAriaLabel
{
get => closeAriaLabel;
set
{
if (closeAriaLabel != value)
{
closeAriaLabel = value;
OnPropertyChanged(nameof(CloseAriaLabel));
}
}
}
private string? width;
/// <summary>
/// Gets or sets the width of the dialog.

View File

@@ -254,6 +254,13 @@ namespace Radzen
[Parameter]
public string RemoveChipTitle { get; set; } = "Remove";
/// <summary>
/// Gets or sets the clear button aria label text.
/// </summary>
/// <value>The clear button aria label text.</value>
[Parameter]
public string ClearAriaLabel { get; set; } = "Clear";
/// <summary>
/// Gets or sets the search aria label text.
/// </summary>
@@ -558,6 +565,18 @@ namespace Radzen
}
}
/// <summary>
/// Gets the listbox identifier.
/// </summary>
/// <value>The listbox identifier.</value>
protected string ListId
{
get
{
return $"{GetId()}-list";
}
}
/// <summary>
/// Gets the search identifier.
/// </summary>
@@ -635,6 +654,8 @@ namespace Radzen
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
}
isPopupOpen = true;
if (list != null && JSRuntime != null)
{
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", search, list, selectedIndex);
@@ -843,8 +864,15 @@ namespace Radzen
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
isPopupOpen = false;
}
/// <summary>
/// Gets a value indicating whether the popup is open.
/// </summary>
protected bool isPopupOpen;
int itemIndex;
string? previousKey;
@@ -1290,9 +1318,25 @@ namespace Radzen
await Change.InvokeAsync(internalValue);
}
StateHasChanged();
}
/// <summary>
/// Handles keyboard activation for the select-all action.
/// </summary>
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
protected async Task OnSelectAllKeyDown(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)
{
ArgumentNullException.ThrowIfNull(args);
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await SelectAll();
}
}
/// <inheritdoc />
public override object? GetValue()
{

View File

@@ -152,6 +152,12 @@ namespace Radzen
/// <value>The summary content.</value>
public RenderFragment<NotificationService>? SummaryContent { get; set; }
/// <summary>
/// Gets or sets the close button aria-label.
/// </summary>
/// <value>The close button aria-label.</value>
public string CloseAriaLabel { get; set; } = "Close";
#region Implementation of IEquatable<NotificationMessage> and operators overloading

View File

@@ -19,9 +19,11 @@
if (!item.Visible)
continue;
var accordionId = $"{GetId()}-accordiontab-{items.IndexOf(item)}";
<div @ref="@item.Element" id="@item.GetItemId()" @attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style" @onkeydown:stopPropagation>
<a @onclick="@((args) => SelectItem(item))" aria-label="@ItemAriaLabel(i, item)" title="@ItemTitle(i, item)" @onclick:preventDefault="true" role="tab"
id="@($"rz-accordiontab-{items.IndexOf(item)}")" aria-controls="@($"rz-accordiontab-{items.IndexOf(item)}-content")" aria-expanded="true">
<button type="button" @onclick="@((args) => SelectItem(item))" aria-label="@ItemAriaLabel(i, item)" title="@ItemTitle(i, item)" role="tab"
id="@accordionId" aria-controls="@($"{accordionId}-content")" aria-expanded="@(item.GetSelected() ? "true" : "false")"
aria-selected="@(item.GetSelected() ? "true" : "false")" tabindex="@(item.GetSelected() ? "0" : "-1")">
<span class="@ToggleIconClass(item)">keyboard_arrow_down</span>
@if (!string.IsNullOrEmpty(item.Icon))
{
@@ -35,10 +37,10 @@
{
<span>@item.Text</span>
}
</a>
</button>
</div>
<Expander Expanded=@item.GetSelected() role="tabpanel"
id="@($"rz-accordiontab-{items.IndexOf(item)}-content")" aria-labelledby="@($"rz-accordiontab-{items.IndexOf(item)}")">
id="@($"{accordionId}-content")" aria-labelledby="@accordionId">
<div class="rz-accordion-content" @onkeydown:stopPropagation>
@item.ChildContent
</div>

View File

@@ -13,25 +13,27 @@
{
<textarea @ref="@search" @attributes="InputAttributes" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange" onfocus="@(OpenOnFocus ? OpenScript() : null)"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
aria-autocomplete="list" aria-haspopup="listbox" aria-controls="@ListId" aria-expanded="@(IsPopupOpen ? "true" : "false")" autocomplete="off" role="combobox"
class=@InputClass onblur="Radzen.activeElement = null"
id="@Name" aria-expanded="true" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
id="@Name" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
}
else
{
<input @ref="@search" @attributes="InputAttributes" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange" onfocus="@(OpenOnFocus ? OpenScript() : null)"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
aria-autocomplete="list" aria-haspopup="listbox" aria-controls="@ListId" aria-expanded="@(IsPopupOpen ? "true" : "false")" autocomplete="off" role="combobox"
class=@InputClass onblur="Radzen.activeElement = null"
type="@InputType" id="@Name" aria-expanded="true" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
type="@InputType" id="@Name" placeholder="@CurrentPlaceholder" maxlength="@MaxLength" />
}
<div id="@PopupID" class="rz-autocomplete-panel" style="@PopupStyle">
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
<ul id="@ListId" @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
@if (OpenOnFocus || (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText)))
{
@foreach (var item in LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>()))
{
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))" onmousedown="Radzen.activeElement = null">
<li role="option" class="rz-autocomplete-list-item" tabindex="-1"
aria-selected="@(object.Equals(item, SelectedItem) ? "true" : "false")"
@onclick="@(() => OnSelectItem(item))" onmousedown="Radzen.activeElement = null">
<span>
@if (Template != null)
{

View File

@@ -222,6 +222,10 @@ namespace Radzen.Blazor
}
}
private string ListId => $"{PopupID}-list";
private bool IsPopupOpen => OpenOnFocus || (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText));
private async Task OnSelectItem(object item)
{
if (JSRuntime != null)

View File

@@ -7,11 +7,11 @@
<section @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId() tabindex="0">
@if(AllowPaging && (PagerPosition == PagerPosition.Top || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenStack class="rz-carousel-pager rz-carousel-pager-top" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Wrap="FlexWrap.Wrap">
<RadzenStack class="rz-carousel-pager rz-carousel-pager-top" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Wrap="FlexWrap.Wrap" role="list">
@foreach (var item in items)
{
var index = items.IndexOf(item);
<a @onclick="@(args => Navigate(index))" class="rz-carousel-pager-button @(index == selectedIndex ? "rz-state-active" : "")"></a>
<button type="button" role="listitem" @onclick="@(args => Navigate(index))" class="rz-carousel-pager-button @(index == selectedIndex ? "rz-state-active" : "")" aria-label="@string.Format(PagerButtonAriaLabelFormat, index + 1)"></button>
}
</RadzenStack>
}
@@ -30,11 +30,11 @@
</ul>
@if(AllowPaging && (PagerPosition == PagerPosition.Bottom || PagerPosition == PagerPosition.TopAndBottom))
{
<RadzenStack class="rz-carousel-pager rz-carousel-pager-bottom" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Wrap="FlexWrap.Wrap">
<RadzenStack class="rz-carousel-pager rz-carousel-pager-bottom" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Wrap="FlexWrap.Wrap" role="list">
@foreach (var item in items)
{
var index = items.IndexOf(item);
<a @onclick="@(args => Navigate(index))" class="rz-carousel-pager-button @(index == selectedIndex ? "rz-state-active" : "")"></a>
<button type="button" role="listitem" @onclick="@(args => Navigate(index))" class="rz-carousel-pager-button @(index == selectedIndex ? "rz-state-active" : "")" aria-label="@string.Format(PagerButtonAriaLabelFormat, index + 1)"></button>
}
</RadzenStack>
}

View File

@@ -179,6 +179,12 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<int> Change { get; set; }
/// <summary>
/// Gets or sets the pager button aria-label format. Use {0} for the 1-based slide index.
/// </summary>
[Parameter]
public string PagerButtonAriaLabelFormat { get; set; } = "Go to slide {0}";
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{

View File

@@ -5,12 +5,14 @@
@inherits FormComponent<TValue>
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@(Disabled || ReadOnly ? "-1" : $"{TabIndex}")" id="@GetId()">
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault @onclick=@Toggle @onclick:preventDefault style="@Style"
role="checkbox" aria-checked="@CheckBoxAriaChecked" aria-disabled="@(Disabled || ReadOnly ? "true" : "false")"
tabindex="@(Disabled || ReadOnly ? "-1" : $"{TabIndex}")" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" @onchange=@Toggle value=@CheckBoxValue name=@Name id=@Name checked=@CheckBoxChecked aria-checked="@((Value as bool? == true).ToString().ToLowerInvariant())" @attributes="InputAttributes"
tabindex="-1" readonly="@ReadOnly">
</div>
<div class=@BoxClass @onclick=@Toggle @onclick:preventDefault>
<div class=@BoxClass>
<span class=@IconClass></span>
</div>
</div>

View File

@@ -59,6 +59,8 @@ namespace Radzen.Blazor
bool CheckBoxChecked => object.Equals(Value, true);
string CheckBoxAriaChecked => object.Equals(Value, true) ? "true" : Value == null ? "mixed" : "false";
/// <inheritdoc />
protected override string GetComponentCssClass() => GetClassList("rz-chkbox").ToString();

View File

@@ -15,23 +15,27 @@
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
role="checkboxgroup" @onfocus=@OnFocus @onblur=@OnBlur
role="checkboxgroup" aria-disabled="@(Disabled ? "true" : "false")" @onfocus=@OnFocus @onblur=@OnBlur
tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
@if (AllowSelectAll)
{
<div class="rz-multiselect-header rz-helper-clearfix" @onclick:preventDefault>
<RadzenCheckBox ReadOnly="@ReadOnly" Disabled="@Disabled" Name="SelectAll" TValue="bool?" Value="@IsAllSelected()" Change="@SelectAll"
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", SelectAllText ?? "" }})" />
<span @onclick="@(() => SelectAll(!IsAllSelected() ?? true))" class="rz-chkbox-label" style="cursor:pointer">@SelectAllText</span>
<button type="button" @onclick="@(() => SelectAll(!IsAllSelected() ?? true))" class="rz-chkbox-label" disabled="@(Disabled || ReadOnly)">@SelectAllText</button>
</div>
}
<RadzenStack Orientation="@Orientation" JustifyContent="@JustifyContent" AlignItems="@AlignItems" Gap="@Gap" Wrap="@Wrap">
@foreach (var item in allItems.Where(i => i.Visible))
{
<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style" role="checkbox" aria-checked=@(IsSelected(item)? "true" : "false") aria-label="@item.Text">
<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @onkeydown="@(args => OnItemKeyDown(args, item))"
@attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style"
role="checkbox" tabindex="@(Disabled || item.Disabled ? "-1" : "0")"
aria-checked=@(IsSelected(item)? "true" : "false") aria-label="@item.Text"
aria-disabled="@(Disabled || item.Disabled ? "true" : "false")">
<div class="rz-chkbox">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" value="@item.Value" disabled="@Disabled" readonly="@ReadOnly" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" aria-checked="@(IsSelected(item).ToString().ToLowerInvariant())">
<input type="checkbox" name="@Name" value="@item.Value" disabled="@(Disabled || item.Disabled)" readonly="@ReadOnly" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" aria-checked="@(IsSelected(item).ToString().ToLowerInvariant())">
</div>
<div class=@ItemClass(item)>
<span class=@IconClass(item)></span>

View File

@@ -332,6 +332,15 @@ namespace Radzen.Blazor
StateHasChanged();
}
async Task OnItemKeyDown(KeyboardEventArgs args, RadzenCheckBoxListItem<TValue> item)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await SelectItem(item);
}
}
bool focused;
int focusedIndex = -1;
bool preventKeyPress = true;

View File

@@ -5,14 +5,18 @@
@if (Visible)
{
<div @ref=@Element style=@Style @onclick=@Toggle @attributes=@Attributes class=@GetCssClass() id=@GetId() tabindex="@(Disabled ? -1 : TabIndex)" @onkeypress="@(args => OnKeyPress(args, Toggle()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<div @ref=@Element style=@Style @onclick=@Toggle @attributes=@Attributes class=@GetCssClass() id=@GetId()
role="button" aria-haspopup="dialog" aria-expanded="@isPopupOpen.ToString().ToLowerInvariant()" aria-controls="@($"{GetId()}-popup")" aria-disabled="@(Disabled.ToString().ToLowerInvariant())"
tabindex="@(Disabled ? -1 : TabIndex)" @onkeypress="@(args => OnKeyPress(args, Toggle()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
@if (Icon != null)
{
<i class="notranslate rzi" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@Icon</i>
}
<div class="rz-colorpicker-value" style="background-color: @Value" ></div>
<button aria-label="@ToggleAriaLabel" type="button" tabindex="-1" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="notranslate rzi" /></button>
<Popup Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@Popup class="rz-colorpicker-popup" Close=@OnClosePopup Open=@Open>
<Popup id="@($"{GetId()}-popup")" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@Popup
role="dialog" aria-label="@PopupAriaLabel"
class="rz-colorpicker-popup" Close=@OnClosePopup Open=@OnPopupOpen>
@if (ShowHSV)
{
<Draggable class="rz-saturation-picker rz-colorpicker-section" style=@($"background-color: hsl({(HueHandleLeft * 360).ToInvariantString()}, 100%, 50%)") Drag=@OnSaturationMove

View File

@@ -42,6 +42,13 @@ namespace Radzen.Blazor
[Parameter]
public string ToggleAriaLabel { get; set; } = "Toggle";
/// <summary>
/// Gets or sets the popup aria label text.
/// </summary>
/// <value>The popup aria label text.</value>
[Parameter]
public string PopupAriaLabel { get; set; } = "Color picker";
/// <summary>
/// Gets or sets the open callback.
/// </summary>
@@ -113,6 +120,7 @@ namespace Radzen.Blazor
public string ButtonText { get; set; } = "OK";
Popup Popup { get; set; } = default!;
bool isPopupOpen;
internal event EventHandler<string>? SelectedColorChanged;
@@ -381,6 +389,7 @@ namespace Radzen.Blazor
async Task OnClosePopup()
{
isPopupOpen = false;
if (ShowButton)
{
SetInitialValue();
@@ -389,6 +398,12 @@ namespace Radzen.Blazor
await Close.InvokeAsync(null);
}
async Task OnPopupOpen()
{
isPopupOpen = true;
await Open.InvokeAsync(null);
}
/// <summary>
/// Gets or sets a value indicating whether button is shown.
/// </summary>

View File

@@ -1,4 +1,5 @@
@using Radzen.Blazor.Rendering
<div class="rz-colorpicker-item @(isSelected ? "selected" : "")" style="background-color: @Background" @onmousedown:preventDefault @onclick=@OnClick
role="button" aria-label="@Value" aria-disabled="@(ColorPicker?.Disabled == true ? "true" : "false")"
tabindex="@(ColorPicker?.Disabled == true ? -1 : 0)" @onkeypress="@(args => OnKeyPress(args, OnClick()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation></div>

View File

@@ -35,9 +35,9 @@
{
<div class="rz-group-header-item">
<span class="rz-group-header-item-title">@gd.GetTitle()</span>
<a id="@(GetId() + "rg")" aria-label="@RemoveGroupAriaLabel" @onclick:preventDefault="true" @onclick=@(args => RemoveGroupAsync(gd)) role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<button type="button" id="@(GetId() + "rg")" aria-label="@RemoveGroupAriaLabel" @onclick=@(args => RemoveGroupAsync(gd)) class="rz-dialog-titlebar-icon rz-dialog-titlebar-close">
<span class="notranslate rzi rzi-times"></span>
</a>
</button>
</div>
}
</div>
@@ -123,9 +123,12 @@
<span class="rz-column-title">
@if(ShowExpandAll && ExpandMode == DataGridExpandMode.Multiple)
{
<a title=@TitleAttribute() aria-label="@TitleAttribute()" @onclick:preventDefault="true" @onclick="_ => this.ToggleAllRowsExpand()" @onclick:stopPropagation="true">
<span class="@(allRowsExpanded ? "rzi-chevron-circle-down" : "rzi-chevron-circle-right")"></span>
</a>
<button type="button" title=@TitleAttribute() aria-label="@TitleAttribute()"
aria-expanded="@(allRowsExpanded.ToString().ToLowerInvariant())"
class="rz-button rz-button-sm rz-button-icon-only rz-variant-text rz-base rz-shade-default"
@onclick="_ => this.ToggleAllRowsExpand()" @onclick:stopPropagation="true">
<span class="@(allRowsExpanded ? "rzi-chevron-circle-down" : "rzi-chevron-circle-right")"></span>
</button>
}
else
{
@@ -329,7 +332,10 @@
{
if (filterMode == FilterMode.Simple)
{
<button aria-label="@FilterToggleAriaLabel" class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default @(column.HasActiveFilter() ? "rz-grid-filter-active" : "")" onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<button type="button" aria-label="@FilterToggleAriaLabel" aria-controls="@($"{PopupID}{column.GetFilterProperty()}")"
aria-haspopup="dialog" aria-expanded="false"
class="rz-button rz-button-md rz-button-icon-only rz-variant-flat rz-base rz-shade-default @(column.HasActiveFilter() ? "rz-grid-filter-active" : "")"
onclick="@($"Radzen.togglePopup(this.parentNode, '{PopupID}{column.GetFilterProperty()}')")">
<i class="notranslate rzi">date_range</i>
</button>
<span>
@@ -338,16 +344,16 @@
@if (filterValue != null && filters.Any(d => d.Property == column.GetFilterProperty()))
{
<span class="rz-current-filter">@string.Format("{0:" + getFilterDateFormat(column) + "}", filterValue)</span>
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
<button type="button" class="notranslate rzi rz-cell-filter-clear" aria-label="@ClearFilterText" @onclick="@((args) => ClearFilter(column))">close</button>
}
else if ((filterOperator == FilterOperator.IsNull || filterOperator == FilterOperator.IsNotNull) && filters.Any(d => d.Property == column.GetFilterProperty()))
{
<span class="rz-current-filter">@column.GetFilterOperatorText(filterOperator)</span>
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear">close</i>
<button type="button" class="notranslate rzi rz-cell-filter-clear" aria-label="@ClearFilterText" @onclick="@((args) => ClearFilter(column))">close</button>
}
</span>
<div id="@($"{PopupID}{column.GetFilterProperty()}")" class="rz-overlaypanel rz-grid-date-filter"
style="display:none;" tabindex="0">
style="display:none;" tabindex="0" role="dialog" aria-label="@FilterText">
<div class="rz-overlaypanel-content">
<div class="rz-date-filter">
@@ -357,62 +363,82 @@
<ul class="rz-listbox-list">
@if (column.GetFilterOperators().Contains(FilterOperator.Equals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.Equals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))" style="display: block;">
<span>@EqualsText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.Equals)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.Equals))">
<span>@EqualsText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.NotEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))" style="display: block;">
<span>@NotEqualsText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.NotEquals)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.NotEquals))">
<span>@NotEqualsText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.LessThan))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))" style="display: block;">
<span>@LessThanText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.LessThan)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThan))">
<span>@LessThanText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))" style="display: block;">
<span>@LessThanOrEqualsText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.LessThanOrEquals)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.LessThanOrEquals))">
<span>@LessThanOrEqualsText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))" style="display: block;">
<span>@GreaterThanText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThan)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThan))">
<span>@GreaterThanText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))" style="display: block;">
<span>@GreaterThanOrEqualsText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.GreaterThanOrEquals)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.GreaterThanOrEquals))">
<span>@GreaterThanOrEqualsText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsEmpty))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))" style="display: block;">
<span>@IsEmptyText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.IsEmpty)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsEmpty))">
<span>@IsEmptyText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))" style="display: block;">
<span>@IsNotEmptyText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotEmpty)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotEmpty))">
<span>@IsNotEmptyText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNull))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))" style="display: block;">
<span>@IsNullText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.IsNull)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNull))">
<span>@IsNullText</span>
</button>
</li>
}
@if (column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
{
<li class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull))" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))" style="display: block;">
<span>@IsNotNullText</span>
<li role="presentation">
<button type="button" class="@(DateFilterOperatorStyle(column, FilterOperator.IsNotNull)) rz-filter-menu-item" @onclick="@((args) => ApplyDateFilterByFilterOperator(column, FilterOperator.IsNotNull))">
<span>@IsNotNullText</span>
</button>
</li>
}
</ul>
@@ -504,7 +530,7 @@
<input autocomplete="off" aria-label=@(column.Title + FilterValueAriaLabel + column.GetFilterValue()) disabled=@(!column.CanSetFilterValue()) id="@(getFilterInputId(column))" @onchange="@((args) => OnFilter(args, column))" @onkeydown="@((args) => OnFilterKeyPress(args, column))" value="@column.GetFilterValue()" type="text" placeholder="@column.GetFilterPlaceholder()" class="rz-textbox" style="width: 100%;" />
@if (column.GetFilterValue() != null && filters.Any(d => d.Property == column.Property && $"{d.FilterProperty}" == $"{column.FilterProperty}"))
{
<i @onclick="@((args) => ClearFilter(column))" class="notranslate rzi rz-cell-filter-clear" style="position:absolute;inset-inline-end:10px;">close</i>
<button type="button" class="notranslate rzi rz-cell-filter-clear" style="position:absolute;inset-inline-end:10px;" aria-label="@ClearFilterText" @onclick="@((args) => ClearFilter(column))">close</button>
}
}
}
@@ -607,9 +633,12 @@
@if (this.LoadChildData.HasDelegate && this.ShowExpandColumn && this.allColumns.IndexOf(column) == 0)
{
<span class="rz-cell-toggle">
<a id="@(GetId() + "exp")" aria-label="@ExpandChildItemAriaLabel" class="@(getExpandIconCssClass(this, Item))" style="@(getExpandIconStyle(this, Item, rowArgs.Item1.Expandable))" @onclick:preventDefault="true" @onclick="_ => this.ExpandItem(Item)" @onclick:stopPropagation="true">
<span class="@(this.ExpandedItemStyle(Item))"></span>
</a>
<button type="button" id="@(GetId() + "exp")" aria-label="@ExpandChildItemAriaLabel"
class="rz-button rz-button-sm rz-button-icon-only rz-variant-text rz-base rz-shade-default"
style="@(getExpandIconStyle(this, Item, rowArgs.Item1.Expandable))"
@onclick="_ => this.ExpandItem(Item)" @onclick:stopPropagation="true">
<span class="@(getExpandIconCssClass(this, Item)) @(this.ExpandedItemStyle(Item))"></span>
</button>
<span class="@column.GetCellClass()" @attributes="@spanAttributes">
@if (Item != null)
{

View File

@@ -2,7 +2,8 @@
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime
<button title=@Column.GetFilterOperatorText(Column.GetFilterOperator()) class="@FilterIconStyle()" onclick="@($"Radzen.togglePopup(this.parentNode, '{filterId}')")">
<button title=@Column.GetFilterOperatorText(Column.GetFilterOperator()) class="@FilterIconStyle()" onclick="@($"Radzen.togglePopup(this.parentNode, '{filterId}')")"
aria-haspopup="menu" aria-controls="@filterId" aria-expanded="false">
<i class="notranslate rzi">@Grid.FilterIcon</i>
@if (Column.GetFilterOperator() == FilterOperator.DoesNotContain)
{
@@ -14,110 +15,144 @@
}
</button>
<div id="@($"{filterId}")" class="rz-overlaypanel"
style="display:none;" tabindex="0">
style="display:none;" tabindex="0" role="menu" aria-label="@Grid.FilterText">
<div class="rz-overlaypanel-content">
<ul class="rz-listbox-list">
@if (Column.FilterPropertyType != null && (QueryableExtension.IsEnumerable(Column.FilterPropertyType) || Column.FilterPropertyType == typeof(string)))
{
@if (Column.GetFilterOperators().Contains(FilterOperator.Contains))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.Contains))" @onclick="@(args => ApplyFilter(FilterOperator.Contains))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Contains)</span><span>@Grid.ContainsText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.Contains)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.Contains))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Contains)</span><span>@Grid.ContainsText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.DoesNotContain))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.DoesNotContain))" @onclick="@(args => ApplyFilter(FilterOperator.DoesNotContain))" style="display: block;">
<span class="rz-filter-menu-symbol"><s>@Column.GetFilterOperatorSymbol(FilterOperator.DoesNotContain)</s></span><span>@Grid.DoesNotContainText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.DoesNotContain)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.DoesNotContain))">
<span class="rz-filter-menu-symbol"><s>@Column.GetFilterOperatorSymbol(FilterOperator.DoesNotContain)</s></span><span>@Grid.DoesNotContainText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.In))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.In))" @onclick="@(args => ApplyFilter(FilterOperator.In))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.In)</span><span>@Grid.InText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.In)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.In))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.In)</span><span>@Grid.InText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.NotIn))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.NotIn))" @onclick="@(args => ApplyFilter(FilterOperator.NotIn))" style="display: block;">
<span class="rz-filter-menu-symbol"><s>@Column.GetFilterOperatorSymbol(FilterOperator.NotIn)</s></span><span>@Grid.NotInText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.NotIn)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.NotIn))">
<span class="rz-filter-menu-symbol"><s>@Column.GetFilterOperatorSymbol(FilterOperator.NotIn)</s></span><span>@Grid.NotInText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.StartsWith) && Column.FilterPropertyType == typeof(string))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.StartsWith))" @onclick="@(args => ApplyFilter(FilterOperator.StartsWith))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.StartsWith)</span><span>@Grid.StartsWithText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.StartsWith)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.StartsWith))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.StartsWith)</span><span>@Grid.StartsWithText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.EndsWith) && Column.FilterPropertyType == typeof(string))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.EndsWith))" @onclick="@(args => ApplyFilter(FilterOperator.EndsWith))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.EndsWith)</span><span>@Grid.EndsWithText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.EndsWith)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.EndsWith))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.EndsWith)</span><span>@Grid.EndsWithText</span>
</button>
</li>
}
}
@if (Column.GetFilterOperators().Contains(FilterOperator.Equals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.Equals))" @onclick="@(args => ApplyFilter(FilterOperator.Equals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Equals)</span><span>@Grid.EqualsText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.Equals)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.Equals))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.Equals)</span><span>@Grid.EqualsText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.NotEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.NotEquals))" @onclick="@(args => ApplyFilter(FilterOperator.NotEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.NotEquals)</span><span>@Grid.NotEqualsText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.NotEquals)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.NotEquals))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.NotEquals)</span><span>@Grid.NotEqualsText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.LessThan))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.LessThan))" @onclick="@(args => ApplyFilter(FilterOperator.LessThan))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThan)</span><span>@Grid.LessThanText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.LessThan)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.LessThan))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThan)</span><span>@Grid.LessThanText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.LessThanOrEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.LessThanOrEquals))" @onclick="@(args => ApplyFilter(FilterOperator.LessThanOrEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThanOrEquals)</span><span>@Grid.LessThanOrEqualsText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.LessThanOrEquals)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.LessThanOrEquals))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.LessThanOrEquals)</span><span>@Grid.LessThanOrEqualsText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.GreaterThan))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThan))" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThan))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThan)</span><span>@Grid.GreaterThanText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThan)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThan))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThan)</span><span>@Grid.GreaterThanText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.GreaterThanOrEquals))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThanOrEquals))" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThanOrEquals))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThanOrEquals)</span><span>@Grid.GreaterThanOrEqualsText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.GreaterThanOrEquals)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.GreaterThanOrEquals))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.GreaterThanOrEquals)</span><span>@Grid.GreaterThanOrEqualsText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNull))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNull))" @onclick="@(args => ApplyFilter(FilterOperator.IsNull))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNull)</span><span>@Grid.IsNullText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.IsNull)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.IsNull))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNull)</span><span>@Grid.IsNullText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNotNull))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNotNull))" @onclick="@(args => ApplyFilter(FilterOperator.IsNotNull))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotNull)</span><span>@Grid.IsNotNullText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.IsNotNull)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.IsNotNull))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotNull)</span><span>@Grid.IsNotNullText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsEmpty) && Column.FilterPropertyType == typeof(string))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsEmpty)</span><span>@Grid.IsEmptyText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.IsEmpty)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.IsEmpty))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsEmpty)</span><span>@Grid.IsEmptyText</span>
</button>
</li>
}
@if (Column.GetFilterOperators().Contains(FilterOperator.IsNotEmpty) && Column.FilterPropertyType == typeof(string))
{
<li class="@(FilterOperatorStyle(Column, FilterOperator.IsNotEmpty))" @onclick="@(args => ApplyFilter(FilterOperator.IsNotEmpty))" style="display: block;">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotEmpty)</span><span>@Grid.IsNotEmptyText</span>
<li role="presentation">
<button type="button" class="@(FilterOperatorStyle(Column, FilterOperator.IsNotEmpty)) rz-filter-menu-item" @onclick="@(args => ApplyFilter(FilterOperator.IsNotEmpty))">
<span class="rz-filter-menu-symbol">@Column.GetFilterOperatorSymbol(FilterOperator.IsNotEmpty)</span><span>@Grid.IsNotEmptyText</span>
</button>
</li>
}
<li class="rz-multiselect-item" @onclick="@(args => ClearFilter())" style="display:block;">
<span class="rz-filter-menu-symbol">x</span><span>@Grid.ClearFilterText</span>
<li role="presentation">
<button type="button" class="rz-multiselect-item rz-filter-menu-item" @onclick="@(args => ClearFilter())">
<span class="rz-filter-menu-symbol">x</span><span>@Grid.ClearFilterText</span>
</button>
</li>
</ul>
</div>

View File

@@ -28,9 +28,12 @@
<span class="rz-column-title"></span>
@if (rowArgs?.Item1.Expandable == true)
{
<a id="@(Grid.GridId() + Group.GetHashCode())" aria-label=@Grid.ExpandGroupAriaLabel @onclick:preventDefault="true" @onclick="@(_ => Grid.ExpandGroupItem(this, rowArgs?.Item1.Expanded))">
<span class="@(Grid.ExpandedGroupItemStyle(this, Grid.allGroupsExpanded != null ? Grid.allGroupsExpanded : rowArgs?.Item1.Expanded))"></span>
</a>
<button type="button" id="@(Grid.GridId() + Group.GetHashCode())" aria-label=@Grid.ExpandGroupAriaLabel
aria-expanded="@(Grid.IsGroupItemExpanded(this).ToString().ToLowerInvariant())"
class="rz-button rz-button-sm rz-button-icon-only rz-variant-text rz-base rz-shade-default"
@onclick="@(_ => Grid.ExpandGroupItem(this, rowArgs?.Item1.Expanded))">
<span class="@(Grid.ExpandedGroupItemStyle(this, Grid.allGroupsExpanded != null ? Grid.allGroupsExpanded : rowArgs?.Item1.Expanded))"></span>
</button>
}
</td>
}

View File

@@ -7,8 +7,11 @@
@if (RowIndex == Column.GetLevel())
{
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))>
<div @onclick='@((args) => Grid.OnSort(args, Column))' @onkeydown="OnSortKeyPressed">
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass"
scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))
aria-sort="@(Grid.AllowSorting && Column.Sortable ? (Column.GetSortOrder() == SortOrder.Ascending ? "ascending" : Column.GetSortOrder() == SortOrder.Descending ? "descending" : "none") : null)">
<div @onclick='@((args) => Grid.OnSort(args, Column))' @onkeydown="OnSortKeyPressed"
role="@(Grid.AllowSorting && Column.Sortable ? "button" : null)">
@if ((Grid.AllowColumnReorder && Column.Reorderable || Grid.AllowGrouping && Column.Groupable))
{
<span id="@(Grid.getColumnUniqueId(ColumnIndex) + "-drag")" class="rz-column-drag"
@@ -60,12 +63,15 @@
@{var filterMode = Column.FilterMode ?? Grid.FilterMode;}
@if (Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Advanced || filterMode == FilterMode.CheckBoxList))
{
<i @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true">
<button type="button" @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true"
aria-haspopup="dialog" aria-controls="@Column.GetColumnPopupID()" aria-expanded="false"
aria-label="@Grid.FilterToggleAriaLabel">
@Grid.FilterIcon
</i>
</button>
<Popup Lazy=@(Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand) @ref=popup id="@($"{Column.GetColumnPopupID()}")" class="rz-overlaypanel"
role="dialog" aria-label="@Grid.FilterText"
style="display:none;min-width:250px;" @onkeydown="OnFilterPopupKeyPressed">
<div class="rz-overlaypanel-content">
@if (Column.FilterTemplate != null)

View File

@@ -27,9 +27,12 @@
<span class="rz-column-title"></span>
@if (rowArgs?.Item1.Expandable == true && !(Grid?.LoadChildData.HasDelegate ?? false))
{
<a id="@((Grid?.GridId() ?? "") + Item.GetHashCode())" aria-label="@(Grid?.ExpandChildItemAriaLabel ?? "")" @onclick:preventDefault="true" @onclick="@(_ => Grid?.ExpandItem(Item)!)" @onclick:stopPropagation>
<button type="button" id="@((Grid?.GridId() ?? "") + Item.GetHashCode())" aria-label="@(Grid?.ExpandChildItemAriaLabel ?? "")"
aria-expanded="@(Grid != null && Grid.IsRowExpanded(Item) ? "true" : "false")"
class="rz-button rz-button-sm rz-button-icon-only rz-variant-text rz-base rz-shade-default"
@onclick="@(_ => Grid?.ExpandItem(Item)!)" @onclick:stopPropagation>
<span class="@(Grid?.ExpandedItemStyle(Item) ?? "")"></span>
</a>
</button>
}
</td>
}

View File

@@ -17,27 +17,30 @@
}
@if (ShowButton)
{
<button aria-label="@ToggleAriaLabel" @onmousedown=@OnToggle class="@($"rz-datepicker-trigger{(ShowInput ? " rz-datepicker-field-button" : "")} rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")} {ButtonClass}")" tabindex="-1" type="button">
<button aria-label="@ToggleAriaLabel" aria-haspopup="dialog" aria-controls="@PopupID" aria-expanded="false"
@onmousedown=@OnToggle class="@($"rz-datepicker-trigger{(ShowInput ? " rz-datepicker-field-button" : "")} rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")} {ButtonClass}")" tabindex="-1" type="button">
<span aria-hidden="true" class="@ButtonClasses"></span><span class="rz-button-text"></span>
</button>
}
@if (AllowClear && HasValue && (ShowInput || !ShowButton))
{
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
<button type="button" class="notranslate rz-dropdown-clear-icon rzi rzi-times" aria-label="@ClearAriaLabel" @onclick="@Clear" @onclick:stopPropagation="true"></button>
}
}
<Popup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle class="@($"{(Inline ? "rz-datepicker-inline-container " : "rz-datepicker-popup-container ")}")">
<Popup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle
role="dialog" aria-label="@PopupAriaLabel"
class="@($"{(Inline ? "rz-datepicker-inline-container " : "rz-datepicker-popup-container ")}")">
<div class="rz-calendar" @onkeydown="@OnPopupKeyDown">
@if (!TimeOnly)
{
<div class="rz-calendar-header">
<a id="@(GetId() + "pm")" tabindex="-1" aria-label="@PrevMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })">
<button id="@(GetId() + "pm")" type="button" tabindex="-1" aria-label="@PrevMonthAriaLabel" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(-1).Year >= YearFrom) {CurrentDate = CurrentDate.AddMonths(-1);}} catch (ArgumentOutOfRangeException) {}} })" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
<span class="notranslate rzi rz-calendar-prev-icon"></span>
</a>
<a id="@(GetId() + "nm")" tabindex="-1" aria-label="@NextMonthAriaLabel" @onclick:preventDefault="true" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })">
</button>
<button id="@(GetId() + "nm")" type="button" tabindex="-1" aria-label="@NextMonthAriaLabel" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(() => { if (!Disabled) { try { if(CurrentDate.AddMonths(1).Year <= YearTo) {CurrentDate = CurrentDate.AddMonths(1);}} catch (ArgumentOutOfRangeException) {} } })" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
<span class="notranslate rzi rz-calendar-next-icon"></span>
</a>
</button>
<div class="rz-calendar-title">
<RadzenDropDown @ref="monthDropDown" class="rz-calendar-month-dropdown" TabIndex="@TabIndex"
TValue="int" Value="@CurrentDate.Month" Disabled="@Disabled" Data="@months" TextProperty="Name" ValueProperty="Value"
@@ -88,8 +91,10 @@
DateTime date = StartDate.AddDays(dayNumber++);
var dateArgs = DateAttributes(date);
<td @attributes="@(dateArgs.Attributes)" class="@GetDayCssClass(date, dateArgs)"
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })">
<td @attributes="@(dateArgs.Attributes)" class="@GetDayCssClass(date, dateArgs)"
role="button" tabindex="@(Disabled || dateArgs.Disabled ? "-1" : "0")"
@onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })"
@onkeydown="@(args => OnDayKeyDown(args, date, dateArgs))">
<span class=@GetDayCssClass(date, dateArgs, false)>@date.Day</span>
</td>
}
@@ -112,7 +117,7 @@
<div class="rz-timepicker" @onmousedown:stopPropagation>
@if (ShowHour)
{
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "hour" }})" TValue="int" Disabled="@Disabled" Value="@(HourFormat == "12" ? ((CurrentDate.Hour + 11) % 12) + 1 : CurrentDate.Hour)"
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", HourAriaLabel }})" TValue="int" Disabled="@Disabled" Value="@(HourFormat == "12" ? ((CurrentDate.Hour + 11) % 12) + 1 : CurrentDate.Hour)"
Min="@(HourFormat == "12" ? 1 : -1)" Max="@(HourFormat == "12" ? 12 : 24)" Step="@HoursStep"
Change="@UpdateHour" class="rz-hour-picker" @oninput=@OnUpdateHourInput Format="@(PadHours ? "00" : "")" Name="@($"{UniqueID}-h")" />
}
@@ -121,7 +126,7 @@
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "minutes" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" Step="@MinutesStep" Min="0" Max="59"
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", MinutesAriaLabel }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" Step="@MinutesStep" Min="0" Max="59"
Change="@UpdateMinutes" class="rz-minute-picker" @oninput=@OnUpdateHourMinutes Format="@(PadMinutes ? "00" : "")" Name="@($"{UniqueID}-m")"/>
}
@if (ShowSeconds)
@@ -129,19 +134,19 @@
<div class="rz-separator">
<span>:</span>
</div>
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "seconds" }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" Step="@SecondsStep" Min="0" Max="59"
<RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", SecondsAriaLabel }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" Step="@SecondsStep" Min="0" Max="59"
Change="@UpdateSeconds" class="rz-second-picker" @oninput=@OnUpdateHourSeconds Format="@(PadSeconds ? "00" : "")" Name="@($"{UniqueID}-s")"/>
}
@if (HourFormat == "12")
{
<div class="rz-ampm-picker">
<a id="@(GetId() + "ampmup")" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
<button id="@(GetId() + "ampmup")" type="button" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick="@ToggleAmPm" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
<span class="notranslate rzi rzi-chevron-up"></span>
</a>
</button>
<span>@CurrentDate.ToString("tt")</span>
<a id="@(GetId() + "ampmdown")" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick:preventDefault="true" @onclick="@ToggleAmPm">
<button id="@(GetId() + "ampmdown")" type="button" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick="@ToggleAmPm" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
<span class="notranslate rzi rzi-chevron-down"></span>
</a>
</button>
</div>
}
@if (ShowTimeOkButton)

View File

@@ -70,6 +70,41 @@ namespace Radzen.Blazor
[Parameter]
public string ToggleAriaLabel { get; set; } = "Toggle";
/// <summary>
/// Gets or sets the popup aria label text.
/// </summary>
/// <value>The popup aria label text.</value>
[Parameter]
public string PopupAriaLabel { get; set; } = "Date picker";
/// <summary>
/// Gets or sets the clear button aria label text.
/// </summary>
/// <value>The clear button aria label text.</value>
[Parameter]
public string ClearAriaLabel { get; set; } = "Clear";
/// <summary>
/// Gets or sets the hour input aria label text.
/// </summary>
/// <value>The hour input aria label text.</value>
[Parameter]
public string HourAriaLabel { get; set; } = "Hour";
/// <summary>
/// Gets or sets the minutes input aria label text.
/// </summary>
/// <value>The minutes input aria label text.</value>
[Parameter]
public string MinutesAriaLabel { get; set; } = "Minutes";
/// <summary>
/// Gets or sets the seconds input aria label text.
/// </summary>
/// <value>The seconds input aria label text.</value>
[Parameter]
public string SecondsAriaLabel { get; set; } = "Seconds";
/// <summary>
/// Gets or sets the OK button aria label text.
/// </summary>
@@ -453,6 +488,15 @@ namespace Radzen.Blazor
return args;
}
async Task OnDayKeyDown(KeyboardEventArgs args, DateTime date, DateRenderEventArgs dateArgs)
{
var key = args.Code != null ? args.Code : args.Key;
if ((key == "Enter" || key == "Space") && !Disabled && !dateArgs.Disabled)
{
await SetDay(date);
}
}
/// <summary>
/// Gets or sets the kind of DateTime bind to control
/// </summary>

View File

@@ -3,6 +3,26 @@
@using Radzen.Blazor.Rendering
@inject IJSRuntime JSRuntime
@{
var sideOptions = sideDialogOptions;
var sideDialogId = $"rz-dialog-side-{sideOptions?.GetHashCode()}";
var sideDialogLabelId = $"{sideDialogId}-label";
var sideShowTitle = sideOptions?.ShowTitle == true;
var sideAriaAttributes = new Dictionary<string, object?>();
if (sideShowTitle)
{
sideAriaAttributes["aria-labelledby"] = sideDialogLabelId;
}
else
{
sideAriaAttributes["aria-label"] = sideOptions?.AriaLabel ?? sideDialog?.Title ?? sideOptions?.Title;
}
if (sideOptions?.ShowMask == true)
{
sideAriaAttributes["aria-modal"] = "true";
}
}
@foreach (var dialog in dialogs)
{
<DialogContainer @key=@dialog Dialog=@dialog ShowMask=@(dialog==dialogs.LastOrDefault()) />
@@ -12,57 +32,58 @@
{
<aside
class="@GetSideDialogCssClass()"
role="dialog"
@ref="sideDialogElement"
tabindex="0"
style="@GetSideDialogStyle()"
aria-labelledby="rz-dialog-side-label">
@if (sideDialogOptions?.Resizable == true)
@attributes="sideAriaAttributes">
@if (sideOptions?.Resizable == true)
{
<div @ref="resizeBarElement"
class="@GetResizeBarCssClass()"
title="@sideDialogOptions?.ResizeBarTitle" aria-label="@sideDialogOptions?.ResizeBarAriaLabel">
title="@sideOptions?.ResizeBarTitle" aria-label="@sideOptions?.ResizeBarAriaLabel">
<span class="rz-resize" aria-hidden="true"></span>
</div>
}
@if (sideDialogOptions?.ShowTitle == true)
@if (sideShowTitle)
{
<div class="rz-dialog-side-titlebar">
<div class="rz-dialog-side-title" style="display: inline" id="rz-dialog-side-label">
@if (sideDialogOptions.TitleContent != null)
<div class="rz-dialog-side-title" style="display: inline" id="@sideDialogLabelId">
@if (sideOptions?.TitleContent != null)
{
@sideDialogOptions.TitleContent(Service!)
@sideOptions.TitleContent(Service!)
}
else if (!string.IsNullOrEmpty(sideDialog?.Title))
{
@sideDialog.Title
}
else
else if (!string.IsNullOrEmpty(sideOptions?.Title))
{
@sideDialogOptions.Title
@sideOptions.Title
}
</div>
@if (sideDialogOptions.ShowClose)
@if (sideOptions?.ShowClose == true)
{
<a id="@(sideDialogOptions.GetHashCode() + "cl")" aria-label="@CloseSideDialogAriaLabel" @onclick:preventDefault="true" class="rz-dialog-side-titlebar-close" @onclick="@(_ => Service!.CloseSide())" role="button" tabindex="@sideDialogOptions.CloseTabIndex">
<button id="@($"rz-dialog-side-{sideOptions?.GetHashCode() ?? 0}-cl")" type="button" aria-label="@CloseSideDialogAriaLabel" class="rz-dialog-side-titlebar-close" @onclick="@(_ => Service!.CloseSide())" tabindex="@(sideOptions?.CloseTabIndex ?? 0)">
<span class="notranslate rzi rzi-times"></span>
</a>
</button>
}
</div>
}
<div class="@SideDialogContentCssClass" style="@sideDialogOptions?.Style">
<div class="@SideDialogContentCssClass" style="@sideOptions?.Style">
@sideDialogContent
</div>
</aside>
@if (dialogs.Count == 0 && sideDialogOptions?.ShowMask == true)
@if (dialogs.Count == 0 && sideOptions?.ShowMask == true)
{
@if (sideDialogOptions.CloseDialogOnOverlayClick)
@if (sideOptions.CloseDialogOnOverlayClick)
{
<div @onclick="@Service!.CloseSide" class="rz-dialog-mask"></div>
<div @onclick="@Service!.CloseSide" class="rz-dialog-mask" aria-hidden="true" tabindex="-1"></div>
}
else
{
<div class="rz-dialog-mask"></div>
<div class="rz-dialog-mask" aria-hidden="true" tabindex="-1"></div>
}
}
}
@@ -175,7 +196,9 @@
WrapperCssClass = options.WrapperCssClass,
ContentCssClass = options.ContentCssClass,
CloseTabIndex = options.CloseTabIndex,
TitleContent = options.TitleContent
TitleContent = options.TitleContent,
AriaLabel = options.AriaLabel,
CloseAriaLabel = options.CloseAriaLabel
};
// Create a Dialog object for the side dialog to support cascading parameter

View File

@@ -8,7 +8,9 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" onmousedown="Radzen.activeElement = null" @onclick="@(args => OpenPopup("ArrowDown", false, true))" @onclick:preventDefault @onclick:stopPropagation style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" onmousedown="Radzen.activeElement = null"
role="combobox" aria-haspopup="listbox" aria-expanded="@isPopupOpen.ToString().ToLowerInvariant()" aria-controls="@ListId" aria-disabled="@(Disabled.ToString().ToLowerInvariant())"
@onclick="@(args => OpenPopup("ArrowDown", false, true))" @onclick:preventDefault @onclick:stopPropagation style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
@onkeydown="@((args) => OnKeyPress(args))" @onkeydown:preventDefault="@preventKeydown" id="@GetId()" @onfocus=@this.AsNonRenderingEventHandler(OnFocus)>
<div class="rz-helper-hidden-accessible">
<input disabled="@Disabled" aria-haspopup="listbox" readonly="" type="text" tabindex="-1"
@@ -54,7 +56,13 @@
@GetItemOrValueFromProperty(item, TextProperty ?? string.Empty)
}
</span>
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty ?? ""))" type=button class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
<button tabindex="0"
title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty ?? ""))"
aria-label="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item, TextProperty ?? ""))"
type=button class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")"
@onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)">
<RadzenIcon Icon="close" />
</button>
</div>
}
</div>
@@ -133,9 +141,13 @@
<div class="rz-multiselect-header rz-helper-clearfix" @onclick:preventDefault>
@if(AllowSelectAll && Data != null && Data.Cast<object>().Any())
{
<div class="rz-chkbox" title="@(!AllowFiltering ? "" : SelectAllText)" @onclick="@SelectAll">
<div class="rz-chkbox" title="@(!AllowFiltering ? "" : SelectAllText)" @onclick="@SelectAll"
role="checkbox" tabindex="@(Disabled || ReadOnly ? "-1" : "0")"
aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())"
aria-disabled="@(Disabled || ReadOnly ? "true" : "false")"
@onkeydown="OnSelectAllKeyDown">
<div class="rz-helper-hidden-accessible">
<input readonly="readonly" type="checkbox" id="@($"{(Name ?? UniqueID + "sa")}")" aria-label="@SearchAriaLabel" aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())">
<input readonly="readonly" type="checkbox" id="@($"{(Name ?? UniqueID + "sa")}")" aria-label="@SelectAllText" aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())">
</div>
<div class="@(IsAllSelected() ? "notranslate rz-chkbox-box rz-state-active" : "notranslate rz-chkbox-box")">
<span class="@(IsAllSelected() ? "notranslate rz-chkbox-icon rzi rzi-check" : "notranslate rz-chkbox-icon")"></span>
@@ -144,7 +156,7 @@
}
@if (AllowSelectAll && !AllowFiltering && !string.IsNullOrEmpty(SelectAllText) && Data != null && Data.Cast<object>().Any())
{
<span style="cursor:pointer" @onclick="@SelectAll">@SelectAllText</span>
<button type="button" class="rz-multiselect-selectall" disabled="@(Disabled || ReadOnly)" @onclick="@SelectAll">@SelectAllText</button>
}
@if (AllowFiltering)
{
@@ -156,16 +168,18 @@
<span class="notranslate rz-multiselect-filter-icon rzi rzi-search"></span>
</div>
}
<a id="@(GetId() + "clear")" class="rz-multiselect-close " @onclick="@ClearAll" @onclick:stopPropagation="true">
<button type="button" id="@(GetId() + "clear")" class="rz-multiselect-close" aria-label="@ClearAriaLabel"
@onclick="@ClearAll" @onclick:stopPropagation="true">
<span class="notranslate rzi rzi-times"></span>
</a>
</button>
</div>
}
}
<div class="@(Multiple ? "rz-multiselect-items-wrapper" : "rz-dropdown-items-wrapper")" style="@PopupStyle">
@if (Data != null && Data.Cast<object>().Any())
{
<ul @ref="list" class="@(Multiple ? "rz-multiselect-items rz-multiselect-list" : "rz-dropdown-items rz-dropdown-list")" role="listbox">
<ul id="@ListId" @ref="list" class="@(Multiple ? "rz-multiselect-items rz-multiselect-list" : "rz-dropdown-items rz-dropdown-list")"
role="listbox" aria-multiselectable="@(Multiple ? "true" : "false")">
@if (View != null)
{
@RenderItems()
@@ -184,7 +198,8 @@
</div>
@if (AllowClear && (!Multiple && HasValue || Multiple && selectedItems.Count > 0))
{
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@ClearAll" @onclick:stopPropagation="true"></i>
<button type="button" class="notranslate rz-dropdown-clear-icon rzi rzi-times" aria-label="@ClearAriaLabel"
@onclick="@ClearAll" @onclick:stopPropagation="true"></button>
}
</div>
}

View File

@@ -9,6 +9,7 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onfocus=@this.AsNonRenderingEventHandler(OnFocus)
role="combobox" aria-haspopup="listbox" aria-expanded="@isPopupOpen.ToString().ToLowerInvariant()" aria-controls="@PopupID" aria-disabled="@(Disabled.ToString().ToLowerInvariant())"
style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()" @onclick="@(args => OpenPopup("ArrowDown", false, true))" @onclick:preventDefault @onclick:stopPropagation
@onkeydown="@((args) => OnKeyPress(args))" @onkeydown:preventDefault="@preventKeydown">
<div class="rz-helper-hidden-accessible">
@@ -58,7 +59,13 @@
@GetItemOrValueFromProperty(item!, TextProperty ?? string.Empty)
}
</span>
<button tabindex="0" title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item!, TextProperty ?? string.Empty))" type="button" class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
<button tabindex="0"
title="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item!, TextProperty ?? string.Empty))"
aria-label="@(RemoveChipTitle + " " + GetItemOrValueFromProperty(item!, TextProperty ?? string.Empty))"
type="button" class="rz-button rz-button-sm rz-button-icon-only rz-base rz-shade-default @(Disabled ?"rz-state-disabled":"")"
@onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)">
<RadzenIcon Icon="close" />
</button>
</div>
}
</div>
@@ -126,13 +133,15 @@
@RenderFilter()
@if (ShowSearch)
{
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button" title="@SearchTextPlaceholder" @onclick="@((args) => OnFilter(new ChangeEventArgs()))">
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button"
title="@SearchTextPlaceholder" aria-label="@SearchTextPlaceholder" @onclick="@((args) => OnFilter(new ChangeEventArgs()))">
<i class="notranslate rz-button-icon-left rzi">search</i>
</button>
}
@if (ShowAdd)
{
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" style="margin-left: 5px" type="button" title="@AddAriaLabel" @onclick="@OnAddClick">
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" style="margin-left: 5px" type="button"
title="@AddAriaLabel" aria-label="@AddAriaLabel" @onclick="@OnAddClick">
<i class="notranslate rz-button-icon-left rzi">add</i>
</button>
}
@@ -192,7 +201,8 @@
@if (AllowClear && (!Multiple && HasValue || Multiple && (selectedItems.Count > 0 || SelectedValue is IEnumerable)))
{
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
<button type="button" class="notranslate rz-dropdown-clear-icon rzi rzi-times" aria-label="@ClearAriaLabel"
@onclick="@Clear" @onclick:stopPropagation="true"></button>
}
</div>
}

View File

@@ -8,8 +8,10 @@
Disabled = itemArgs.Disabled;
@if (DropDown?.Multiple == true)
{
<li class="@GetComponentCssClass("rz-multiselect")"
<li class="@GetComponentCssClass("rz-multiselect")" role="option" tabindex="-1"
aria-label="@(DropDown?.GetItemOrValueFromProperty(Item!, DropDown?.TextProperty ?? string.Empty) ?? "")"
aria-selected="@(DropDown?.IsSelected(Item) == true)"
aria-disabled="@(Disabled || DropDown?.Disabled == true ? "true" : "false")"
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
@attributes="@(itemArgs?.Attributes.Any() == true ? itemArgs.Attributes : Attributes)">
@@ -32,10 +34,13 @@ Disabled = itemArgs.Disabled;
}
else
{
<li role="option" class="@GetComponentCssClass("rz-dropdown")" aria-label="@(DropDown?.GetItemOrValueFromProperty(Item, DropDown?.TextProperty ?? "") ?? "")"
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
@attributes="@(itemArgs?.Attributes.Any() == true ? itemArgs.Attributes : Attributes)">
<li role="option" class="@GetComponentCssClass("rz-dropdown")" tabindex="-1"
aria-label="@(DropDown?.GetItemOrValueFromProperty(Item, DropDown?.TextProperty ?? "") ?? "")"
aria-selected="@(DropDown?.IsSelected(Item) == true)"
aria-disabled="@(Disabled || DropDown?.Disabled == true ? "true" : "false")"
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
@attributes="@(itemArgs?.Attributes.Any() == true ? itemArgs.Attributes : Attributes)">
<span>
@if (DropDown?.Template != null)
{

View File

@@ -14,12 +14,15 @@
ToggleShade="@ToggleShade"
Disabled="@Disabled"
AriaLabel="@AriaLabel"
AriaExpanded="@isOpen.ToString().ToLowerInvariant()"
AriaControls="@($"{GetId()}-items")"
AriaHasPopup="menu"
class="@ButtonClass"
style="@ButtonStyleCss">
</RadzenToggleButton>
@if (isOpen)
{
<RadzenStack onclick=@CloseAsync Orientation=@StackOrientation AlignItems=@StackAlignment Gap=@Gap class=@GetStackClasses() style=@ComputedItemsStyle ChildContent="@ChildContent" />
<RadzenStack onclick=@CloseAsync Orientation=@StackOrientation AlignItems=@StackAlignment Gap=@Gap class=@GetStackClasses() style=@ComputedItemsStyle ChildContent="@ChildContent" id=@($"{GetId()}-items") role="menu" />
}
</div>

View File

@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Radzen.Blazor;

View File

@@ -9,9 +9,9 @@
<legend class="rz-fieldset-legend" style="white-space:nowrap">
@if (AllowCollapse)
{
<a id="@(GetId() + "expc")" title="@TitleAttribute()" aria-label="@AriaLabelAttribute()" @onclick:preventDefault="true"
aria-controls="rz-fieldset-0-content" aria-expanded="@(collapsed ? "false" : "true")" @onclick=@Toggle
tabindex="0" @onkeypress="@(args => OnKeyPress(args, Toggle(new EventArgs())))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<button type="button" id="@(GetId() + "expc")" title="@TitleAttribute()" aria-label="@AriaLabelAttribute()"
aria-controls="@($"{GetId()}-content")" aria-expanded="@(collapsed ? "false" : "true")" @onclick=@Toggle
@onkeypress="@(args => OnKeyPress(args, Toggle(new EventArgs())))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
@if (collapsed)
{
<span class="notranslate rz-fieldset-toggler rzi rzi-w rzi-plus"></span>
@@ -30,7 +30,7 @@
<span class="rz-fieldset-legend-text">@Text</span>
}
@HeaderTemplate
</a>
</button>
}
else
{
@@ -46,7 +46,7 @@
}
</legend>
}
<Expander Expanded=@(!collapsed) CssClass="rz-fieldset-content-wrapper" id="rz-fieldset-0-content">
<Expander Expanded=@(!collapsed) CssClass="rz-fieldset-content-wrapper" id="@($"{GetId()}-content")">
<div class="rz-fieldset-content">
@ChildContent
</div>

View File

@@ -9,7 +9,10 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class=@ChooseClass tabindex="@(Disabled ? "-1" : $"{TabIndex}")" onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
<span class=@ChooseClass tabindex="@(Disabled ? "-1" : $"{TabIndex}")" role="button"
aria-disabled="@(Disabled ? "true" : "false")" aria-label="@ChooseText"
aria-controls="@(Name ?? GetId())"
onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
<input id="@(Name ?? GetId())" @attributes="InputAttributes" tabindex="-1" disabled="@Disabled" @ref="@fileUpload" name="@Name" type="file" accept="@Accept" onkeydown="event.stopPropagation()"
onchange="Radzen.uploadInputChange(event, null, false, false, true)" />
<span class="rz-button-text">@ChooseText</span>
@@ -23,7 +26,9 @@
<div>
@if (IsImage)
{
<img style="@ImageStyle" src="@ImageValue" @onclick="@OnImageClick" alt="@ImageAlternateText" />
<img style="@ImageStyle" src="@ImageValue" @onclick="@OnImageClick" alt="@ImageAlternateText"
role="@(ImageClick.HasDelegate ? "button" : null)" tabindex="@(ImageClick.HasDelegate ? "0" : null)"
@onkeydown="OnImageKeyDown" />
}
</div>
<div>

View File

@@ -247,6 +247,20 @@ namespace Radzen.Blazor
}
}
async Task OnImageKeyDown(KeyboardEventArgs args)
{
if (!ImageClick.HasDelegate)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnImageClick(new MouseEventArgs());
}
}
async System.Threading.Tasks.Task Remove(EventArgs args)
{
Value = default(TValue)!;

View File

@@ -1,6 +1,21 @@
@inherits RadzenComponentWithChildren
@using System.Collections.Generic
@inherits RadzenComponentWithChildren
@if (Visible)
{
<img @ref="@Element" src="@Path" style="@Style" @onclick="@((args) => OnClick(args))" @attributes="Attributes" class="@GetCssClass()" id="@GetId()" alt="@GetAlternateText()" />
var imgAttributes = new Dictionary<string, object>();
if (Attributes != null)
{
foreach (var attribute in Attributes)
{
imgAttributes[attribute.Key] = attribute.Value;
}
}
if (Click.HasDelegate)
{
imgAttributes["role"] = "button";
imgAttributes["tabindex"] = "0";
}
<img @ref="@Element" src="@Path" style="@Style" @onclick="@((args) => OnClick(args))" @onkeydown="OnKeyDown" @attributes="imgAttributes" class="@GetCssClass()" id="@GetId()" alt="@GetAlternateText()" />
}

View File

@@ -64,6 +64,26 @@ namespace Radzen.Blazor
await Click.InvokeAsync(args);
}
/// <summary>
/// Handles keyboard activation for clickable images.
/// </summary>
/// <param name="args">The <see cref="KeyboardEventArgs"/> instance containing the event data.</param>
protected async System.Threading.Tasks.Task OnKeyDown(KeyboardEventArgs args)
{
ArgumentNullException.ThrowIfNull(args);
if (!Click.HasDelegate)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnClick(new MouseEventArgs());
}
}
string GetAlternateText()
{
if (Attributes != null && Attributes.TryGetValue("alt", out var @alt) && !string.IsNullOrEmpty(Convert.ToString(@alt, CultureInfo.InvariantCulture)))

View File

@@ -23,7 +23,10 @@
{
@if (AllowSelectAll)
{
<div class="rz-chkbox " @onclick="@SelectAll">
<div class="rz-chkbox" @onclick="@SelectAll" role="checkbox" tabindex="@(Disabled || ReadOnly ? "-1" : "0")"
aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())"
aria-disabled="@(Disabled || ReadOnly ? "true" : "false")"
@onkeydown="OnSelectAllKeyDown">
<div class="rz-helper-hidden-accessible">
<input id="@($"{UniqueID}sa")" readonly="readonly" type="checkbox" aria-label="@SelectAllText" aria-checked="@(IsAllSelected().ToString().ToLowerInvariant())">
</div>
@@ -50,7 +53,7 @@
@if (View != null)
{
<div class="rz-listbox-list-wrapper">
<ul @ref="list" class="rz-listbox-list">
<ul @ref="list" class="rz-listbox-list" role="listbox" aria-multiselectable="@(Multiple ? "true" : "false")">
@RenderItems()
</ul>
</div>

View File

@@ -109,6 +109,7 @@ namespace Radzen.Blazor
await OnKeyPress(args, false);
}
private bool visibleChanged;
private bool disabledChanged;
private bool firstRender = true;

View File

@@ -6,7 +6,9 @@
@if (itemArgs?.Visible == true)
{
Disabled = itemArgs.Disabled;
<li class="@GetComponentCssClass()" aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, ListBox?.TextProperty)" @onclick="@SelectItem"
<li class="@GetComponentCssClass()" role="option" aria-selected="@(ListBox?.IsSelected(Item) == true)" tabindex="-1"
aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, ListBox?.TextProperty)" @onclick="@SelectItem"
aria-disabled="@(Disabled || ListBox?.Disabled == true ? "true" : "false")"
@attributes="@(itemArgs?.Attributes.Any() == true ? itemArgs.Attributes : Attributes)">
@if (ListBox?.Multiple == true)
{

View File

@@ -37,7 +37,7 @@
}
@if (AllowResetPassword)
{
<a tabindex="0" class="rz-link" @onclick=@OnReset>@ResetPasswordText</a>
<button type="button" class="rz-link" @onclick=@OnReset>@ResetPasswordText</button>
}
</RadzenStack>
@if (AllowRegister)
@@ -84,7 +84,7 @@
}
@if (AllowResetPassword)
{
<a tabindex="0" class="rz-link" @onclick=@OnReset>@ResetPasswordText</a>
<button type="button" class="rz-link" @onclick=@OnReset>@ResetPasswordText</button>
}
</div>
</div>

View File

@@ -2,13 +2,14 @@
@if (Visible)
{
<ul @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()
<ul @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId() role="menubar" aria-label="@AriaLabel"
tabindex="0" @onkeydown="@OnKeyPress" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation
@onfocus=@this.AsNonRenderingEventHandler(OnFocus)>
@if (Responsive)
{
<li class="rz-menu-toggle-item">
<button aria-label=@ToggleAriaLabel class="rz-menu-toggle" @onclick=@OnToggle>
<button type="button" aria-label=@ToggleAriaLabel class="rz-menu-toggle" @onclick=@OnToggle
aria-haspopup="menu" aria-expanded="@IsOpen.ToString().ToLowerInvariant()" aria-controls="@GetId()">
@if (IsOpen)
{
<i class="notranslate rzi">close</i>

View File

@@ -78,6 +78,13 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<MenuItemEventArgs> Click { get; set; }
/// <summary>
/// Gets or sets the menu aria label text.
/// </summary>
/// <value>The menu aria label text.</value>
[Parameter]
public string AriaLabel { get; set; } = "Menu";
[Inject]
NavigationManager? NavigationManager { get; set; }

View File

@@ -57,7 +57,7 @@
</div>
@if (ChildContent != null)
{
<ul class="rz-navigation-menu" style="display: none">
<ul id="@($"{GetId()}-submenu")" class="rz-navigation-menu" role="menu" style="display: none">
<CascadingValue Value=this>
@ChildContent
</CascadingValue>

View File

@@ -111,6 +111,8 @@ namespace Radzen.Blazor
[Parameter]
public RenderFragment? ChildContent { get; set; }
internal string? SubmenuId => ChildContent != null ? $"{GetId()}-submenu" : null;
/// <summary>
/// Gets or sets the click callback.
/// </summary>

View File

@@ -1,10 +1,16 @@
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@inherits RadzenComponentWithChildren
@if (Item?.Parent?.ClickToOpen == true)
{
<li style=@Style @attributes="@Attributes" @onclick="@Item.OnClick" @onclick:stopPropagation>
<li style=@Style @attributes="@Attributes" @onclick="@Item.OnClick" @onclick:stopPropagation role="menuitem"
tabindex="@(Item?.Disabled == true ? -1 : 0)" aria-disabled="@(Item?.Disabled == true ? "true" : "false")"
aria-haspopup="@(Item?.ChildContent != null ? "menu" : null)"
aria-controls="@Item?.SubmenuId"
aria-expanded="@(Item?.ChildContent != null ? "false" : null)"
@onkeydown="OnKeyDown">
@ChildContent
</li>
}
@@ -12,13 +18,20 @@ else
{
if (Item?.ChildContent != null)
{
<li style=@Style @attributes="@Attributes" onmouseenter="Radzen.toggleMenuItem(this, event, true, false)" onmouseleave="Radzen.toggleMenuItem(this, event, false, false)">
<li style=@Style @attributes="@Attributes" onmouseenter="Radzen.toggleMenuItem(this, event, true, false)" onmouseleave="Radzen.toggleMenuItem(this, event, false, false)"
role="menuitem" tabindex="@(Item?.Disabled == true ? -1 : 0)" aria-disabled="@(Item?.Disabled == true ? "true" : "false")"
aria-haspopup="menu" aria-controls="@Item?.SubmenuId" aria-expanded="false" @onkeydown="OnKeyDown">
@ChildContent
</li>
}
else
{
<li style=@Style @attributes="@Attributes" @onclick="@(Item!.OnClick)" @onclick:stopPropagation>
<li style=@Style @attributes="@Attributes" @onclick="@(Item!.OnClick)" @onclick:stopPropagation role="menuitem"
tabindex="@(Item?.Disabled == true ? -1 : 0)" aria-disabled="@(Item?.Disabled == true ? "true" : "false")"
aria-haspopup="@(Item?.ChildContent != null ? "menu" : null)"
aria-controls="@Item?.SubmenuId"
aria-expanded="@(Item?.ChildContent != null ? "false" : null)"
@onkeydown="OnKeyDown">
@ChildContent
</li>
}
@@ -32,4 +45,25 @@ else
/// <value>The menu item.</value>
[Parameter]
public RadzenMenuItem? Item { get; set; }
async Task OnKeyDown(KeyboardEventArgs args)
{
if (Item == null || Item.Disabled)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
if (Item.ChildContent != null)
{
await Item.Toggle();
}
else
{
await Item.OnClick(new MouseEventArgs());
}
}
}
}

View File

@@ -1,20 +1,27 @@
@using System.Collections.Generic
@using System.Timers
@implements IDisposable
@if (Visible)
{
var classes = GetMessageCssClasses();
<div aria-live="polite" class="rz-notification-item-wrapper rz-open @classes.Item1" style="@(Message?.Click != null || Message?.CloseOnClick == true ? "cursor: pointer;" : "") @Style">
var clickable = Message?.Click != null || Message?.CloseOnClick == true;
var wrapperAttributes = clickable ? new Dictionary<string, object>
{
{ "role", "button" },
{ "tabindex", "0" }
} : null;
<div aria-live="polite" class="rz-notification-item-wrapper rz-open @classes.Item1" style="@(clickable ? "cursor: pointer;" : "") @Style"
@attributes="wrapperAttributes" @onclick="NotificationClicked" @onkeydown="OnKeyDown">
<div class="rz-notification-item">
<div class="rz-notification-message-wrapper">
<span class="notranslate rzi rz-notification-icon @classes.Item2" @onclick="NotificationClicked"></span>
<div class="rz-notification-message" @onclick="NotificationClicked">
<span class="notranslate rzi rz-notification-icon @classes.Item2"></span>
<div class="rz-notification-message">
<div class="rz-notification-title">@if (Message?.SummaryContent != null && Service != null) { @Message.SummaryContent(Service) } else { @Message?.Summary }</div>
<div class="rz-notification-content">@if (Message?.DetailContent != null && Service != null) { @Message.DetailContent(Service) } else { @Message?.Detail }</div>
</div>
</div>
<div class="notranslate rzi rz-notification-close" @onclick="@Close"></div>
<button type="button" class="notranslate rzi rz-notification-close" aria-label="@(Message?.CloseAriaLabel ?? "Close")" @onclick="@Close" @onclick:stopPropagation="true"></button>
</div>
<RadzenProgressBar ShowValue="false" Visible=@(Message?.Duration != null && Message.ShowProgress)
Value=@progress Max="@(Message?.Duration ?? 0)" ProgressBarStyle=@GetProgressBarStyle() />
@@ -103,12 +110,29 @@
private void NotificationClicked()
{
if (Message?.Click == null && Message?.CloseOnClick != true)
return;
if (Message?.CloseOnClick == true)
Close();
Message?.Click?.Invoke(Message);
}
private void OnKeyDown(KeyboardEventArgs args)
{
if (Message?.Click == null && Message?.CloseOnClick != true)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
NotificationClicked();
}
}
public void Dispose()
{
timer?.Stop();

View File

@@ -1,9 +1,10 @@
@inherits RadzenComponent
@if (GetVisible())
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()"
@onkeydown="@OnKeyDown" @onkeydown:preventDefault="preventKeyDown" @onkeydown:stopPropagation="true" tabindex=0
@onfocus=@this.AsNonRenderingEventHandler(OnFocus)>
<nav @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()"
aria-label="@NavigationAriaLabel"
@onkeydown="@OnKeyDown" @onkeydown:preventDefault="preventKeyDown" @onkeydown:stopPropagation="true" tabindex=0
@onfocus=@this.AsNonRenderingEventHandler(OnFocus)>
@if(ShowPagingSummary)
{
<span class="rz-pager-summary">
@@ -17,41 +18,53 @@
}
</span>
}
<a id="@(GetId() + "fp")" class="rz-pager-first rz-pager-element @(skip > 0 ? "": "rz-state-disabled") @(focusedIndex == -2 ? "rz-state-focused": "")" @onclick:preventDefault="true" @onclick="@(() => OnFirstPageClick())" aria-label="@FirstPageAriaLabel" role="button" title="@FirstPageTitle" disabled="@(CurrentPage <= 0)">
<span class="notranslate rz-pager-icon rzi rzi-step-backward"></span>
</a>
<a id="@(GetId() + "pp")" class="rz-pager-prev rz-pager-element @(skip > 0 ? "": "rz-state-disabled") @(focusedIndex == -1 ? "rz-state-focused": "")" @onclick:preventDefault="true" @onclick="@(() => OnPrevPageClick())" aria-label="@PrevPageAriaLabel" role="button" title="@PrevPageTitle" disabled="@(CurrentPage <= 0)">
<span class="notranslate rz-pager-icon rzi rzi-caret-left"></span>
@if (PrevPageLabel != null)
{
<span class="rz-pager-label">@PrevPageLabel</span>
}
</a>
<span class="rz-pager-pages">
<ul class="rz-pager-pages" role="list">
<li class="rz-pager-item">
<button id="@(GetId() + "fp")" type="button" class="rz-pager-first rz-pager-element @(skip > 0 ? "": "rz-state-disabled") @(focusedIndex == -2 ? "rz-state-focused": "")"
@onclick="@(() => OnFirstPageClick())" aria-label="@FirstPageAriaLabel" title="@FirstPageTitle" disabled="@(CurrentPage <= 0)" aria-disabled="@(CurrentPage <= 0 ? "true" : "false")">
<span class="notranslate rz-pager-icon rzi rzi-step-backward"></span>
</button>
</li>
<li class="rz-pager-item">
<button id="@(GetId() + "pp")" type="button" class="rz-pager-prev rz-pager-element @(skip > 0 ? "": "rz-state-disabled") @(focusedIndex == -1 ? "rz-state-focused": "")"
@onclick="@(() => OnPrevPageClick())" aria-label="@PrevPageAriaLabel" title="@PrevPageTitle" disabled="@(CurrentPage <= 0)" aria-disabled="@(CurrentPage <= 0 ? "true" : "false")">
<span class="notranslate rz-pager-icon rzi rzi-caret-left"></span>
@if (PrevPageLabel != null)
{
<span class="rz-pager-label">@PrevPageLabel</span>
}
</button>
</li>
@foreach (var i in Enumerable.Range(startPage, Math.Min(endPage + 1, PageNumbersCount)))
{
<a id="@(GetId() + i.ToString() + "p")" class="rz-pager-page rz-pager-element @(i == CurrentPage ? "rz-state-active" : "") @(startPage + focusedIndex == i ? "rz-state-focused": "")" @onclick:preventDefault="true" @onclick="@(() => OnPageClick(i, startPage))" aria-current="@(i == CurrentPage ? "page" : null)" aria-label="@string.Format(PageAriaLabelFormat, (i + 1).ToString())" role="button" title="@string.Format(PageTitleFormat, (i + 1).ToString())">@(i + 1)</a>
<li class="rz-pager-item">
<button id="@(GetId() + i.ToString() + "p")" type="button" class="rz-pager-page rz-pager-element @(i == CurrentPage ? "rz-state-active" : "") @(startPage + focusedIndex == i ? "rz-state-focused": "")"
@onclick="@(() => OnPageClick(i, startPage))" aria-current="@(i == CurrentPage ? "page" : null)" aria-label="@string.Format(PageAriaLabelFormat, (i + 1).ToString())"
title="@string.Format(PageTitleFormat, (i + 1).ToString())">@(i + 1)</button>
</li>
}
</span>
<a id="@(GetId() + "np")" class="rz-pager-next rz-pager-element @((CurrentPage != numberOfPages - 1) ? "": "rz-state-disabled") @(focusedIndex == Math.Min(endPage + 1, PageNumbersCount)? "rz-state-focused": "")" @onclick:preventDefault="true" @onclick="@(() => OnNextPageClick(endPage))" aria-label="@NextPageAriaLabel" role="button" title="@NextPageTitle" disabled="@(CurrentPage >= (numberOfPages - 1))">
@if (NextPageLabel != null)
{
<span class="rz-pager-label">@NextPageLabel</span>
}
<span class="notranslate rz-pager-icon rzi rzi-caret-right"></span>
</a>
<a id="@(GetId() + "lp")" class="rz-pager-last rz-pager-element @((CurrentPage != numberOfPages - 1) ? "": "rz-state-disabled") @(focusedIndex == Math.Min(endPage + 1, PageNumbersCount) + 1 ? "rz-state-focused": "")" @onclick:preventDefault="true" @onclick="@(() => OnLastPageClick(endPage))" aria-label="@LastPageAriaLabel" role="button" title="@LastPageTitle" disabled="@(CurrentPage >= (numberOfPages - 1))">
<span class="notranslate rz-pager-icon rzi rzi-step-forward"></span>
</a>
<li class="rz-pager-item">
<button id="@(GetId() + "np")" type="button" class="rz-pager-next rz-pager-element @((CurrentPage != numberOfPages - 1) ? "": "rz-state-disabled") @(focusedIndex == Math.Min(endPage + 1, PageNumbersCount)? "rz-state-focused": "")"
@onclick="@(() => OnNextPageClick(endPage))" aria-label="@NextPageAriaLabel" title="@NextPageTitle" disabled="@(CurrentPage >= (numberOfPages - 1))" aria-disabled="@(CurrentPage >= (numberOfPages - 1) ? "true" : "false")">
@if (NextPageLabel != null)
{
<span class="rz-pager-label">@NextPageLabel</span>
}
<span class="notranslate rz-pager-icon rzi rzi-caret-right"></span>
</button>
</li>
<li class="rz-pager-item">
<button id="@(GetId() + "lp")" type="button" class="rz-pager-last rz-pager-element @((CurrentPage != numberOfPages - 1) ? "": "rz-state-disabled") @(focusedIndex == Math.Min(endPage + 1, PageNumbersCount) + 1 ? "rz-state-focused": "")"
@onclick="@(() => OnLastPageClick(endPage))" aria-label="@LastPageAriaLabel" title="@LastPageTitle" disabled="@(CurrentPage >= (numberOfPages - 1))" aria-disabled="@(CurrentPage >= (numberOfPages - 1) ? "true" : "false")">
<span class="notranslate rz-pager-icon rzi rzi-step-forward"></span>
</button>
</li>
</ul>
@if(PageSizeOptions != null && PageSizeOptions.Any())
{
<RadzenDropDown TValue="int" Data="@PageSizeOptions" Value="@PageSize" Change="@OnPageSizeChanged" />
<span class="rz-pagesize-text">@PageSizeText</span>
}
</div>
</nav>
}

View File

@@ -165,6 +165,12 @@ namespace Radzen.Blazor
[Parameter]
public bool ShowPagingSummary { get; set; }
/// <summary>
/// Gets or sets the navigation aria-label.
/// </summary>
[Parameter]
public string NavigationAriaLabel { get; set; } = "Pagination";
/// <summary>
/// Gets or sets the pager summary format. <see cref="PagingSummaryTemplate" /> has preference over this property.
/// </summary>

View File

@@ -20,15 +20,15 @@
@HeaderTemplate
@if (AllowCollapse)
{
<a id="@(GetId() + "expc")" @onclick=@Toggle class="rz-panel-titlebar-icon rz-panel-titlebar-toggler"
@onclick:preventDefault="true" role="button" aria-controls="rz-panel-0-content"
aria-expanded="@(collapsed ? "false" : "true")" aria-label="@(collapsed ? ExpandAriaLabel : CollapseAriaLabel)" title="@(collapsed ? ExpandTitle : CollapseTitle)"
tabindex="0" @onkeypress="@(args => OnKeyPress(args, Toggle(new MouseEventArgs())))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<button id="@(GetId() + "expc")" type="button" @onclick=@Toggle class="rz-panel-titlebar-icon rz-panel-titlebar-toggler"
aria-controls="@($"{GetId()}-content")"
aria-expanded="@(collapsed ? "false" : "true")" aria-label="@(collapsed ? ExpandAriaLabel : CollapseAriaLabel)" title="@(collapsed ? ExpandTitle : CollapseTitle)"
@onkeypress="@(args => OnKeyPress(args, Toggle(new MouseEventArgs())))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<span class="notranslate rzi @(collapsed ? "rzi-plus" : "rzi-minus")"></span>
</a>
</button>
}
</div>
<Expander Expanded=@(!collapsed) CssClass="rz-panel-content-wrapper">
<Expander Expanded=@(!collapsed) CssClass="rz-panel-content-wrapper" id="@($"{GetId()}-content")">
<div class="rz-panel-content">
@ChildContent
</div>

View File

@@ -2,7 +2,8 @@
@if (Visible)
{
<ul @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId() tabindex="0"
<ul @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()
role="menu" aria-label="@AriaLabel" tabindex="0"
@onkeydown=@OnKeyPress
@onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation
@onfocus=@this.AsNonRenderingEventHandler(OnFocus)>

View File

@@ -38,6 +38,13 @@ namespace Radzen.Blazor
[Parameter]
public EventCallback<MenuItemEventArgs> Click { get; set; }
/// <summary>
/// Gets or sets the menu aria label text.
/// </summary>
/// <value>The menu aria label text.</value>
[Parameter]
public string AriaLabel { get; set; } = "Menu";
/// <summary>
/// Gets or sets a value representing the URL matching behavior.
/// </summary>

View File

@@ -3,7 +3,12 @@
@inherits RadzenComponent
@if (Visible)
{
<li @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId() @onclick=@(this.AsNonRenderingEventHandler<MouseEventArgs>(OnClick)) @onclick:stopPropagation>
<li @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()
role="menuitem" tabindex="@(Disabled ? -1 : 0)" aria-disabled="@(Disabled ? "true" : "false")"
aria-haspopup="@(ChildContent != null ? "menu" : null)"
aria-controls="@(ChildContent != null ? $"{GetId()}-submenu" : null)"
aria-expanded="@(ChildContent != null ? expanded.ToString().ToLowerInvariant() : null)"
@onclick=@(this.AsNonRenderingEventHandler<MouseEventArgs>(OnClick)) @onclick:stopPropagation @onkeydown="OnKeyDown">
<div class=@WrapperClass>
@if (Path != null)
{
@@ -22,17 +27,21 @@
}
else if (Parent?.DisplayStyle == MenuItemDisplayStyle.Text || Parent?.DisplayStyle == MenuItemDisplayStyle.IconAndText)
{
<span class="rz-navigation-item-text" @onclick="@Toggle">@Text</span>
<span class="rz-navigation-item-text">@Text</span>
}
@if (ChildContent != null && Parent?.ShowArrow == true)
{
<i class=@ToggleClass @onclick="@Toggle" @onclick:preventDefault>keyboard_arrow_down</i>
<i class=@ToggleClass>keyboard_arrow_down</i>
}
</NavLink>
}
else
{
<div class="rz-navigation-item-link" style="@(Parent?.DisplayStyle == MenuItemDisplayStyle.Icon?"margin-inline-end:0px;":"")" @onclick="@Toggle">
<div class="rz-navigation-item-link" style="@(Parent?.DisplayStyle == MenuItemDisplayStyle.Icon?"margin-inline-end:0px;":"")"
role="button" tabindex="0" aria-expanded="@expanded.ToString().ToLowerInvariant()"
aria-controls="@(ChildContent != null ? $"{GetId()}-submenu" : null)"
aria-haspopup="@(ChildContent != null ? "menu" : null)"
@onclick="@Toggle" @onkeydown="OnToggleKeyDown">
@if (!string.IsNullOrEmpty(Icon) && (Parent?.DisplayStyle == MenuItemDisplayStyle.Icon || Parent?.DisplayStyle == MenuItemDisplayStyle.IconAndText))
{
<i class="notranslate rzi rz-navigation-item-icon" style="@getIconStyle()">@Icon</i>
@@ -59,7 +68,7 @@
@if (ChildContent != null)
{
<Expander Expanded=@expanded>
<ul class="rz-navigation-menu">
<ul id="@($"{GetId()}-submenu")" class="rz-navigation-menu" role="menu">
<CascadingValue Value=this>
@ChildContent
</CascadingValue>

View File

@@ -424,6 +424,34 @@ namespace Radzen.Blazor
}
}
async Task OnKeyDown(KeyboardEventArgs args)
{
if (Disabled)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnClick(new MouseEventArgs());
}
}
async Task OnToggleKeyDown(KeyboardEventArgs args)
{
if (Disabled)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await Toggle();
}
}
/// <inheritdoc />
public override void Dispose()
{

View File

@@ -98,7 +98,7 @@
class="rz-pivot-header-content @(isSortable ? "rz-sortable" : "")"
tabindex="@(isSortable ? "0" : null)"
role="@(isSortable ? "button" : null)"
aria-label="@(isSortable ? $"Sort by {row?.GetTitle()}" : null)">
aria-label="@(isSortable ? string.Format(SortAriaLabelFormat, row?.GetTitle()) : null)">
<span class="rz-pivot-header-text">@row?.GetTitle()</span>
@if (isSortable)
{
@@ -118,12 +118,14 @@
</div>
@if (isFilterable)
{
<i @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (row != null) _ = ToggleFilter(row, filterIconRefKey); })"
class="@(row != null ? GetFilterIconCss(row) : "")"
title="Filter">
<button type="button" @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (row != null) _ = ToggleFilter(row, filterIconRefKey); })"
@onclick="@(() => { if (row != null) _ = ToggleFilter(row, filterIconRefKey); })"
class="@(row != null ? GetFilterIconCss(row) : "")"
aria-label="@FilterText" aria-haspopup="dialog"
aria-controls="@($"pivot-filter-{row?.Property}")" aria-expanded="false">
@FilterIcon
</i>
</button>
}
</div>
</th>
@@ -151,7 +153,7 @@
class="rz-pivot-header-content @(isSortable ? "rz-sortable" : "")"
tabindex="@(isSortable ? "0" : null)"
role="@(isSortable ? "button" : null)"
aria-label="@(isSortable ? $"Sort by {column?.GetTitle()}" : null)">
aria-label="@(isSortable ? string.Format(SortAriaLabelFormat, column?.GetTitle()) : null)">
<span class="rz-pivot-header-text">@column?.GetTitle()</span>
@if (isSortable)
{
@@ -171,12 +173,14 @@
</div>
@if (isFilterable)
{
<i @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
class="@(column != null ? GetFilterIconCss(column) : "")"
title="Filter">
<button type="button" @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
@onclick="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
class="@(column != null ? GetFilterIconCss(column) : "")"
aria-label="@FilterText" aria-haspopup="dialog"
aria-controls="@($"pivot-filter-{column?.Property}")" aria-expanded="false">
@FilterIcon
</i>
</button>
}
</div>
</th>
@@ -204,7 +208,7 @@
class="rz-pivot-header-content @(isSortable ? "rz-sortable" : "")"
tabindex="@(isSortable ? "0" : null)"
role="@(isSortable ? "button" : null)"
aria-label="@(isSortable ? $"Sort by {column?.GetTitle()}" : null)">
aria-label="@(isSortable ? string.Format(SortAriaLabelFormat, column?.GetTitle()) : null)">
<span class="rz-pivot-header-text">@column?.GetTitle()</span>
@if (isSortable)
{
@@ -224,12 +228,14 @@
</div>
@if (isFilterable)
{
<i @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
class="@(column != null ? GetFilterIconCss(column) : "")"
title="Filter">
<button type="button" @ref=FilterIconRef[filterIconRefKey] @onclick:stopPropagation="true"
@onmousedown="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
@onclick="@(() => { if (column != null) _ = ToggleFilter(column, filterIconRefKey); })"
class="@(column != null ? GetFilterIconCss(column) : "")"
aria-label="@FilterText" aria-haspopup="dialog"
aria-controls="@($"pivot-filter-{column?.Property}")" aria-expanded="false">
@FilterIcon
</i>
</button>
}
</div>
</th>
@@ -295,6 +301,8 @@
{
<div class="rz-pivot-drill-down-header">
<span @onclick="@(() => ToggleColumnDrillDown(cell.PathKey))"
@onkeydown="@(args => OnDrillDownKeyDown(args, cell.PathKey))"
role="button" tabindex="0" aria-expanded="@(!cell.IsCollapsed).ToString().ToLowerInvariant()"
class="notranslate rz-tree-toggler rzi rzi-caret-@(cell.IsCollapsed ? "right" : "down")" style="margin-inline-start:0"></span>
<span class="rz-pivot-header-text">
@if (cell.HeaderTemplate != null && cell.Group != null)
@@ -431,6 +439,7 @@
var prefix = currentFilterField is RadzenPivotColumn<TItem> ? "col" : currentFilterField is RadzenPivotRow<TItem> ? "row" : "agg";
var filterIconRefKey = $"{prefix}{currentFilterField.GetFilterProperty()}";
<Popup @ref="filterPopup" id="@($"pivot-filter-{currentFilterField.Property}")" class="rz-overlaypanel"
role="dialog" aria-label="@FilterText"
style="display:none;min-width:250px;" @onkeydown=@(args => OnFilterPopupKeyPressed(args, filterIconRefKey))>
<div class="rz-overlaypanel-content">
@if (currentFilterField.FilterTemplate != null)

View File

@@ -190,6 +190,13 @@ namespace Radzen.Blazor
[Parameter]
public string AggregatesText { get; set; } = "Aggregates";
/// <summary>
/// Gets or sets the sort aria label format.
/// </summary>
/// <value>The sort aria label format.</value>
[Parameter]
public string SortAriaLabelFormat { get; set; } = "Sort by {0}";
/// <summary>
/// Gets or set the filter icon to use.
/// </summary>
@@ -1602,6 +1609,15 @@ namespace Radzen.Blazor
await HandleFieldSort(pivotRows, row);
}
async Task OnDrillDownKeyDown(KeyboardEventArgs args, string pathKey)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await ToggleColumnDrillDown(pathKey);
}
}
private async Task HandleFieldSort<T>(List<T> allFields, T sortedField)
where T : RadzenPivotField<TItem>
{

View File

@@ -3,9 +3,13 @@
@if (Visible)
{
<ul @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
tabindex="0" @onkeydown="@OnKeyPress" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
role="menu" aria-label="@ToggleAriaLabel" tabindex="0"
@onkeydown="@OnKeyPress" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
<li class="rz-navigation-item">
<div class="rz-navigation-item-wrapper" onclick="Radzen.toggleMenuItem(this)">
<div class="rz-navigation-item-wrapper" role="button" tabindex="0" aria-haspopup="menu"
aria-label="@ToggleAriaLabel"
aria-expanded="@(!Collapsed).ToString().ToLowerInvariant()" aria-controls="@($"{GetId()}-menu")"
onclick="Radzen.toggleMenuItem(this)" @onkeydown="OnToggleKeyDown">
<div class="rz-navigation-item-link">
<div class="item-text" @onkeydown:stopPropagation>
@if (Template != null)
@@ -19,7 +23,8 @@
}
</div>
</div>
<ul class="rz-navigation-menu" style="@contentStyle" @onkeydown:stopPropagation>
<ul id="@($"{GetId()}-menu")" class="rz-navigation-menu" role="menu" style="@contentStyle"
aria-hidden="@(Collapsed ? "true" : "false")" @onkeydown:stopPropagation>
<CascadingValue Value=this>
@ChildContent
</CascadingValue>

View File

@@ -50,6 +50,13 @@ namespace Radzen.Blazor
[Parameter]
public bool ShowIcon { get; set; } = true;
/// <summary>
/// Gets or sets the toggle aria label text.
/// </summary>
/// <value>The toggle aria label text.</value>
[Parameter]
public string ToggleAriaLabel { get; set; } = "Profile menu";
string contentStyle = "display:none;position:absolute;z-index:1;";
/// <summary>
@@ -133,6 +140,15 @@ namespace Radzen.Blazor
}
}
async Task OnToggleKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Space" || key == "Enter")
{
await Toggle(new MouseEventArgs());
}
}
internal bool IsFocused(RadzenProfileMenuItem item)
{
return items.IndexOf(item) == focusedIndex && focusedIndex != -1;

View File

@@ -2,7 +2,7 @@
@inherits RadzenComponent
@if (Visible)
{
<li @attributes="Attributes" class="@GetItemCssClass()" style="@Style" @onclick="@OnClick">
<li @attributes="Attributes" class="@GetItemCssClass()" style="@Style" @onclick="@OnClick" role="menuitem" tabindex="0" @onkeydown="OnKeyDown">
<div class="rz-navigation-item-wrapper">
@if (Path != null)
{

View File

@@ -125,6 +125,15 @@ namespace Radzen.Blazor
}
}
async Task OnKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnClick(new MouseEventArgs());
}
}
RadzenProfileMenu? _parent;
/// <summary>
/// Gets or sets the parent.

View File

@@ -15,15 +15,19 @@
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
role="radiogroup" @onfocus=@OnFocus @onblur=@OnBlur
role="radiogroup" aria-disabled="@(Disabled ? "true" : "false")" @onfocus=@OnFocus @onblur=@OnBlur
tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
<RadzenStack Orientation="@Orientation" JustifyContent="@JustifyContent" AlignItems="@AlignItems" Gap="@Gap" Wrap="@Wrap">
@foreach (var item in allItems.Where(i => i.Visible))
{
<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style" role="radio" aria-checked=@(IsSelected(item)? "true" : "false") aria-label="@item.Text">
<div @ref="@item.Element" id="@item.GetItemId()" @onclick="@(args => SelectItem(item))" @onkeydown="@(args => OnItemKeyDown(args, item))"
@attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style"
role="radio" tabindex="@(Disabled || item.Disabled ? "-1" : "0")"
aria-checked=@(IsSelected(item)? "true" : "false") aria-label="@item.Text"
aria-disabled="@(Disabled || item.Disabled ? "true" : "false")">
<div class="rz-radiobutton">
<div class="rz-helper-hidden-accessible">
<input type="radio" disabled="@Disabled" name="@Name" value="@item.Value" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" @attributes="item.InputAttributes">
<input type="radio" disabled="@(Disabled || item.Disabled)" name="@Name" value="@item.Value" tabindex="-1" aria-label="@(item.Text + " " + item.Value)" @attributes="item.InputAttributes">
</div>
<div class=@ItemClass(item)>
<span class=@IconClass(item)></span>

View File

@@ -250,6 +250,15 @@ namespace Radzen.Blazor
StateHasChanged();
}
async Task OnItemKeyDown(KeyboardEventArgs args, RadzenRadioButtonListItem<TValue> item)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await SelectItem(item);
}
}
/// <summary>
/// Refreshes this instance.
/// </summary>

View File

@@ -6,19 +6,19 @@
<div @ref="@Element" style=@Style @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@if (!ReadOnly)
{
<a id="@(GetId() + "cl")" aria-label="@ClearAriaLabel" @onclick="@(args => SetValue(0))" @onclick:preventDefault="true" class="rz-rating-cancel"
tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
<button type="button" id="@(GetId() + "cl")" aria-label="@ClearAriaLabel" @onclick="@(args => SetValue(0))" class="rz-rating-cancel"
tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
@onkeypress="@(args => OnKeyPress(args, SetValue(0)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<span class="notranslate rz-rating-icon rzi rzi-ban"></span>
</a>
</button>
}
@foreach (var index in Enumerable.Range(1, Stars))
{
<a id="@(GetId() + index.ToString() + "r")" aria-label="@RateAriaLabel" @onclick="@(args => SetValue(index))" @onclick:preventDefault="true"
<button type="button" id="@(GetId() + index.ToString() + "r")" aria-label="@RateAriaLabel" @onclick="@(args => SetValue(index))"
tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
@onkeypress="@(args => OnKeyPress(args, SetValue(index)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<span class="notranslate rz-rating-icon rzi @(index <= Value ? "rzi-star": "rzi-star-o")"></span>
</a>
</button>
}
</div>
}

View File

@@ -14,13 +14,17 @@
@if (Visible)
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
role="toolbar" aria-orientation="horizontal" @onfocus=@this.AsNonRenderingEventHandler(OnFocus) @onblur=@this.AsNonRenderingEventHandler(OnBlur)
role="toolbar" aria-orientation="@(Orientation == Orientation.Vertical ? "vertical" : "horizontal")"
aria-disabled="@(Disabled ? "true" : "false")"
@onfocus=@this.AsNonRenderingEventHandler(OnFocus) @onblur=@this.AsNonRenderingEventHandler(OnBlur)
tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
@foreach (var item in allItems.Where(i => i.Visible))
{
<div @ref="@item.Element" id="@item.GetItemId()"
<button type="button" @ref="@item.Element" id="@item.GetItemId()"
@onclick="@(args => SelectItem(item))"
@attributes="item.Attributes" style="@item.Style" class=@ButtonClass(item) aria-label="@item.Text" aria-selected=@(IsSelected(item)? "true" : "false")>
@attributes="item.Attributes" style="@item.Style" class=@ButtonClass(item)
aria-label="@item.Text" aria-pressed="@(IsSelected(item)? "true" : "false")"
disabled="@(Disabled || item.Disabled)">
@if (item.Template != null)
{
@item.Template(item)
@@ -37,7 +41,7 @@
}
<span class="rz-button-text">@item.Text</span>
}
</div>
</button>
}
</div>
}

View File

@@ -1,7 +1,7 @@
@inherits RadzenComponent
@if (Visible)
{
<button aria-label="@ToggleAriaLabel" tabindex="0" @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" @onclick="@OnClick" id="@GetId()">
<button type="button" aria-label="@ToggleAriaLabel" tabindex="0" @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" @onclick="@OnClick" id="@GetId()">
<i class="notranslate rzi rz-display-flex rz-align-items-center">@(!string.IsNullOrWhiteSpace(Icon) ? Icon : "menu")</i>
</button>
}

View File

@@ -43,11 +43,12 @@
}
</span>
</button>
<button tabindex="-1" disabled="@IsDisabled" onclick="@OpenPopupScript()" class=@PopupButtonClass type="button" aria-label="@OpenAriaLabel">
<button tabindex="-1" disabled="@IsDisabled" onclick="@OpenPopupScript()" class=@PopupButtonClass type="button"
aria-label="@OpenAriaLabel" aria-haspopup="menu" aria-controls="@PopupID" aria-expanded="false">
<RadzenIcon Icon="@DropDownIcon" />
</button>
<div id="@PopupID" class="rz-splitbutton-menu">
<ul class="rz-menu-list">
<ul class="rz-menu-list" role="menu" aria-label="@OpenAriaLabel">
<CascadingValue Value=this>
@ChildContent
</CascadingValue>

View File

@@ -1,8 +1,9 @@
@inherits RadzenComponent
@if (Visible)
{
<li class=@ItemClass role="menuitem" @onclick="@OnClick" @attributes="Attributes" style="@Style">
<a id="@(SplitButton?.SplitButtonId() + GetHashCode())" class="rz-menuitem-link">
<li class=@ItemClass role="menuitem" tabindex="@(Disabled ? "-1" : "0")" aria-disabled="@(Disabled ? "true" : "false")"
@onclick="@OnClick" @onkeydown="OnKeyDown" @attributes="Attributes" style="@Style">
<span id="@(SplitButton?.SplitButtonId() + GetHashCode())" class="rz-menuitem-link">
@if (!string.IsNullOrEmpty(Icon))
{
<span class="rz-menuitem-icon" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@Icon</span>
@@ -11,6 +12,6 @@
{
<span class="rz-menuitem-text">@Text</span>
}
</a>
</span>
</li>
}

View File

@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor.Rendering;
using System;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
@@ -81,6 +82,21 @@ namespace Radzen.Blazor
}
}
async Task OnKeyDown(KeyboardEventArgs args)
{
ArgumentNullException.ThrowIfNull(args);
if (Disabled)
{
return;
}
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnClick(new MouseEventArgs());
}
}
string ItemClass => ClassList.Create("rz-menuitem")
.AddDisabled(Disabled)
.Add("rz-state-highlight", SplitButton?.IsFocused(this) == true)

View File

@@ -21,10 +21,13 @@
var step = steps[i];
@if (step.Visible)
{
<li class="@step.GetItemCssClass()" @attributes="step.Attributes" style="@step.Style" tabindex="@(step.Disabled ? -1 : 0)" @onkeypress="@(args => OnKeyPress(args, SelectStep(step, true)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation>
<a id="@(GetId() + i.ToString() + "s")" title="@step.Title" aria-label="@step.AriaLabel"
<li class="@step.GetItemCssClass()" @attributes="step.Attributes" style="@step.Style">
<button type="button" role="tab" id="@(GetId() + i.ToString() + "s")" title="@step.Title" aria-label="@step.AriaLabel"
aria-selected="@(IsSelected(i, step) ? "true" : "false")"
aria-controls="@($"{GetId()}-panel-{i}")"
@onclick="@(async (args) => { if (!step.Disabled && AllowStepSelect) { await SelectStep(step, true); } })"
@onclick:preventDefault="true" class="rz-menuitem-link">
@onkeypress="@(args => OnKeyPress(args, SelectStep(step, true)))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
disabled="@step.Disabled" aria-disabled="@step.Disabled" class="rz-menuitem-link">
<span class="rz-steps-number">@(steps.Where(s => s.Visible).ToList().IndexOf(step) + 1)</span>
@if (step.Template != null)
{
@@ -34,7 +37,7 @@
{
<span class="rz-steps-title">@step.Text</span>
}
</a>
</button>
</li>
}
}
@@ -47,7 +50,7 @@
{
@if (IsSelected(i, step))
{
<div class="rz-widget-content">
<div class="rz-widget-content" role="tabpanel" id="@($"{GetId()}-panel-{i}")" aria-labelledby="@(GetId() + i.ToString() + "s")">
@if (step.ChildContent != null)
{
@step.ChildContent
@@ -59,14 +62,16 @@
@if(ShowStepsButtons)
{
<div class="rz-steps-buttons">
<a id="@(GetId() + "prev")" title="@PreviousTitle" aria-label="@PreviousAriaLabel" tabindex="@(IsFirstVisibleStep() ? -1 : 0)"
<button type="button" id="@(GetId() + "prev")" title="@PreviousTitle" aria-label="@PreviousAriaLabel"
class='@($"rz-steps-prev {(IsFirstVisibleStep() ? "rz-state-disabled" : "")}")'
@onkeypress="@(args => OnKeyPress(args, PrevStep()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
@onclick="@PrevStep" @onclick:preventDefault="true"><span class="notranslate rzi"></span>@PreviousText</a>
<a id="@(GetId() + "next")" title="@NextTitle" aria-label="@NextAriaLabel" tabindex="@(IsLastVisibleStep() ? -1 : 0)"
disabled="@(IsFirstVisibleStep())" aria-disabled="@(IsFirstVisibleStep())"
@onkeypress="@(args => OnKeyPress(args, PrevStep()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
@onclick="@PrevStep"><span class="notranslate rzi"></span>@PreviousText</button>
<button type="button" id="@(GetId() + "next")" title="@NextTitle" aria-label="@NextAriaLabel"
class='@($"rz-steps-next {(IsLastVisibleStep() ? "rz-state-disabled" : "")}")'
@onkeypress="@(args => OnKeyPress(args, NextStep()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
@onclick="@NextStep" @onclick:preventDefault="true">@NextText<span class="notranslate rzi"></span></a>
disabled="@(IsLastVisibleStep())" aria-disabled="@(IsLastVisibleStep())"
@onkeypress="@(args => OnKeyPress(args, NextStep()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation
@onclick="@NextStep">@NextText<span class="notranslate rzi"></span></button>
</div>
}
</div>

View File

@@ -3,11 +3,12 @@
@inherits FormComponent<bool>
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onclick="@Toggle" @onkeypress="@(args => OnKeyPress(args, Toggle()))" @onkeypress:preventDefault=preventKeyPress @onkeypress:stopPropagation style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" id="@Name" checked="@Value" value="@ValueAsString" tabindex="-1" aria-checked="@(Value.ToString().ToLowerInvariant())" @attributes=@InputAttributes>
</div>
<label @ref="@Element" @attributes="Attributes" class="@GetCssClass()" id="@GetId()" style="@Style">
<input type="checkbox" role="switch" name="@Name" id="@Name" checked="@Value"
value="@ValueAsString" tabindex="@(Disabled || ReadOnly ? "-1" : $"{TabIndex}")"
disabled="@(Disabled || ReadOnly)" aria-checked="@(Value.ToString().ToLowerInvariant())"
@onclick="@Toggle" @onkeydown="@OnKeyPress"
@onkeydown:stopPropagation class="rz-hidden-accessible" @attributes=@InputAttributes>
<span class="rz-switch-circle@(Disabled ? " rz-disabled" : ReadOnly ? " rz-readonly" : "")"></span>
</div>
</label>
}

View File

@@ -63,7 +63,7 @@ namespace Radzen.Blazor
/// Does nothing if the switch is disabled or read-only.
/// </summary>
/// <returns>A task representing the asynchronous toggle operation.</returns>
public async System.Threading.Tasks.Task Toggle()
public async Task Toggle()
{
if (Disabled || ReadOnly)
{
@@ -77,20 +77,13 @@ namespace Radzen.Blazor
await Change.InvokeAsync(Value);
}
bool preventKeyPress = true;
async Task OnKeyPress(KeyboardEventArgs args, Task task)
async Task OnKeyPress(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Space" || key == "Enter")
if (key == "Enter")
{
preventKeyPress = true;
await task;
}
else
{
preventKeyPress = false;
await Toggle();
}
}
}

View File

@@ -6,7 +6,8 @@
{
<div @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()
tabindex=0 @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
<ul role="tablist" class="rz-tabview-nav">
<ul role="tablist" class="rz-tabview-nav"
aria-orientation="@(TabPosition == TabPosition.Left || TabPosition == TabPosition.Right ? "vertical" : "horizontal")">
@Tabs
</ul>
<div class="rz-tabview-panels">

View File

@@ -2,9 +2,15 @@
@implements IDisposable
@if ((Tabs?.RenderMode == TabRenderMode.Server ? Visible : true))
{
<li role="tab" @attributes=@Attributes style=@getStyle() class=@Class
aria-selected=@(IsSelected ? "true" : "false") aria-controls="@($"{Tabs?.Id ?? ""}-tabpanel-{Index}")">
<a @onclick=@OnClick @onclick:preventDefault="true" id="@($"{Tabs?.Id ?? ""}-tabpanel-{Index}-label")" @onkeydown:stopPropagation>
<li role="presentation" style=@getStyle() class=@Class>
<button type="button" role="tab" @attributes=@Attributes @onclick=@OnClick
id="@($"{Tabs?.Id ?? ""}-tabpanel-{Index}-label")"
aria-selected="@(IsSelected ? "true" : "false")"
aria-controls="@($"{Tabs?.Id ?? ""}-tabpanel-{Index}")"
aria-disabled="@(Disabled ? "true" : "false")"
disabled="@Disabled"
tabindex="@(Disabled ? "-1" : (IsSelected ? "0" : "-1"))"
@onkeydown:stopPropagation>
@if (!string.IsNullOrEmpty(Icon))
{
<span class="notranslate rzi rz-tabview-icon" style="@(!string.IsNullOrEmpty(IconColor) ? $"color:{IconColor}" : null)">@Icon</span>
@@ -17,6 +23,6 @@
{
<span class="rz-tabview-title">@Text</span>
}
</a>
</button>
</li>
}

View File

@@ -29,18 +29,20 @@
@onkeydown:preventDefault="@preventKeyPress" @onkeydown:stopPropagation />
@if (ShowPopupButton)
{
<button type="button" aria-label="@TogglePopupAriaLabel" disabled="@Disabled"
tabindex="-1" class="@GetTogglePopupButtonClass()"
<button type="button" aria-label="@TogglePopupAriaLabel" aria-haspopup="dialog"
aria-expanded="@isPopupOpen.ToString().ToLowerInvariant()" aria-controls="@($"{GetId()}-popup")"
disabled="@Disabled" tabindex="-1" class="@GetTogglePopupButtonClass()"
@onclick="@ClickPopupButton">
<span aria-hidden="true" class="notranslate rz-button-icon-left rzi rzi-timespan"></span><span class="rz-button-text"></span>
</button>
}
@if (AllowClear && HasValue && (_isNullable || ConfirmedValue != DefaultNonNullValue) && !Disabled && !ReadOnly)
{
<i class="notranslate rz-dropdown-clear-icon rzi rzi-times" @onclick="@Clear" @onclick:stopPropagation="true"></i>
<button type="button" class="notranslate rz-dropdown-clear-icon rzi rzi-times" aria-label="@ClearAriaLabel" @onclick="@Clear" @onclick:stopPropagation="true"></button>
}
<Popup @ref="@popup" Lazy="@(PopupRenderMode == PopupRenderMode.OnDemand)"
<Popup id="@($"{GetId()}-popup")" @ref="@popup" Lazy="@(PopupRenderMode == PopupRenderMode.OnDemand)"
Open="@OnPopupOpen" Close="@OnPopupClose"
role="dialog" aria-label="@PopupAriaLabel"
class="rz-timespanpicker-popup-container">
@RenderPanel()
</Popup>

View File

@@ -161,6 +161,19 @@ namespace Radzen.Blazor
/// </summary>
[Parameter]
public string TogglePopupAriaLabel { get; set; } = "Toggle popup";
/// <summary>
/// Specifies the aria label for the popup.
/// </summary>
[Parameter]
public string PopupAriaLabel { get; set; } = "Time span picker";
/// <summary>
/// Gets or sets the clear button aria label text.
/// </summary>
/// <value>The clear button aria label text.</value>
[Parameter]
public string ClearAriaLabel { get; set; } = "Clear";
#endregion
#region Parameters: panel config
@@ -716,6 +729,8 @@ namespace Radzen.Blazor
private Task ClosePopup()
=> Inline ? Task.CompletedTask : popup?.CloseAsync(Element) ?? Task.CompletedTask;
private bool isPopupOpen;
private async Task PopupKeyDown(KeyboardEventArgs args)
{
var key = args.Code ?? args.Key;
@@ -728,11 +743,13 @@ namespace Radzen.Blazor
private void OnPopupOpen()
{
isPopupOpen = true;
ResetUnconfirmedValue();
preventKeyPress = true;
}
private void OnPopupClose()
{
isPopupOpen = false;
ResetUnconfirmedValue();
preventKeyPress = false;
}

View File

@@ -1,7 +1,16 @@
@inherits RadzenComponentWithChildren
<li role="presentation" @ref=@Element style=@Style @attributes=@Attributes class=@GetCssClass() id=@GetId()>
<div class=@WrapperClass>
<a href=@Selector class=@LinkClass @onclick:preventDefault @onclick=@OnClickAsync>@if (Template is null) {@Text} else {@Template}</a>
<button type="button" class=@LinkClass @onclick=@OnClickAsync aria-current="@(selected ? "location" : null)">
@if (Template is null)
{
@Text
}
else
{
@Template
}
</button>
</div>
@if (ChildContent != null)
{

View File

@@ -6,10 +6,12 @@
type="@((Enum.GetName(typeof(ButtonType), ButtonType) ?? ButtonType.ToString()).ToLower())"
@attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onclick="@OnClick" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
aria-label="@AriaLabel">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" id="@Name" checked="@Value" value="@(Value.ToString().ToLower())" tabindex="-1" aria-checked="@(Value.ToString().ToLowerInvariant())" @attributes=@InputAttributes>
</div>
aria-label="@AriaLabel" aria-pressed="@(Value.ToString().ToLowerInvariant())"
aria-expanded="@AriaExpanded" aria-controls="@AriaControls" aria-haspopup="@AriaHasPopup">
@if (!string.IsNullOrEmpty(Name))
{
<input type="hidden" name="@Name" id="@Name" value="@(Value.ToString().ToLowerInvariant())" @attributes=@InputAttributes />
}
<span class="rz-button-box">
@if (ChildContent != null)
{

View File

@@ -47,6 +47,27 @@ namespace Radzen.Blazor
[Parameter]
public string? ToggleIcon { get; set; }
/// <summary>
/// Gets or sets the aria-expanded attribute.
/// </summary>
/// <value>The aria-expanded attribute.</value>
[Parameter]
public string? AriaExpanded { get; set; }
/// <summary>
/// Gets or sets the aria-controls attribute.
/// </summary>
/// <value>The aria-controls attribute.</value>
[Parameter]
public string? AriaControls { get; set; }
/// <summary>
/// Gets or sets the aria-haspopup attribute.
/// </summary>
/// <value>The aria-haspopup attribute.</value>
[Parameter]
public string? AriaHasPopup { get; set; }
private string? GetIcon()
{
return Value && !string.IsNullOrEmpty(ToggleIcon) ? ToggleIcon : Icon;

View File

@@ -6,6 +6,7 @@
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()"
role="tree" aria-multiselectable="@(AllowCheckBoxes ? "true" : null)"
tabindex="0" @onkeydown="@OnKeyPress" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation>
<ul class="rz-tree-container">
<CascadingValue Value=this>

View File

@@ -4,10 +4,13 @@
@{var itemArgs = Tree?.ItemAttributes(this); }
<li class="rz-treenode" @attributes="@(itemArgs?.Item1.Attributes.Any() == true ? itemArgs.Item1.Attributes : Attributes)"
@oncontextmenu="OnContextMenu" @oncontextmenu:preventDefault="@(Tree?.ItemContextMenu.HasDelegate ?? false)" @oncontextmenu:stopPropagation>
<div class=@ContentClass @onclick="@Select">
<div class=@ContentClass role="treeitem" tabindex="0"
aria-selected="@(selected.ToString().ToLowerInvariant())"
aria-expanded="@(ChildContent != null || HasChildren ? clientExpanded.ToString().ToLowerInvariant() : null)"
@onclick="@Select" @onkeydown="OnKeyDown">
@if (ChildContent != null || HasChildren)
{
<span class=@IconClass @onclick="@Toggle" @onclick:stopPropagation></span>
<span class=@IconClass role="button" tabindex="0" aria-label="@Text" @onclick="@Toggle" @onclick:stopPropagation @onkeydown="OnToggleKeyDown"></span>
}
@if(Tree != null && Tree.AllowCheckBoxes)
{

View File

@@ -276,6 +276,24 @@ namespace Radzen.Blazor
Tree?.SelectItem(this);
}
void OnKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
Select();
}
}
async Task OnToggleKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await Toggle();
}
}
internal void Unselect()
{
selected = false;

View File

@@ -8,7 +8,9 @@
{
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<div class="rz-fileupload-buttonbar">
<span class="@ChooseClassList" tabindex="@(Disabled ? -1 : 0)" onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
<span class="@ChooseClassList" tabindex="@(Disabled ? -1 : 0)" role="button" aria-label="@ChooseText"
aria-disabled="@(Disabled ? "true" : "false")" aria-controls="@(Name ?? GetId())"
onkeydown="if(event.keyCode == 32 || event.keyCode == 13){event.preventDefault();this.firstElementChild.click();}">
@RenderInput()
@if (!string.IsNullOrEmpty(Icon))
{
@@ -32,7 +34,10 @@
<div>@file.Name</div>
<div>@(file.Size / 1024) KB</div>
<div>
<button title=@DeleteText tabindex="0" disabled="@Disabled" @onclick="@(args => OnRemove(file))" type="button" class="@ButtonClassList"><span class="rz-icon-trash" style="display:block"></span></button>
<button title=@DeleteText tabindex="0" disabled="@Disabled" @onclick="@(args => OnRemove(file))"
aria-label="@DeleteText" type="button" class="@ButtonClassList">
<span class="rz-icon-trash" style="display:block"></span>
</button>
</div>
</div>
}

View File

@@ -4,7 +4,9 @@
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable
<div @ref=@element class="@($"{"rz-event"} {CssClass}".Trim())" style=@Style @onclick=@OnClick @onmouseenter=@OnMouseEnter @onmouseleave=@OnMouseLeave>
<div @ref=@element class="@($"{"rz-event"} {CssClass}".Trim())" style=@Style
role="button" tabindex="0" aria-label="@Data?.Text"
@onclick=@OnClick @onkeydown="OnKeyDown" @onmouseenter=@OnMouseEnter @onmouseleave=@OnMouseLeave>
<div class="rz-event-content" title=@Title @attributes=@Attributes>
@if (ShowAppointmentContent && Scheduler != null && Data != null)
{
@@ -85,6 +87,15 @@
await Click.InvokeAsync(Data);
}
async Task OnKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnClick();
}
}
async Task OnMouseEnter()
{
if (Scheduler != null && Data != null)

View File

@@ -2,7 +2,7 @@
@inherits DropableViewBase
<div class="rz-view rz-day-view">
<div class="rz-view-header" @onclick=@(args => OnDayClick(@StartDate))>
<div class="rz-view-header" role="button" tabindex="0" @onclick=@(args => OnDayClick(@StartDate)) @onkeydown="OnHeaderKeyDown">
<div class="rz-slot-hour-header"></div>
<div class="rz-slot-header">
@StartDate.ToString("ddd", Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
@@ -86,6 +86,15 @@
}
}
async Task OnHeaderKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnDayClick(StartDate);
}
}
IDictionary<string, object> Attributes(DateTime date)
{
var attributes = Scheduler?.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot), () => AppointmentsInSlot(date, date.AddMinutes(MinutesPerSlot))) ?? new Dictionary<string, object>();

View File

@@ -4,38 +4,57 @@
@inject IJSRuntime JSRuntime
@implements IDisposable
<div class=@WrapperClass>
<div @ref="dialog" class=@Class role="dialog" aria-labelledby="rz-dialog-0-label" style=@Style>
@if (Dialog?.Options?.ShowTitle == true)
@{
var options = Dialog?.Options;
var dialogId = $"rz-dialog-{Dialog?.GetHashCode()}";
var titleId = $"{dialogId}-label";
var showTitle = options?.ShowTitle == true;
var ariaAttributes = new Dictionary<string, object?>();
if (showTitle)
{
ariaAttributes["aria-labelledby"] = titleId;
}
else
{
ariaAttributes["aria-label"] = options?.AriaLabel ?? Dialog?.Title;
}
if (ShowMask)
{
ariaAttributes["aria-modal"] = "true";
}
}
<div @ref="dialog" class=@Class role="dialog" style=@Style @attributes="ariaAttributes">
@if (showTitle)
{
<div class="rz-dialog-titlebar">
<div class="rz-dialog-title" id="rz-dialog-0-label">
@if (!string.IsNullOrEmpty(Dialog.Options.Icon))
<div class="rz-dialog-title" id="@titleId">
@if (!string.IsNullOrEmpty(options?.Icon))
{
<RadzenIcon Icon="@Dialog.Options.Icon"
IconColor="@(string.IsNullOrEmpty(Dialog.Options.IconColor) ? null : Dialog.Options.IconColor)"
Style="@Dialog.Options.IconStyle" />
<RadzenIcon Icon="@options.Icon"
IconColor="@(string.IsNullOrEmpty(options.IconColor) ? null : options.IconColor)"
Style="@options.IconStyle" />
}
@if (Dialog.Options.TitleContent != null && Service != null)
@if (options?.TitleContent != null && Service != null)
{
@Dialog.Options.TitleContent(Service)
@options.TitleContent(Service)
}
else
{
@Dialog.Title
@Dialog?.Title
}
</div>
@if (Dialog.Options.ShowClose)
@if (options?.ShowClose == true)
{
<a @onclick:preventDefault="true" @onclick=@Close @onkeydown="@OnKeyPress" role="button" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close" tabindex=@Dialog.Options.CloseTabIndex>
<button type="button" @onclick=@Close @onkeydown="@OnKeyPress" class="rz-dialog-titlebar-icon rz-dialog-titlebar-close" tabindex="@(options?.CloseTabIndex ?? 0)" aria-label="@options?.CloseAriaLabel">
<span class="notranslate rzi rzi-times"></span>
</a>
</button>
}
</div>
}
<div class=@ContentClass>
@if (Dialog?.Options?.ChildContent != null && Service != null)
@if (options?.ChildContent != null && Service != null)
{
@Dialog.Options.ChildContent(Service)
@options.ChildContent(Service)
}
else
{
@@ -48,11 +67,11 @@
{
@if (Dialog?.Options?.CloseDialogOnOverlayClick == true)
{
<div @onclick="@Close" class="rz-dialog-mask"></div>
<div @onclick="@Close" class="rz-dialog-mask" aria-hidden="true" tabindex="-1"></div>
}
else
{
<div class="rz-dialog-mask" style="pointer-events: none;"></div>
<div class="rz-dialog-mask" style="pointer-events: none;" aria-hidden="true" tabindex="-1"></div>
}
}
</div>

View File

@@ -1,4 +1,4 @@
<div class=@Class @onclick=@Select @attributes=@Attributes role="option" aria-selected=@(IsSelected ? "true" : "false")>
<div class=@Class @onclick=@Select @attributes=@Attributes role="option" aria-selected=@(IsSelected ? "true" : "false") tabindex="0" @onkeydown="OnKeyDown">
@if (ChildContent != null)
{
@ChildContent(this)
@@ -30,6 +30,15 @@
await DropDown.Select(this, true);
}
async Task OnKeyDown(KeyboardEventArgs args)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await Select();
}
}
protected override async Task OnParametersSetAsync()
{
if (DropDown?.Value == Value && DropDown != null)

View File

@@ -1,6 +1,6 @@
@using Radzen.Blazor
<span class="rz-legend-item" style="@Style" @onclick="@OnClick" tabindex="0" @onkeypress="@OnKeyPress" @onkeypress:preventDefault=@preventKeyPress @onkeypress:stopPropagation>
<span class="rz-legend-item" style="@Style" @onclick="@OnClick" role="button" aria-disabled="@(!Clickable).ToString().ToLowerInvariant()" tabindex="@(Clickable ? "0" : "-1")" @onkeypress="@OnKeyPress" @onkeypress:preventDefault=@preventKeyPress @onkeypress:stopPropagation>
<svg width="@((MarkerSize * 2).ToInvariantString())" height="@((MarkerSize * 2).ToInvariantString())">
<g class="rz-series-@Index @Class">
<Marker X="@MarkerSize" Y="@MarkerSize" Type="@(MarkerType == MarkerType.None ? MarkerType.Square : MarkerType)" Fill="@Color" Size="@MarkerSize" />

View File

@@ -52,7 +52,7 @@
var slotWidth = 100 / 7.0;
var left = dayIndex * slotWidth;
var top = 1.5 * (MaxAppointmentsInSlot + 1);
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())rem; left: @(left.ToInvariantString())%" @onclick=@(args => { if (slot.Appointments != null && MoreText != null) _ = OnListClick(slot.Start, slot.Appointments); })>@(MoreText != null ? String.Format(MoreText, slot.Hidden) : "")</a>
<button type="button" class="rz-event-list-btn" style="top: @(top.ToInvariantString())rem; left: @(left.ToInvariantString())%" @onclick=@(args => { if (slot.Appointments != null && MoreText != null) _ = OnListClick(slot.Start, slot.Appointments); })>@(MoreText != null ? String.Format(MoreText, slot.Hidden) : "")</button>
}
}
</div>
@@ -61,7 +61,9 @@
{
var dayOfWeek = StartDate.AddDays(days++);
<div @onclick="@(args => OnSlotClick(dayOfWeek))" ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @attributes=@Attributes(dayOfWeek)>
<div class="rz-slot-title @(dayOfWeek == CurrentDate ? " rz-state-focused" : "")" @onclick=@(args => OnDayClick(dayOfWeek)) @onclick:stopPropagation>
<div class="rz-slot-title @(dayOfWeek == CurrentDate ? " rz-state-focused" : "")" role="button" tabindex="0"
@onclick=@(args => OnDayClick(dayOfWeek)) @onclick:stopPropagation
@onkeydown="@(args => OnDayHeaderKeyDown(args, dayOfWeek))">
@dayOfWeek.Day
</div>
</div>
@@ -243,6 +245,15 @@
await Scheduler.SelectDay(day, AppointmentsInSlot(day, day.AddDays(1)));
}
async Task OnDayHeaderKeyDown(KeyboardEventArgs args, DateTime day)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnDayClick(day);
}
}
ElementReference contentView;
async Task OnAppointmentClick(AppointmentData data)

View File

@@ -9,7 +9,9 @@
@for (var day = StartDate; day < EndDate; day = day.AddDays(1))
{
var loopDay = day;
<div class="rz-slot-header" @onclick=@(args => OnDayClick(@loopDay))>
<div class="rz-slot-header" role="button" tabindex="0"
@onclick=@(args => OnDayClick(@loopDay))
@onkeydown="@(args => OnHeaderKeyDown(args, loopDay))">
@day.ToString(HeaderFormat, Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
</div>
}
@@ -98,6 +100,15 @@
}
}
async Task OnHeaderKeyDown(KeyboardEventArgs args, DateTime day)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnDayClick(day);
}
}
IDictionary<string, object> Attributes(DateTime date)
{
if (Scheduler == null)

View File

@@ -94,14 +94,16 @@
var left = (slotIndex + 1) * slotWidth;
var top = ((MaxAppointmentsInSlot + 1) * 0.6) + 1.3;
var listDate = start;
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => { if (appointments != null && MoreText != null) _ = OnListClick(listDate, appointments); })>@(MoreText != null ? String.Format(MoreText, excessCount) : "")</a>
<button type="button" class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => { if (appointments != null && MoreText != null) _ = OnListClick(listDate, appointments); })>@(MoreText != null ? String.Format(MoreText, excessCount) : "")</button>
}
}
}
</div>
<div class="rz-slots">
<div @attributes=@Attributes(realstart, "rz-slot", false)>
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
<div class="rz-slot-header" role="button" tabindex="0"
@onclick=@(args => OnMonthClick(startMonth))
@onkeydown="@(args => OnMonthHeaderKeyDown(args, startMonth))">
@realstart.ToString("MMM", Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
</div>
</div>
@@ -132,7 +134,9 @@
}
}
<div @attributes=@Attributes(realstart, "rz-slot", false)>
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
<div class="rz-slot-header" role="button" tabindex="0"
@onclick=@(args => OnMonthClick(startMonth))
@onkeydown="@(args => OnMonthHeaderKeyDown(args, startMonth))">
@realstart.ToString("MMM", Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
</div>
</div>
@@ -241,6 +245,15 @@
await Scheduler.SelectMonth(monthStart, AppointmentsInRange(monthStart, monthStart.EndOfMonth()));
}
async Task OnMonthHeaderKeyDown(KeyboardEventArgs args, DateTime monthStart)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnMonthClick(monthStart);
}
}
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
{
if (Scheduler == null) return;

View File

@@ -94,14 +94,16 @@
var left = ((slotIndex + 1) * slotWidth) + (100.0 / 85.0);
var top = ((MaxAppointmentsInSlot + 1) * 1.5) + 1.7;
var listDate = start;
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => { if (appointments != null && MoreText != null) _ = OnListClick(listDate, appointments); })>@(MoreText != null ? String.Format(MoreText, excessCount) : "")</a>
<button type="button" class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => { if (appointments != null && MoreText != null) _ = OnListClick(listDate, appointments); })>@(MoreText != null ? String.Format(MoreText, excessCount) : "")</button>
}
}
}
</div>
<div class="rz-slots">
<div @attributes=@Attributes(realstart, "rz-slot", false)>
<div class="rz-slot-header" @onclick=@(args => OnMonthClick(startMonth))>
<div class="rz-slot-header" role="button" tabindex="0"
@onclick=@(args => OnMonthClick(startMonth))
@onkeydown="@(args => OnMonthHeaderKeyDown(args, startMonth))">
@realstart.ToString("MMMM", Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
</div>
</div>
@@ -231,6 +233,15 @@
await Scheduler.SelectMonth(monthStart, AppointmentsInRange(monthStart, monthStart.EndOfMonth()));
}
async Task OnMonthHeaderKeyDown(KeyboardEventArgs args, DateTime monthStart)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnMonthClick(monthStart);
}
}
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
{
if (Scheduler == null) return;

View File

@@ -37,7 +37,7 @@
tabindex="0" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault="@preventKeyPress" @onkeydown:stopPropagation
@onfocus=@(args => {CurrentDate = currentDate; CurrentMonth = currentMonth; })>
<div class="rz-slot-header rz-pb-2" @onclick=@(args => OnMonthClick(startMonth))>
<div class="rz-slot-header rz-pb-2" role="button" tabindex="0" @onclick=@(args => OnMonthClick(startMonth)) @onkeydown="@(args => OnMonthHeaderKeyDown(args, startMonth))">
<span class="rz-text-subtitle1">
@realstart.ToString("MMMM yyyy", Scheduler?.Culture ?? System.Globalization.CultureInfo.CurrentCulture)
</span>
@@ -64,7 +64,7 @@
var excessCount = appointments.Count();
string classname = $"rz-slot-title {(day.Month != offSetMonth ? "rz-other-month" : "")} {(excessCount > 0 ? "rz-has-appointments" : "")} {(day == CurrentDate && month == CurrentMonth ? " rz-state-focused" : "")}".Trim();
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot")>
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot") role="button" tabindex="0" @onkeydown="@(args => OnDayKeyDown(args, day, appointments))">
<div class="@classname">
@day.Day
</div>
@@ -135,6 +135,15 @@
await Scheduler.SelectMonth(monthStart, AppointmentsInRange(monthStart, monthStart.EndOfMonth()));
}
async Task OnMonthHeaderKeyDown(KeyboardEventArgs args, DateTime monthStart)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnMonthClick(monthStart);
}
}
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
{
if (Scheduler == null) return;
@@ -168,6 +177,15 @@
}
}
async Task OnDayKeyDown(KeyboardEventArgs args, DateTime day, IEnumerable<AppointmentData> appointments)
{
var key = args.Code != null ? args.Code : args.Key;
if (key == "Enter" || key == "Space")
{
await OnListClick(day, appointments);
}
}
async Task OnListEventClick(AppointmentData data)
{
DialogService.Close();

View File

@@ -66,7 +66,8 @@ $accordion-shadow: none !default;
border-top: var(--rz-accordion-item-border)
}
> a {
> a,
> button {
padding-block: var(--rz-accordion-item-padding-block);
padding-inline: var(--rz-accordion-item-padding-inline);
color: var(--rz-accordion-item-color);
@@ -77,6 +78,8 @@ $accordion-shadow: none !default;
font-size: var(--rz-accordion-item-font-size);
font-weight: var(--rz-accordion-item-font-weight);
cursor: pointer;
background: none;
border: none;
&:hover {
color: var(--rz-accordion-hover-color);

View File

@@ -66,6 +66,15 @@ $checkbox-tri-icon-font-size: $checkbox-icon-font-size !default;
margin-inline: var(--rz-checkbox-label-margin-inline);
}
button.rz-chkbox-label {
background: none;
border: none;
padding: 0;
font: inherit;
color: inherit;
cursor: pointer;
}
.rz-chkbox {
box-sizing: border-box;
display: inline-block;

View File

@@ -15,6 +15,15 @@
display: none;
}
.rz-hidden-accessible {
opacity: 0;
width: 100%;
height: 0;
padding: 0;
margin: 0;
border: 0;
}
.rz-scrollbar-measure {
width: 100px;
height: 100px;

View File

@@ -389,6 +389,10 @@ $timepicker-border: none !default;
width: 4rem;
}
.rz-ampm-picker a {
.rz-ampm-picker a,
.rz-ampm-picker button {
text-decoration: none;
background: none;
border: none;
padding: 0;
}

View File

@@ -161,6 +161,11 @@ $dialog-resize-bar-handle-size: 16px;
.rz-dialog-titlebar-close,
.rz-dialog-side-titlebar-close {
background: none;
border: none;
padding: 0;
cursor: pointer;
.rzi-times {
font-size: var(--rz-dialog-close-font-size);
color: var(--rz-dialog-close-color);

Some files were not shown because too many files have changed in this diff Show More