Skip to content

Commit 0bdfb20

Browse files
authored
Support drawer menus opening as overlay instead of pushing content in ios (#7986)
1 parent d3d6961 commit 0bdfb20

16 files changed

+1044
-226
lines changed

e2e/SetRoot.test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,14 @@ describe('SetRoot', () => {
5151
await elementById(TestIDs.OK_BUTTON).tap();
5252
});
5353
});
54+
55+
it.e2e(':ios: set root with left and right side menus - menu visibility', async () => {
56+
await elementById(TestIDs.SET_ROOT_WITH_MENUS).tap();
57+
await elementById(TestIDs.TOGGLE_SIDE_MENU_OPEN_MODE_BTN).tap();
58+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
59+
await elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN).tap();
60+
await expect(elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN)).toBeNotVisible();
61+
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
62+
await elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN).tap();
63+
await expect(elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN)).toBeNotVisible();
64+
});

e2e/SideMenu.test.js

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,91 @@
11
import Utils from './Utils';
22
import TestIDs from '../playground/src/testIDs';
33

4-
const { elementByLabel, elementById } = Utils;
4+
const {elementByLabel, elementById, expectImagesToBeEqual} = Utils;
55

6-
describe('SideMenu', () => {
6+
describe.each(['aboveContent', 'pushContent'])('SideMenu', (openMode) => {
77
beforeEach(async () => {
8-
await device.launchApp({ newInstance: true });
8+
await device.launchApp({newInstance: true});
99
await elementById(TestIDs.SIDE_MENU_BTN).tap();
10-
});
1110

12-
it('close SideMenu and push to stack with static id', async () => {
13-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
14-
await elementById(TestIDs.LEFT_SIDE_MENU_PUSH_BTN).tap();
15-
await elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN).tap();
16-
await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeVisible();
17-
await elementById(TestIDs.POP_BTN).tap();
18-
await expect(elementById(TestIDs.CENTER_SCREEN_HEADER)).toBeVisible();
11+
if (openMode === 'aboveContent') {
12+
await elementById(TestIDs.TOGGLE_SIDE_MENU_OPEN_MODE_BTN).tap();
13+
}
1914
});
2015

21-
it('Push to stack with static id and close SideMenu with screen options', async () => {
22-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
23-
await elementById(TestIDs.LEFT_SIDE_MENU_PUSH_AND_CLOSE_BTN).tap();
24-
await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeVisible();
25-
await elementById(TestIDs.POP_BTN).tap();
26-
await expect(elementById(TestIDs.CENTER_SCREEN_HEADER)).toBeVisible();
27-
});
16+
describe(`Open mode '${openMode}'`, () => {
17+
it('close SideMenu and push to stack with static id', async () => {
18+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
19+
await elementById(TestIDs.LEFT_SIDE_MENU_PUSH_BTN).tap();
20+
await elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN).tap();
21+
await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeVisible();
22+
await elementById(TestIDs.POP_BTN).tap();
23+
await expect(elementById(TestIDs.CENTER_SCREEN_HEADER)).toBeVisible();
24+
});
2825

29-
it('side menu visibility - left', async () => {
30-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
31-
await elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN).tap();
32-
await expect(elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN)).toBeNotVisible();
33-
});
26+
it('Push to stack with static id and close SideMenu with screen options', async () => {
27+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
28+
await elementById(TestIDs.LEFT_SIDE_MENU_PUSH_AND_CLOSE_BTN).tap();
29+
await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeVisible();
30+
await elementById(TestIDs.POP_BTN).tap();
31+
await expect(elementById(TestIDs.CENTER_SCREEN_HEADER)).toBeVisible();
32+
});
3433

35-
it('side menu visibility - right', async () => {
36-
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
37-
await elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN).tap();
38-
await expect(elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN)).toBeNotVisible();
39-
});
34+
it('side menu visibility - left', async () => {
35+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
36+
await elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN).tap();
37+
await expect(elementById(TestIDs.CLOSE_LEFT_SIDE_MENU_BTN)).toBeNotVisible();
38+
});
4039

41-
it.e2e('should rotate', async () => {
42-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
43-
await device.setOrientation('landscape');
44-
await expect(elementById(TestIDs.LEFT_SIDE_MENU_PUSH_BTN)).toBeVisible();
45-
});
40+
it('side menu visibility - right', async () => {
41+
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
42+
await elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN).tap();
43+
await expect(elementById(TestIDs.CLOSE_RIGHT_SIDE_MENU_BTN)).toBeNotVisible();
44+
});
4645

47-
it.e2e(':ios: rotation should update drawer height', async () => {
48-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
49-
await expect(elementByLabel('left drawer height: 869')).toBeVisible();
50-
await device.setOrientation('landscape');
51-
await expect(elementByLabel('left drawer height: 428')).toBeVisible();
52-
await device.setOrientation('portrait');
53-
await expect(elementByLabel('left drawer height: 869')).toBeVisible();
54-
});
46+
it.e2e('should rotate', async () => {
47+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
48+
await device.setOrientation('landscape');
49+
await expect(elementById(TestIDs.LEFT_SIDE_MENU_PUSH_BTN)).toBeVisible();
50+
});
5551

