Alternative Mobile Menu (SAP Design Studio)
Hello SAP Community!
I recently set out to create a simple mobile menu when I realized that the SAP BI iOS app poses a UX problem:
as default, the standard menu icon gets covered by the BI app’s full screen icon!
Of course, you could tell users to minimize the view, but why put an extra click between the user and the desired view?
After seeing, the flaw in the BI app’s design, I set out to create an alternative.
DOWNLOAD
Demo: iOS // iPad // Desktop
Steps
1. Create application structure
2 Icon components at top-right
2 Icon components at bottom-left
Panel component (off-screen)
We’re also going to add the following to ‘CSS Style’ property of PANEL_FXN:
opacity: 0;
background-color: #2c3034;
box-shadow: -10px 0 30px 0 rgba(0, 0, 0, 0.2);
2 Icon components at bottom-left of PANEL_FXN
2. Create External CSS
Note: media queries are what allow for the seamless transition from desktop buttons at top-right to mobile floating action buttons at the bottom-left.
Paste the following into your Design Studio application’s external stylesheet.
/***************************************
* Mobile Menu Template
* written by Pratham Mohapatra
* >> http://prath.co
***************************************/
body {
overflow-x: hidden !important;
}
* {
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
}
.hdr {
background-color: rgba(0, 0, 0, 0.1) !important;
line-height: 50px;
font-size: 1.6em;
font-family: "Calibri Light", "Calibri", Arial, sans-serif;
text-align: center;
color: #fff;
}
/********************************************
Animation
********************************************/
.SLIDE-RIGHT {
-webkit-animation: slide-right .8s ease-in forwards ;
animation: slide-right .8s ease-in forwards ;
}
@-webkit-keyframes slide-right {
0%{
-webkit-transform: translateX(-300px);
transform: translateX(-300px);
opacity: 1;
}
100%{
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 0;
}
}
@keyframes slide-right {
0%{
transform: translateX(-300px);
opacity: 1;
}
100%{
transform: translateX(0);
opacity: 0;
}
}
.SLIDE-LEFT {
-webkit-animation: slide-left .8s ease-in forwards ;
animation: slide-left .8s ease-in forwards ;
}
@-webkit-keyframes slide-left {
0%{
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 0;
}
100%{
-webkit-transform: translateX(-300px);
transform: translateX(-300px);
display: none !important;
opacity: 1;
}
}
@keyframes slide-left {
0%{
transform: translateX(0);
opacity: 0;
}
100%{
transform: translateX(-300px);
display: none !important;
opacity: 1;
}
}
/*********************************************
Media Queries - START
*********************************************/
/********* XL *********/
@media screen and (min-width: 1601px) {
.fab-x {
display: block;
}
.fab-m {
display: none;
}
}
/**************************/
/********* Desktop *********/
@media screen and (max-width: 1601px) {
.fab-x {
display: block;
}
.fab-m {
display: none;
}
}
/**************************/
/********* Tablet *********/
@media screen and (max-width: 1024px) {
.fab-x {
display: none;
}
.fab-m {
display: block;
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.5);
}
}
/**************************/
/********* Mobile *********/
@media screen and (max-width: 480px) {
.fab-x {
display: none;
}
.fab-m {
display: block;
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.5);
}
}
/*********************************************
Media Queries - END
*********************************************/
/***************************************
* Mobile Menu Template
* written by Pratham Mohapatra
* >> http://prath.co
***************************************/
3. Create Global Functions
a. create Global function showFab()
Create input parameter st (type: boolean) and paste the following:
[F_MENU, F_FILT, FM_MENU, FM_FILT].forEach(function(element, index) {
element.setVisible(st);
});
b. create Global function toggleMenu()
Create input parameter icon (type: Icon) and paste the following:
if (PANEL_FXN.getCSSClass() !== "SLIDE-LEFT") {
PANEL_FXN.setCSSClass("SLIDE-LEFT");
GLOBAL.showFab(false);
}
else {
PANEL_FXN.setCSSClass("SLIDE-RIGHT");
GLOBAL.showFab(true);
}
4. Bind Global functions to all relevant icons
Note: ‘this’ keyword tells the toggleMenu() function to pass the icon component that is clicked on.
Paste the following BIAL script On Click event for all relevant icons:
GLOBAL.toggleMenu(this);
5. Execute the application and preview
iPhone:
iPad:

Desktop:
I hope you found this helpful. Thanks for reading!
SAP Consultant and Full-Stack Developer
Hi Pratham,
I have come across this issue too so it's good to see an example of a solution to resolve it. I have some questions and suggestions as follows:
1. My understanding is that the solution presented simply places the menu icon in an alternative screen location that is not obscured by the full screen icon. I can see how this works for the iPhone example, where the icon is placed in the page footer. However, I'm not sure how the issue is resolved on the iPad because in the screenshot above the menu icon is in the header on the right corner, which is where the fullscreen icon overlaps with it. Can you clarify?
2. It would be useful if you adapted your solution (as needed) to be based on the Blue Crystal theme because the Mobile theme is being deprecated going forward and is not available with the SAP UI5 M Mode rendering option which is the only rendering mode which will be supported in future.
Regards,
Mustafa.
Hi Mustafa,
Thanks for reading my blog. To answer your questions,
1. I agree completely regarding the iPad issue. I will be editing this post shortly with an appropriate solution.
2. I was unaware of the Mobile theme being deprecated. Could you provide an official resource for this? I could see the size of components such as drop-downs presenting a mobile UX issue.
I appreciate your interest in this solution and will post a reply here once the improvements have been made.
Thanks,
Pratham
Hello All,
any update on this? I have a similar requirement and would like to know what is the best practice to achieve this.
Thanks
Basile