Skip to content

Commit

Permalink
[Autocomplete] Update some Accessibility issues (#866)
Browse files Browse the repository at this point in the history
* Update Autocomplete Accessibility items

* Update Unit Tests

* Fix Enter key when popup is closed

* Update Previous and Next titles (and Unit Tests)
  • Loading branch information
dvoituron committed Oct 18, 2023
1 parent 106dae2 commit 95787e6
Show file tree
Hide file tree
Showing 16 changed files with 328 additions and 284 deletions.
13 changes: 13 additions & 0 deletions examples/Demo/Shared/Microsoft.Fast.Components.FluentUI.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3573,6 +3573,16 @@
Footer content, placed at the bottom of the popup panel.
</summary>
</member>
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.TitleScrollToPrevious">
<summary>
Title and Aria-Label for the Scroll to previous button.
</summary>
</member>
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.TitleScrollToNext">
<summary>
Title and Aria-Label for the Scroll to next button.
</summary>
</member>
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.ListStyleValue">
<summary />
</member>
Expand All @@ -3582,6 +3592,9 @@
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.IdScroll">
<summary />
</member>
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.IdPopup">
<summary />
</member>
<member name="P:Microsoft.Fast.Components.FluentUI.FluentAutocomplete`1.IsMultiSelectOpened">
<summary />
</member>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@namespace Microsoft.Fast.Components.FluentUI
@inherits FluentComponentBase
<fluent-anchored-region @ref=Element
id="@Id"
anchor="@Anchor"
viewport="@Viewport"
horizontal-positioning-mode="@HorizontalPositioningMode.ToAttributeValue()"
Expand Down
10 changes: 8 additions & 2 deletions src/Core/Components/List/FluentAutocomplete.razor
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
disabled="@Disabled"
placeholder="@(this.SelectedOptions?.Any() == false ? Placeholder : string.Empty)"
aria-expanded="@(IsMultiSelectOpened ? "true" : "false")"
aria-controls="@(IsMultiSelectOpened ? IdScroll : string.Empty)"
aria-controls="@(IsMultiSelectOpened ? IdPopup : string.Empty)"
aria-label="@(GetAriaLabel() ?? Label ?? Placeholder)"
current-value="@_valueText"
@onclick="@OnDropDownExpandedAsync"
@oninput="@InputHandlerAsync"
Expand All @@ -26,13 +27,17 @@
<fluent-flipper onclick="document.getElementById('@IdScroll').scrollToPrevious()"
slot="previous-flipper"
aria-hidden="false"
aria-label="@TitleScrollToPrevious"
title="@TitleScrollToPrevious"
role="button"
tabindex="0"
class="previous fluent-autocomplete-previous"
direction="previous"></fluent-flipper>
<fluent-flipper onclick="document.getElementById('@IdScroll').scrollToNext()"
slot="next-flipper"
aria-hidden="false"
aria-label="@TitleScrollToNext"
title="@TitleScrollToNext"
role="button"
tabindex="0"
class="next fluent-autocomplete-next"
Expand Down Expand Up @@ -82,7 +87,8 @@
@if (IsMultiSelectOpened)
{
<FluentOverlay OnClose="@(e => IsMultiSelectOpened = false)" Visible="true" Transparent="true" FullScreen="true" />
<FluentAnchoredRegion Anchor="@Id"
<FluentAnchoredRegion Id="@IdPopup"
Anchor="@Id"
HorizontalDefaultPosition="HorizontalPosition.Right"
HorizontalInset="true"
VerticalDefaultPosition="@VerticalPosition.Unset"
Expand Down
20 changes: 20 additions & 0 deletions src/Core/Components/List/FluentAutocomplete.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ public override bool Multiple
[Parameter]
public RenderFragment<IEnumerable<TOption>>? FooterContent { get; set; }

/// <summary>
/// Title and Aria-Label for the Scroll to previous button.
/// </summary>
[Parameter]
public string TitleScrollToPrevious { get; set; } = "Previous";

/// <summary>
/// Title and Aria-Label for the Scroll to next button.
/// </summary>
[Parameter]
public string TitleScrollToNext { get; set; } = "Next";

/// <summary />
private string? ListStyleValue => new StyleBuilder()
.AddStyle("width", Width, when: !string.IsNullOrEmpty(Width))
Expand Down Expand Up @@ -159,6 +171,9 @@ private string ComponentWidth
/// <summary />
private string IdScroll => $"{Id}-scroll";

/// <summary />
private string IdPopup => $"{Id}-popup";

/// <summary />
private bool IsMultiSelectOpened { get; set; } = false;

Expand Down Expand Up @@ -271,6 +286,11 @@ Task KeyDown_ArrowDown()
// Enter
async Task KeyDown_Enter()
{
if (!IsMultiSelectOpened)
{
return;
}

if (Items != null && Items.Any() && SelectableItem != null)
{
await OnSelectedItemChangedHandlerAsync(SelectableItem);
Expand Down
7 changes: 7 additions & 0 deletions tests/Core/FluentAssert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ public static class FluentAssert
}
}

// Create a "received.json" file
else if (Options.UpdateVerifiedFiles)
{
var formattedReceivedHtml = NodePrintExtensions.ToMarkup((IEnumerable<INode>)receivedNodes);
File.WriteAllText(expectedFile.FullName, formattedReceivedHtml);
}

// Create a "received.json" file
else
{
Expand Down
6 changes: 6 additions & 0 deletions tests/Core/FluentAssertOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public class FluentAssertOptions
/// </summary>
public string ReceivedRazorExtension { get; set; } = ".received.razor.html";

/// <summary>
/// True to update the verified files with the received files.
/// No exceptions will be thrown.
/// </summary>
public bool UpdateVerifiedFiles => !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("UPDATE_VERIFIED_FILES"));

/// <summary>
/// Scrub lines with an optional replace.
/// Can return the input to ignore the line, or return a a different string to replace it.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@

<div class=" fluent-autocomplete-multiselect" style="width: 100%;" b-90q402ec2b="">
<fluent-text-field role="combobox" id="xxx" placeholder="" aria-expanded="true" aria-controls="myComponent-scroll" current-value="" blazor:onclick="1" blazor:oninput="2" blazor:onkeydown="3" blazor:onfocusout="4" style="width: 100%; min-width: 100%;" b-90q402ec2b="">
<fluent-horizontal-scroll id="xxx" style="width: 100%;" slot="start" b-90q402ec2b="">
<fluent-flipper onclick="document.getElementById('myComponent-scroll').scrollToPrevious()" slot="previous-flipper" aria-hidden="false" role="button" tabindex="0" class="previous fluent-autocomplete-previous" direction="previous" b-90q402ec2b=""></fluent-flipper>
<fluent-flipper onclick="document.getElementById('myComponent-scroll').scrollToNext()" slot="next-flipper" aria-hidden="false" role="button" tabindex="0" class="next fluent-autocomplete-next" direction="next" b-90q402ec2b=""></fluent-flipper>
<fluent-badge id="xxx" appearance="neutral" blazor:onclick="5" aria-label="Customer { Id = 1, Name = Denis Voituron }" blazor:elementreference="">
<div style="width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap;">
Customer { Id = 1, Name = Denis Voituron }<svg style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer; margin: 2px 0px 0px 2px;" focusable="false" viewBox="0 0 24 24" aria-hidden="true" blazor:onclick="8">
<path d="m4.4 4.55.07-.08a.75.75 0 0 1 .98-.07l.08.07L12 10.94l6.47-6.47a.75.75 0 1 1 1.06 1.06L13.06 12l6.47 6.47c.27.27.3.68.07.98l-.07.08a.75.75 0 0 1-.98.07l-.08-.07L12 13.06l-6.47 6.47a.75.75 0 0 1-1.06-1.06L10.94 12 4.47 5.53a.75.75 0 0 1-.07-.98l.07-.08-.07.08Z"></path>
</svg>
</div>
</fluent-badge>
<fluent-badge id="xxx" appearance="neutral" blazor:onclick="6" aria-label="Customer { Id = 2, Name = Vincent Baaij }" blazor:elementreference="">
<div style="width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap;">
Customer { Id = 2, Name = Vincent Baaij }<svg style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer; margin: 2px 0px 0px 2px;" focusable="false" viewBox="0 0 24 24" aria-hidden="true" blazor:onclick="9">
<path d="m4.4 4.55.07-.08a.75.75 0 0 1 .98-.07l.08.07L12 10.94l6.47-6.47a.75.75 0 1 1 1.06 1.06L13.06 12l6.47 6.47c.27.27.3.68.07.98l-.07.08a.75.75 0 0 1-.98.07l-.08-.07L12 13.06l-6.47 6.47a.75.75 0 0 1-1.06-1.06L10.94 12 4.47 5.53a.75.75 0 0 1-.07-.98l.07-.08-.07.08Z"></path>
</svg>
</div>
</fluent-badge>
</fluent-horizontal-scroll>
<svg slot="end" style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer;" focusable="false" viewBox="0 0 16 16" aria-hidden="true" blazor:onclick="7">
<title>Clear</title>
<path d="m2.59 2.72.06-.07a.5.5 0 0 1 .63-.06l.07.06L8 7.29l4.65-4.64a.5.5 0 0 1 .7.7L8.71 8l4.64 4.65c.18.17.2.44.06.63l-.06.07a.5.5 0 0 1-.63.06l-.07-.06L8 8.71l-4.65 4.64a.5.5 0 0 1-.7-.7L7.29 8 2.65 3.35a.5.5 0 0 1-.06-.63l.06-.07-.06.07Z"></path>
</svg>
</fluent-text-field>
<div class="fluent-overlay" style="cursor: auto; position: fixed; z-index: 9900;" blazor:onclick="10" blazor:oncontextmenu="11" blazor:oncontextmenu:preventdefault="" b-rbsnh2nzwy="">
<div style="display: flex; align-items:center; justify-content: center; width: 100%; heigth: 100%" b-rbsnh2nzwy=""></div>
</div>
<fluent-anchored-region anchor="xxx" horizontal-positioning-mode="dynamic" horizontal-default-position="right" horizontal-inset="" horizontal-threshold="0" horizontal-scaling="content" vertical-positioning-mode="dynamic" vertical-default-position="unset" vertical-threshold="0" vertical-scaling="content" auto-update-mode="auto" style="z-index: 9999;" b-z9rtvm3m6a="" blazor:elementreference="">
<div style="z-index: 9999; background-color: var(--neutral-layer-floating); box-shadow: var(--elevation-shadow-flyout); margin-top: 10px; border-radius: calc(var(--control-corner-radius) * 2px); background-color: var(--neutral-layer-floating);" b-z9rtvm3m6a="">
<div role="listbox" style="width: 100%;" aria-label="List" b-90q402ec2b="">
<fluent-option id="xxx" value="Customer { Id = 1, Name = Denis Voituron }" selected="" blazor:onclick="12" blazor:elementreference="">Customer { Id = 1, Name = Denis Voituron }</fluent-option>
<fluent-option id="xxx" value="Customer { Id = 2, Name = Vincent Baaij }" selected="" blazor:onclick="13" selectable="" blazor:elementreference="">Customer { Id = 2, Name = Vincent Baaij }</fluent-option>
<fluent-option id="xxx" value="Customer { Id = 3, Name = Bill Gates }" blazor:onclick="14" blazor:elementreference="">Customer { Id = 3, Name = Bill Gates }</fluent-option>
</div>
<fluent-text-field role="combobox" id="xxx" placeholder="" aria-expanded="true" aria-controls="myComponent-popup" current-value="" blazor:onclick="1" blazor:oninput="2" blazor:onkeydown="3" blazor:onfocusout="4" style="width: 100%; min-width: 100%;" b-90q402ec2b="">
<fluent-horizontal-scroll id="xxx" style="width: 100%;" slot="start" b-90q402ec2b="">
<fluent-flipper onclick="document.getElementById('myComponent-scroll').scrollToPrevious()" slot="previous-flipper" aria-hidden="false" aria-label="Previous" title="Previous" role="button" tabindex="0" class="previous fluent-autocomplete-previous" direction="previous" b-90q402ec2b=""></fluent-flipper>
<fluent-flipper onclick="document.getElementById('myComponent-scroll').scrollToNext()" slot="next-flipper" aria-hidden="false" aria-label="Next" title="Next" role="button" tabindex="0" class="next fluent-autocomplete-next" direction="next" b-90q402ec2b=""></fluent-flipper>
<fluent-badge id="xxx" appearance="neutral" blazor:onclick="5" aria-label="Customer { Id = 1, Name = Denis Voituron }" blazor:elementreference="">
<div style="width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap;">
Customer { Id = 1, Name = Denis Voituron }<svg style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer; margin: 2px 0px 0px 2px;" focusable="false" viewBox="0 0 24 24" aria-hidden="true" blazor:onclick="8">
<path d="m4.4 4.55.07-.08a.75.75 0 0 1 .98-.07l.08.07L12 10.94l6.47-6.47a.75.75 0 1 1 1.06 1.06L13.06 12l6.47 6.47c.27.27.3.68.07.98l-.07.08a.75.75 0 0 1-.98.07l-.08-.07L12 13.06l-6.47 6.47a.75.75 0 0 1-1.06-1.06L10.94 12 4.47 5.53a.75.75 0 0 1-.07-.98l.07-.08-.07.08Z"></path>
</svg>
</div>
</fluent-badge>
<fluent-badge id="xxx" appearance="neutral" blazor:onclick="6" aria-label="Customer { Id = 2, Name = Vincent Baaij }" blazor:elementreference="">
<div style="width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap;">
Customer { Id = 2, Name = Vincent Baaij }<svg style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer; margin: 2px 0px 0px 2px;" focusable="false" viewBox="0 0 24 24" aria-hidden="true" blazor:onclick="9">
<path d="m4.4 4.55.07-.08a.75.75 0 0 1 .98-.07l.08.07L12 10.94l6.47-6.47a.75.75 0 1 1 1.06 1.06L13.06 12l6.47 6.47c.27.27.3.68.07.98l-.07.08a.75.75 0 0 1-.98.07l-.08-.07L12 13.06l-6.47 6.47a.75.75 0 0 1-1.06-1.06L10.94 12 4.47 5.53a.75.75 0 0 1-.07-.98l.07-.08-.07.08Z"></path>
</svg>
</div>
</fluent-anchored-region>
</fluent-badge>
</fluent-horizontal-scroll>
<svg slot="end" style="width: 12px; fill: var(--accent-fill-rest); cursor: pointer;" focusable="false" viewBox="0 0 16 16" aria-hidden="true" blazor:onclick="7">
<title>Clear</title>
<path d="m2.59 2.72.06-.07a.5.5 0 0 1 .63-.06l.07.06L8 7.29l4.65-4.64a.5.5 0 0 1 .7.7L8.71 8l4.64 4.65c.18.17.2.44.06.63l-.06.07a.5.5 0 0 1-.63.06l-.07-.06L8 8.71l-4.65 4.64a.5.5 0 0 1-.7-.7L7.29 8 2.65 3.35a.5.5 0 0 1-.06-.63l.06-.07-.06.07Z"></path>
</svg>
</fluent-text-field>
<div class="fluent-overlay" style="cursor: auto; position: fixed; z-index: 9900;" blazor:onclick="10" blazor:oncontextmenu="11" blazor:oncontextmenu:preventdefault="" b-rbsnh2nzwy="">
<div style="display: flex; align-items:center; justify-content: center; width: 100%; heigth: 100%" b-rbsnh2nzwy=""></div>
</div>
<fluent-anchored-region id="xxx" anchor="xxx" horizontal-positioning-mode="dynamic" horizontal-default-position="right" horizontal-inset="" horizontal-threshold="0" horizontal-scaling="content" vertical-positioning-mode="dynamic" vertical-default-position="unset" vertical-threshold="0" vertical-scaling="content" auto-update-mode="auto" style="z-index: 9999;" b-z9rtvm3m6a="" blazor:elementreference="">
<div style="z-index: 9999; background-color: var(--neutral-layer-floating); box-shadow: var(--elevation-shadow-flyout); margin-top: 10px; border-radius: calc(var(--control-corner-radius) * 2px); background-color: var(--neutral-layer-floating);" b-z9rtvm3m6a="">
<div role="listbox" style="width: 100%;" aria-label="List" b-90q402ec2b="">
<fluent-option id="xxx" value="Customer { Id = 1, Name = Denis Voituron }" selected="" blazor:onclick="12" blazor:elementreference="">Customer { Id = 1, Name = Denis Voituron }</fluent-option>
<fluent-option id="xxx" value="Customer { Id = 2, Name = Vincent Baaij }" selected="" blazor:onclick="13" selectable="" blazor:elementreference="">Customer { Id = 2, Name = Vincent Baaij }</fluent-option>
<fluent-option id="xxx" value="Customer { Id = 3, Name = Bill Gates }" blazor:onclick="14" blazor:elementreference="">Customer { Id = 3, Name = Bill Gates }</fluent-option>
</div>
</div>
</fluent-anchored-region>
</div>
Loading

0 comments on commit 95787e6

Please sign in to comment.