56-
it.e2e('should set left drawer width', async () => {
57-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
58-
await expect(elementById(TestIDs.SIDE_MENU_LEFT_DRAWER_HEIGHT_TEXT)).toBeVisible();
59-
await expect(elementByLabel('left drawer width: 250')).toBeVisible();
60-
});
52+
it.e2e(':ios: rotation should update drawer height', async () => {
53+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
54+
await expect(elementByLabel('left drawer height: 869')).toBeVisible();
55+
await device.setOrientation('landscape');
56+
await expect(elementByLabel('left drawer height: 428')).toBeVisible();
57+
await device.setOrientation('portrait');
58+
await expect(elementByLabel('left drawer height: 869')).toBeVisible();
59+
});
6160

62-
it.e2e('should change left drawer width', async () => {
63-
await elementById(TestIDs.CHANGE_LEFT_SIDE_MENU_WIDTH_BTN).tap();
64-
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
65-
await expect(elementByLabel('left drawer width: 50')).toBeVisible();
66-
});
61+
it.e2e('should set left drawer width', async () => {
62+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
63+
await expect(elementById(TestIDs.SIDE_MENU_LEFT_DRAWER_HEIGHT_TEXT)).toBeVisible();
64+
await expect(elementByLabel('left drawer width: 250')).toBeVisible();
65+
});
6766

68-
it.e2e('should set right drawer width', async () => {
69-
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
70-
await expect(elementByLabel('right drawer width: 250')).toBeVisible();
71-
});
67+
it.e2e('should change left drawer width', async () => {
68+
await elementById(TestIDs.CHANGE_LEFT_SIDE_MENU_WIDTH_BTN).tap();
69+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
70+
await expect(elementByLabel('left drawer width: 50')).toBeVisible();
71+
});
72+
73+
it.e2e('should set right drawer width', async () => {
74+
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
75+
await expect(elementByLabel('right drawer width: 250')).toBeVisible();
76+
});
77+
78+
it.e2e('should change right drawer width', async () => {
79+
await elementById(TestIDs.CHANGE_RIGHT_SIDE_MENU_WIDTH_BTN).tap();
80+
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
81+
await expect(elementByLabel('right drawer width: 50')).toBeVisible();
82+
});
7283

73-
it.e2e('should change right drawer width', async () => {
74-
await elementById(TestIDs.CHANGE_RIGHT_SIDE_MENU_WIDTH_BTN).tap();
75-
await elementById(TestIDs.OPEN_RIGHT_SIDE_MENU_BTN).tap();
76-
await expect(elementByLabel('right drawer width: 50')).toBeVisible();
84+
it.e2e(':ios: should render side menu correctly', async () => {
85+
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
86+
const snapshottedImagePath = `./e2e/assets/side_menu.${openMode}.png`;
87+
const actual = await elementById('SideMenuContainer').takeScreenshot(`side_menu_${openMode}`);
88+
expectImagesToBeEqual(actual, snapshottedImagePath);
89+
});
7790
});
7891
});

e2e/assets/side_menu.aboveContent.png

150 KB
Loading

e2e/assets/side_menu.pushContent.png

160 KB
Loading

lib/ios/RNNSideMenu/MMDrawerController/MMDrawerController.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController *dra
127127

128128
@interface MMDrawerController : UIViewController
129129

130+
/**
131+
Enum defining how the drawer opens
132+
*/
133+
typedef NS_ENUM(NSInteger, MMDrawerOpenMode) {
134+
MMDrawerOpenModePushContent = 0, // Original behavior - pushes content aside
135+
MMDrawerOpenModeAboveContent = 1, // Overlay behavior - opens above content
136+
};
137+
130138
///---------------------------------------
131139
/// @name Accessing Drawer Container View Controller Properties
132140
///---------------------------------------
@@ -213,6 +221,18 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController *dra
213221
@property(nonatomic, assign) BOOL shouldStretchLeftDrawer;
214222
@property(nonatomic, assign) BOOL shouldStretchRightDrawer;
215223

224+
/**
225+
* Specifies how the drawer should open relative to the center content.
226+
*
227+
* Possible values:
228+
* - MMDrawerOpenModePushContent: The drawer will push the center content aside when opening (traditional behavior).
229+
* - MMDrawerOpenModeAboveContent: The drawer will open above the center content with a semi-transparent overlay.
230+
*
231+
* By default, this value is set to MMDrawerOpenModePushContent.
232+
*/
233+
@property(nonatomic, assign) MMDrawerOpenMode leftDrawerOpenMode;
234+
@property(nonatomic, assign) MMDrawerOpenMode rightDrawerOpenMode;
235+
216236
/**
217237
The current open side of the drawer.
218238
@@ -600,4 +620,6 @@ typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController *dra
600620
(BOOL (^)(MMDrawerController *drawerController, UIGestureRecognizer *gesture,
601621
UITouch *touch))gestureShouldRecognizeTouchBlock;
602622

623+
- (void)side:(MMDrawerSide)drawerSide openMode:(MMDrawerOpenMode)openMode;
624+
603625
@end

0 commit comments

Comments
 (0)