Expose TextBox/NumberBox/AutoSuggestBox clear button to Voice Access - #11656
Expose TextBox/NumberBox/AutoSuggestBox clear button to Voice Access#11656Harini Malothu (HariniMalothu17) wants to merge 1 commit into
Conversation
The inline clear ("Delete") button shown by TextBox, NumberBox, and
AutoSuggestBox could not be targeted by Voice Access "Show numbers". The
template set AutomationProperties.AccessibilityView="Raw" on that button,
which removes it from the UIA Content view, and Voice Access only tags
elements in the Content view.
Remove the explicit AccessibilityView="Raw" from the DeleteButton in every
affected template so it reverts to the default Content view. The button
remains Visibility="Collapsed" (shown only in the ButtonVisible visual
state) and keeps IsTabStop="False", so it is exposed to Voice Access only
while it is actually visible and keyboard tab order is unchanged.
Add interaction tests verifying the visible clear/Delete button is exposed
(and invocable) for NumberBox inline mode and for TextBox, distinct from the
Increase/Decrease spin buttons.
Fixes #7996
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2620f9d2-ff0f-45b0-aa36-3626abe3e83a
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Yes |
| Edit textBox = new Edit(FindElement.ByName("ClearButtonTextBox")); | ||
| Verify.IsNotNull(textBox, "The test TextBox should be found."); | ||
|
|
||
| // The clear (Delete) button is only shown while the TextBox is focused and non-empty. |
There was a problem hiding this comment.
If the Delete button isn't an immediate child of the Edit's peer, this test silently fails. Suggestion: use the same FindButton(textBox, "Delete") / FindElement.ByName helper for consistency and robustness.
Protik Biswas (protikbiswas100)
left a comment
There was a problem hiding this comment.
check the comment once
| <ScrollViewer x:Name="ContentElement" Foreground="{TemplateBinding Foreground}" Grid.Row="1" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsTabStop="False" AutomationProperties.AccessibilityView="Raw" ZoomMode="Disabled" /> | ||
| <ContentControl x:Name="PlaceholderTextContentPresenter" Grid.Row="1" Foreground="{ThemeResource TextControlPlaceholderForeground}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsTabStop="False" Grid.ColumnSpan="2" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Content="{TemplateBinding PlaceholderText}" IsHitTestVisible="False" /> | ||
| <Button x:Name="DeleteButton" Grid.Row="1" CornerRadius="{TemplateBinding CornerRadius}" Style="{StaticResource DeleteButtonStyle}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{ThemeResource HelperButtonThemePadding}" IsTabStop="False" Grid.Column="1" Visibility="Collapsed" FontSize="{TemplateBinding FontSize}" Width="32" AutomationProperties.AccessibilityView="Raw" VerticalAlignment="Stretch" /> | ||
| <Button x:Name="DeleteButton" Grid.Row="1" CornerRadius="{TemplateBinding CornerRadius}" Style="{StaticResource DeleteButtonStyle}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{ThemeResource HelperButtonThemePadding}" IsTabStop="False" Grid.Column="1" Visibility="Collapsed" FontSize="{TemplateBinding FontSize}" Width="32" VerticalAlignment="Stretch" /> |
There was a problem hiding this comment.
This is making different behavior for DeleteButton & QueryButton, I think the guidance for delete operation is to use 'delete' in keyboard only. Please check with accessibility team for the right experience before going ahead
There was a problem hiding this comment.
Godly T.Alias (@godlytalias) Voice Access has no keyboard, so the "clear via Delete key" path doesn't serve Voice Access users at all — which is the exact gap #7996 reports. Voice Access acts on elements by name ("Click Delete") or "Show numbers" overlay, and both require the element to be in the UIA tree .Confirmed with accessibility team.
On DeleteButton vs QueryButton: scoped intentionally to #7996; if we want consistency I'll create a new issue for querybutton and address.
There was a problem hiding this comment.
I see that Voice access supports commands to delete text, https://support.microsoft.com/en-us/accessibility/windows/voice-access/voice-access-command-list#edit-text
Moreover the main concern here is that the QueryButton is having the same flags set and this change will make the behavior different for both the buttons
Summary
Fixes the Voice Access issue where the TextBox / NumberBox / AutoSuggestBox inline clear (
x) button could not be targeted by a number tag.When the inline clear button is shown (for example a
NumberBoxwithSpinButtonPlacementMode="Inline"), the button clears the entered text. It is a real namedButtonthat already receives a localized UIA name ("Delete"). However, the template explicitly setAutomationProperties.AccessibilityView="Raw"on thatDeleteButton, which excludes the element from the UIA Content view. Voice Access "Show numbers" only tags elements in the Content view, so the clear button never received a number tag and could not be targeted hands-free.Repro (from #7996)
x) button.What changed
Removed the explicit
AutomationProperties.AccessibilityView="Raw"from theDeleteButtonin every affected template, reverting it to its defaultContentaccessibility view. Because the button remainsVisibility="Collapsed"(only shown in theButtonVisiblevisual state) and keepsIsTabStop="False", it is exposed to Voice Access only while it is actually visible, and keyboard tab order is unchanged.controls/dev/CommonStyles/TextBox_themeresources.xaml— removedAccessibilityView="Raw"from theDeleteButtonin the default TextBox template.controls/dev/CommonStyles/TextBox_themeresources_perf2026.xaml— same change in the perf2026 TextBox template copy.controls/dev/NumberBox/NumberBox.xaml— removedAccessibilityView="Raw"from theDeleteButtonin the inner NumberBox TextBox style.controls/dev/NumberBox/NumberBox_perf2026.xaml— same change in the perf2026 NumberBox template copy.controls/dev/AutoSuggestBox/AutoSuggestBox_themeresources.xaml— removedAccessibilityView="Raw"from theDeleteButton.controls/dev/AutoSuggestBox/AutoSuggestBox_themeresources_perf2026.xaml— same change in the perf2026 AutoSuggestBox template copy.Tests
controls/dev/NumberBox/InteractionTests/NumberBoxTests.cs— addedVerifyClearButtonIsAccessible: switches NumberBox to inline mode, enters a value so the clear button is visible, and verifies the "Delete" button is exposed to UIA (found in the inner TextBox subtree), distinct from the Increase/Decrease spin buttons, then invokes it and checks the text is cleared.controls/dev/CommonStyles/InteractionTests/CommonStylesTests.cs— addedTextBoxClearButtonIsAccessibleTest: focuses a TextBox so the clear button is visible and verifies the "Delete" button is exposed to UIA and clears the text when invoked.controls/dev/CommonStyles/TestUI/TextControlsPage.xaml— named the test TextBox so the new test can find it.Fixes #7996