
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-22-2024 10:01 AM
I've been asked to redesign our Service Portal with a requirement to move the menu to a sidebar. Service Portal really doesn't seem to want to do that as the core page places header above body, The closest solution I have found (see below) is to set the sidebar position to absolute, and add left padding to the .body class to account for the width of the sidebar. While this works, it doesn't help with two other requirements:
- I'd like to add icons to the left of each menu item and have a toggle to let the user collapse the sidebar down to hide the menu text and just show the icons (kind of like the platform menu with UI16), which means the width of the sidebar will change.
- For mobile, the sidebar needs to be hidden completely, and toggled with a hamburger icon.
I also don't love having to use z-index to force the menu to show up, when it's technically beside the main page.
I looked at doing some things with javascript, but it doesn't look like anything at the root level of the main container has an ID...
.body {
padding-left: $chhi-menu-frame-width;
}
.menu-frame {
position: absolute;
z-index: 1000;
width: $chhi-menu-frame-width;
top: 64px;
height: calc(100vh - 64px);
background-color: $chhi-color-background-menu;
padding-left: $chhi-menu-pad-left;
padding-right: $chhi-menu-pad-right;
}
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
@Pavithra0812 - I did. It's a little hackey but it works great. You need to go to your theme and add some CSS and JS includes. For one thing, Bootstrap 5, which supports side menu, conflicts with the OOTB Bootstrap 3.5, particularly when it comes to modals - so you'll have to create some overrides.
CSS Includes (in order):
- https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
- Bootstrap Fixes (attached, as a local stylesheet)
- Menu Core CSS (attached, as a local stylesheet)
- Core CSS (attached, as a local stylesheet)
JS Include:
Then use some version of the attached Header CSS and Header HTML in your header widget. Note that I wanted the limited side menu to appear at all times, so had to get really creative with the body position and size.
You end up with what you see in the attached images.
Edit - for some reason the site doesn't like my Header HTML.txt. Here is the code:
<div class="portal-header">
<div class="my-table" class="menu-frame">
<div clas="my-table-row" class="menu-frame">
<div class="my-table-cell menu-item">
<a href="?">
<div class="my-table">
<div class="my-table-row">
<div class="my-table-cell portal-logo-text">
</div>
</div>
<div class="my-table-row">
<div class="my-table-cell portal-title-text">
{{::data.title}}
</div>
</div>
</div>
</a>
</div>
<div ng-if="data.isLoggedIn" class="my-table-cell menu-item hidden-xs hidden-sm" style="white-space:nowrap">
<sp-widget widget="data.prop_selector"></sp-widget>
</div>
<div ng-if="data.isLoggedIn" class="hidden-xs hidden-sm my-table-cell menu-item search-box">
<div class="hidden-xs hidden-sm" >
<sp-widget widget="data.typeAheadSearch" />
</div>
</div>
<div class="hidden-md hidden-lg hidden-xl my-table-cell" style="width: 100%">
</div>
<div class="my-table-cell menu-item">
<div class="hidden-xs" style="width: 40px; padding-right: 16px;">
<div class="header-loader" ng-show="loadingIndicator">
<div class="sp-loading-indicator la-sm">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function hide_title_attributes(el){
var t = el.querySelectorAll('[title]');
if(t && t.length > 0){
for(var n=0;n<t.length;++n){
var title=t[n].title;
t[n].removeAttribute('title');
t[n].setAttribute('aria-label',title);
}
}
}
hide_title_attributes(document.body);
document.body.onmouseover = function(e){
if(e.target.innerHTML.indexOf('title=')>-1){
hide_title_attributes(e.target);
}
else if(e.target.title){
var t=e.target.title;
e.target.removeAttribute('title');
e.target.setAttribute('aria-label',t);
}
}
</script>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-22-2024 10:43 AM
Hi @John Tomko,
I saw that NewRocket released a free update set that uses a sidebar menu. Maybe it will help.
https://serviceportal.io/creating-a-sidebar-menu-widget-for-employee-center/

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-24-2024 09:20 AM
Thanks Chris - I have seen that, and it's close. Their solution seems to float the sidebar above the main page, which gets around the issue I am having, but doesn't really support the menu being permanently next to the main page.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@John Tomko , Were you able to figure this out? We have a similar requirement and would greatly appreciate your input.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
@Pavithra0812 - I did. It's a little hackey but it works great. You need to go to your theme and add some CSS and JS includes. For one thing, Bootstrap 5, which supports side menu, conflicts with the OOTB Bootstrap 3.5, particularly when it comes to modals - so you'll have to create some overrides.
CSS Includes (in order):
- https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
- Bootstrap Fixes (attached, as a local stylesheet)
- Menu Core CSS (attached, as a local stylesheet)
- Core CSS (attached, as a local stylesheet)
JS Include:
Then use some version of the attached Header CSS and Header HTML in your header widget. Note that I wanted the limited side menu to appear at all times, so had to get really creative with the body position and size.
You end up with what you see in the attached images.
Edit - for some reason the site doesn't like my Header HTML.txt. Here is the code:
<div class="portal-header">
<div class="my-table" class="menu-frame">
<div clas="my-table-row" class="menu-frame">
<div class="my-table-cell menu-item">
<a href="?">
<div class="my-table">
<div class="my-table-row">
<div class="my-table-cell portal-logo-text">
</div>
</div>
<div class="my-table-row">
<div class="my-table-cell portal-title-text">
{{::data.title}}
</div>
</div>
</div>
</a>
</div>
<div ng-if="data.isLoggedIn" class="my-table-cell menu-item hidden-xs hidden-sm" style="white-space:nowrap">
<sp-widget widget="data.prop_selector"></sp-widget>
</div>
<div ng-if="data.isLoggedIn" class="hidden-xs hidden-sm my-table-cell menu-item search-box">
<div class="hidden-xs hidden-sm" >
<sp-widget widget="data.typeAheadSearch" />
</div>
</div>
<div class="hidden-md hidden-lg hidden-xl my-table-cell" style="width: 100%">
</div>
<div class="my-table-cell menu-item">
<div class="hidden-xs" style="width: 40px; padding-right: 16px;">
<div class="header-loader" ng-show="loadingIndicator">
<div class="sp-loading-indicator la-sm">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function hide_title_attributes(el){
var t = el.querySelectorAll('[title]');
if(t && t.length > 0){
for(var n=0;n<t.length;++n){
var title=t[n].title;
t[n].removeAttribute('title');
t[n].setAttribute('aria-label',title);
}
}
}
hide_title_attributes(document.body);
document.body.onmouseover = function(e){
if(e.target.innerHTML.indexOf('title=')>-1){
hide_title_attributes(e.target);
}
else if(e.target.title){
var t=e.target.title;
e.target.removeAttribute('title');
e.target.setAttribute('aria-label',t);
}
}
</script>