Skip to content

Commit 74a161e

Browse files
[Fabric] Add Support for Role Prop (#14352)
* Add Support for Role Prop * Change files * Format * Update Tests --------- Co-authored-by: Tatiana Kapos <tatianakapos@microsoft.com>
1 parent 871a067 commit 74a161e

File tree

4 files changed

+112
-8
lines changed

4 files changed

+112
-8
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Add Support for Role Prop",
4+
"packageName": "react-native-windows",
5+
"email": "34109996+chiaramooney@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ class AccessibilityStateExamples extends React.Component {
475475
accessibilityValue={{
476476
text: this.state.viewValueText,
477477
}}
478-
accessibilityRole="combobox"
478+
role="combobox"
479479
testID="accessibilityValue-text"
480480
accessible
481481
aria-readonly>

packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,14 +751,14 @@ exports[`snapshotAllPages Accessibility Windows 4`] = `
751751
The following View exposes the accessibilityValue.Text field
752752
</Text>
753753
<View
754-
accessibilityRole="combobox"
755754
accessibilityValue={
756755
{
757756
"text": "testText",
758757
}
759758
}
760759
accessible={true}
761760
aria-readonly={true}
761+
role="combobox"
762762
style={
763763
{
764764
"backgroundColor": "gray",

vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
283283
return S_OK;
284284
}
285285

286-
long GetControlType(const std::string &role) noexcept {
286+
long GetControlTypeFromString(const std::string &role) noexcept {
287287
if (role == "adjustable") {
288288
return UIA_SliderControlTypeId;
289289
} else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
@@ -346,6 +346,96 @@ long GetControlType(const std::string &role) noexcept {
346346
return UIA_GroupControlTypeId;
347347
}
348348

349+
long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
350+
switch (role) {
351+
case facebook::react::Role::Alert:
352+
return UIA_TextControlTypeId;
353+
case facebook::react::Role::Application:
354+
return UIA_WindowControlTypeId;
355+
case facebook::react::Role::Button:
356+
return UIA_ButtonControlTypeId;
357+
case facebook::react::Role::Checkbox:
358+
return UIA_CheckBoxControlTypeId;
359+
case facebook::react::Role::Columnheader:
360+
return UIA_HeaderControlTypeId;
361+
case facebook::react::Role::Combobox:
362+
return UIA_ComboBoxControlTypeId;
363+
case facebook::react::Role::Document:
364+
return UIA_DocumentControlTypeId;
365+
case facebook::react::Role::Grid:
366+
return UIA_GroupControlTypeId;
367+
case facebook::react::Role::Group:
368+
return UIA_GroupControlTypeId;
369+
case facebook::react::Role::Heading:
370+
return UIA_TextControlTypeId;
371+
case facebook::react::Role::Img:
372+
return UIA_ImageControlTypeId;
373+
case facebook::react::Role::Link:
374+
return UIA_HyperlinkControlTypeId;
375+
case facebook::react::Role::List:
376+
return UIA_ListControlTypeId;
377+
case facebook::react::Role::Listitem:
378+
return UIA_ListItemControlTypeId;
379+
case facebook::react::Role::Menu:
380+
return UIA_MenuControlTypeId;
381+
case facebook::react::Role::Menubar:
382+
return UIA_MenuBarControlTypeId;
383+
case facebook::react::Role::Menuitem:
384+
return UIA_MenuItemControlTypeId;
385+
case facebook::react::Role::None:
386+
return UIA_GroupControlTypeId;
387+
case facebook::react::Role::Presentation:
388+
return UIA_GroupControlTypeId;
389+
case facebook::react::Role::Progressbar:
390+
return UIA_ProgressBarControlTypeId;
391+
case facebook::react::Role::Radio:
392+
return UIA_RadioButtonControlTypeId;
393+
case facebook::react::Role::Radiogroup:
394+
return UIA_GroupControlTypeId;
395+
case facebook::react::Role::Rowgroup:
396+
return UIA_GroupControlTypeId;
397+
case facebook::react::Role::Rowheader:
398+
return UIA_HeaderControlTypeId;
399+
case facebook::react::Role::Scrollbar:
400+
return UIA_ScrollBarControlTypeId;
401+
case facebook::react::Role::Searchbox:
402+
return UIA_EditControlTypeId;
403+
case facebook::react::Role::Separator:
404+
return UIA_SeparatorControlTypeId;
405+
case facebook::react::Role::Slider:
406+
return UIA_SliderControlTypeId;
407+
case facebook::react::Role::Spinbutton:
408+
return UIA_SpinnerControlTypeId;
409+
case facebook::react::Role::Status:
410+
return UIA_StatusBarControlTypeId;
411+
case facebook::react::Role::Summary:
412+
return UIA_GroupControlTypeId;
413+
case facebook::react::Role::Switch:
414+
return UIA_ButtonControlTypeId;
415+
case facebook::react::Role::Tab:
416+
return UIA_TabItemControlTypeId;
417+
case facebook::react::Role::Table:
418+
return UIA_TableControlTypeId;
419+
case facebook::react::Role::Tablist:
420+
return UIA_TabControlTypeId;
421+
case facebook::react::Role::Tabpanel:
422+
return UIA_TabControlTypeId;
423+
case facebook::react::Role::Timer:
424+
return UIA_ButtonControlTypeId;
425+
case facebook::react::Role::Toolbar:
426+
return UIA_ToolBarControlTypeId;
427+
case facebook::react::Role::Tooltip:
428+
return UIA_ToolTipControlTypeId;
429+
case facebook::react::Role::Tree:
430+
return UIA_TreeControlTypeId;
431+
case facebook::react::Role::Treegrid:
432+
return UIA_TreeControlTypeId;
433+
case facebook::react::Role::Treeitem:
434+
return UIA_TreeItemControlTypeId;
435+
}
436+
return UIA_GroupControlTypeId;
437+
}
438+
349439
HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
350440
if (pRetVal == nullptr)
351441
return E_POINTER;
@@ -371,8 +461,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
371461
switch (propertyId) {
372462
case UIA_ControlTypePropertyId: {
373463
pRetVal->vt = VT_I4;
374-
auto role = props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole;
375-
pRetVal->lVal = GetControlType(role);
464+
pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty()
465+
? GetControlTypeFromString(compositionView->DefaultControlType())
466+
: GetControlTypeFromString(props->accessibilityRole)
467+
: GetControlTypeFromRole(props->role);
376468
break;
377469
}
378470
case UIA_AutomationIdPropertyId: {
@@ -412,12 +504,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
412504
}
413505
case UIA_IsContentElementPropertyId: {
414506
pRetVal->vt = VT_BOOL;
415-
pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
507+
pRetVal->boolVal =
508+
(props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
509+
? VARIANT_TRUE
510+
: VARIANT_FALSE;
416511
break;
417512
}
418513
case UIA_IsControlElementPropertyId: {
419514
pRetVal->vt = VT_BOOL;
420-
pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
515+
pRetVal->boolVal =
516+
(props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
517+
? VARIANT_TRUE
518+
: VARIANT_FALSE;
421519
break;
422520
}
423521
case UIA_IsOffscreenPropertyId: {
@@ -564,7 +662,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe
564662
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
565663
if (props == nullptr)
566664
return UIA_E_ELEMENTNOTAVAILABLE;
567-
auto accessibilityRole = props->accessibilityRole;
568665
if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) {
569666
*pRetVal = props->accessibilityState->readOnly.value();
570667
} else {

0 commit comments

Comments
 (0)