Skip to content

Commit 68fb4fd

Browse files
[0.74] Rework modal to be implemented entirely using public APIs (#14271)
* Implement ISelectionProvider and ISelectionItemProvider (#14019) Adds support for ISelectionProvider interface Adds support for ISelectionItemProvider interface Adds support for accessibilityState:selected Adjusts AccessibilityState native type on Windows to be std::optional instead of bool Adjusts AccessibilityState native type on Windows to include multiselectable and required fields of type std::optional Adds multiselectable and required fields to AccessibilityState type in JS with type boolean | undefined Adds support for aria-multiselectable and aria-required. Adds support for the following accessibilityActions: addToSelection, removeFromSelection, select Fixes crash in AccessibilityInsights. * [Fabric] Implement IRangeValueProvider and Adjust IValueProvider Implementation (#14212) * IRangeValue Provider * Adjust ReadOnly to Use Prop Value * Complete IRangeValueProvider Implementation * Change files * Update Snapshots * Rework modal to be implemented entirely using public APIs (#14256) * Rework modal implementation to use public APIs * shutdown fix * Change files * format * remove dead code * format * fixes * fix * UIA tree for root component should be kept distinct from main UIA tree * input offset fix for sub rootviews * Split modal into two componentview's so that we dont have multiple roots in our componentview tree * format * Ensure rootview removes itself from the island, before a new one adds itself on instance reload * defork some modal test pages * remove override * fix * fix * snapshots --------- Co-authored-by: Chiara Mooney <[email protected]>
1 parent 0f9d266 commit 68fb4fd

File tree

82 files changed

+8329
-1094
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+8329
-1094
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": "Implement ISelectionProvider and ISelectionItemProvider",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "IRangeValue Provider",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Rework modal implementation to use public APIs",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/tester/overrides.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727
"type": "platform",
2828
"file": "src/js/examples/HTTP/HTTPExampleMultiPartFormData.js"
2929
},
30-
{
31-
"type": "patch",
32-
"file": "src/js/examples/Modal/ModalOnShow.windows.js",
33-
"baseFile": "packages/rn-tester/js/examples/Modal/ModalOnShow.js",
34-
"baseHash": "5098723f16d232ef3c5971a6f153522f42f87f61"
35-
},
3630
{
3731
"type": "patch",
3832
"file": "src/js/examples/Modal/ModalPresentation.windows.js",

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

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -312,33 +312,40 @@ class AccessibilityStateExamples extends React.Component {
312312
The following list of TouchableHighlights toggles
313313
accessibilityState.selected when touched:
314314
</Text>
315-
<FlatList
316-
accessibilityLabel="List of selectable items"
317-
data={selectableItems}
318-
renderItem={item => (
319-
<TouchableHighlight
320-
style={{
321-
width: 100,
322-
height: 50,
323-
backgroundColor: this.state.itemsSelected[item.index]
324-
? 'gray'
325-
: 'lightskyblue',
326-
}}
327-
accessibilityRole="button"
328-
accessibilityLabel={'Selectable item ' + (item.index + 1)}
329-
accessibilityState={{
330-
selected: this.state.itemsSelected[item.index],
331-
}}
332-
onPress={() => this.selectPress(item.index)}>
333-
<Text>
334-
{this.state.itemsSelected[item.index]
335-
? 'Selected'
336-
: 'Unselected'}
337-
</Text>
338-
</TouchableHighlight>
339-
)}
340-
keyExtractor={(item, index) => index.toString()}
341-
/>
315+
<View
316+
accessible
317+
accessibilityLabel="Selection Container"
318+
accessibilityState={{multiselectable: true, required: true}}
319+
testID="selection-container">
320+
<FlatList
321+
accessibilityLabel="List of selectable items"
322+
data={selectableItems}
323+
renderItem={item => (
324+
<TouchableHighlight
325+
style={{
326+
width: 100,
327+
height: 50,
328+
backgroundColor: this.state.itemsSelected[item.index]
329+
? 'gray'
330+
: 'lightskyblue',
331+
}}
332+
accessibilityRole="button"
333+
accessibilityLabel={'Selectable item ' + (item.index + 1)}
334+
testID={'Selectable item ' + (item.index + 1)}
335+
accessibilityState={{
336+
selected: this.state.itemsSelected[item.index],
337+
}}
338+
onPress={() => this.selectPress(item.index)}>
339+
<Text>
340+
{this.state.itemsSelected[item.index]
341+
? 'Selected'
342+
: 'Unselected'}
343+
</Text>
344+
</TouchableHighlight>
345+
)}
346+
keyExtractor={(item, index) => index.toString()}
347+
/>
348+
</View>
342349
<Text>
343350
The following TouchableHighlight cycles accessibilityState.checked
344351
through unchecked/checked/mixed for the View under it:
@@ -429,7 +436,8 @@ class AccessibilityStateExamples extends React.Component {
429436
</Text>
430437
<TouchableHighlight
431438
style={{width: 100, height: 50, backgroundColor: 'blue'}}
432-
onPress={this.rangePress}>
439+
onPress={this.rangePress}
440+
testID="accessibilityValue-increment">
433441
<Text>Range value increment</Text>
434442
</TouchableHighlight>
435443
<View
@@ -444,7 +452,9 @@ class AccessibilityStateExamples extends React.Component {
444452
min: this.state.viewRangeMin,
445453
max: this.state.viewRangeMax,
446454
now: this.state.viewRangeNow,
447-
}}>
455+
}}
456+
testID="accessibilityValue-number"
457+
accessibilityState={{readOnly: true}}>
448458
<Text>
449459
The View's (accessibilityRole == adjustable, ie. Slider) properties
450460
should be the following according to UIA: Min-{' '}
@@ -465,7 +475,10 @@ class AccessibilityStateExamples extends React.Component {
465475
accessibilityValue={{
466476
text: this.state.viewValueText,
467477
}}
468-
accessibilityRole="combobox">
478+
accessibilityRole="combobox"
479+
testID="accessibilityValue-text"
480+
accessible
481+
aria-readonly>
469482
<Text>
470483
The View's properties should be the following according to UIA:
471484
Text- {this.state.viewValueText}

packages/@react-native-windows/tester/src/js/examples/Modal/ModalOnShow.windows.js

Lines changed: 0 additions & 149 deletions
This file was deleted.

packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,9 @@ const styles = StyleSheet.create({
293293
marginTop: 6,
294294
},
295295
modalContainer: {
296-
// [Windows
297-
width: 500,
298-
height: 500,
299-
// flex: 1,
300-
// justifyContent: 'center',
301-
// padding: 20,
302-
// Windows ]
296+
flex: 1,
297+
justifyContent: 'center',
298+
padding: 20,
303299
},
304300
modalInnerContainer: {
305301
borderRadius: 10,
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
* Licensed under the MIT License.
4+
*
5+
* @format
6+
*/
7+
8+
import {dumpVisualTree} from '@react-native-windows/automation-commands';
9+
import {goToApiExample} from './RNTesterNavigation';
10+
import {app} from '@react-native-windows/automation';
11+
import {verifyNoErrorLogs} from './Helpers';
12+
13+
beforeAll(async () => {
14+
// If window is partially offscreen, tests will fail to click on certain elements
15+
await app.setWindowPosition(0, 0);
16+
await app.setWindowSize(1000, 1250);
17+
await goToApiExample('Accessibility Windows');
18+
});
19+
20+
afterEach(async () => {
21+
await verifyNoErrorLogs();
22+
});
23+
24+
const searchBox = async (input: string) => {
25+
const searchBox = await app.findElementByTestID('example_search');
26+
await app.waitUntil(
27+
async () => {
28+
await searchBox.setValue(input);
29+
return (await searchBox.getText()) === input;
30+
},
31+
{
32+
interval: 1500,
33+
timeout: 5000,
34+
timeoutMsg: `Unable to enter correct search text into test searchbox.`,
35+
},
36+
);
37+
};
38+
39+
describe('Accessibility Tests', () => {
40+
test('Elements can set accessibilityState:selected to false', async () => {
41+
await searchBox('Sta');
42+
const component = await app.findElementByTestID('Selectable item 1');
43+
await component.waitForDisplayed({timeout: 5000});
44+
const dump = await dumpVisualTree('Selectable item 1');
45+
expect(dump).toMatchSnapshot();
46+
});
47+
test('Elements can set accessibilityState:selected to true', async () => {
48+
await searchBox('Sta');
49+
const component = await app.findElementByTestID('Selectable item 1');
50+
await component.waitForDisplayed({timeout: 5000});
51+
await component.click();
52+
const dump = await dumpVisualTree('Selectable item 1');
53+
expect(dump).toMatchSnapshot();
54+
});
55+
test('Selectable items must have a Selection Container. Elements can set accessibilityState:multiselectable and accessibilityState:required to true', async () => {
56+
await searchBox('Sta');
57+
const componentsTab = await app.findElementByTestID('selection-container');
58+
await componentsTab.waitForDisplayed({timeout: 5000});
59+
const dump = await dumpVisualTree('selection-container');
60+
expect(dump).toMatchSnapshot();
61+
});
62+
test('Components can store range data by setting the min, max, and now of accessibilityValue', async () => {
63+
await searchBox('Sta');
64+
const componentsTab = await app.findElementByTestID(
65+
'accessibilityValue-number',
66+
);
67+
await componentsTab.waitForDisplayed({timeout: 5000});
68+
const dump = await dumpVisualTree('accessibilityValue-number');
69+
expect(dump).toMatchSnapshot();
70+
});
71+
test('Components can store value data by setting the text of accessibilityValue', async () => {
72+
await searchBox('Sta');
73+
const componentsTab = await app.findElementByTestID(
74+
'accessibilityValue-text',
75+
);
76+
await componentsTab.waitForDisplayed({timeout: 5000});
77+
const dump = await dumpVisualTree('accessibilityValue-text');
78+
expect(dump).toMatchSnapshot();
79+
});
80+
});

0 commit comments

Comments
 (0)