#15 Main Navigation (Mobile Menu)
Saturday, January 26, 2019
In this article we will set up our mobile navigation menu. In addition to adding the markup and styling our approach will require the first use of javascript within our main navigation component to animate the mobile menu in and out based on user interaction.
Parts
- Part 29: Offset Pager Urls
- Part 28: Offset Pager Start
- Part 27: Mock Context Builder
- Part 26: Mock Repository
- Part 25: Mock Async
- Part 24: Picture Tag Helper
- Part 23: Img DPR Tag Helper
- Part 22: Img Responsive Tag Helper
- Part 21: Img Optimized Display
- Part 20: Img Optimization
- Part 19: Img Lazy Loading
- Part 18: Img Responsive
- Part 17: Bottom Nav
- Part 16: Main Nav Cookie
- Part 15: Main Nav Mobile
- Part 14: Main Nav Search
- Part 13: Main Nav Auth
- Part 12: Main Nav Anchors
- Part 11: Main Nav Logo
- Part 10: Search Results
- Part 9: Search Manager
- Part 8: Search Start
- Part 7: Seeding the Database
- Part 6: Domain Database
- Part 5: Emailing Exceptions
- Part 4: Mailkit
- Part 3: View Renderer
- Part 2: Upgrade to 2.1
- Part 1: Quick Start
The Markup
- WebUi
- Pages
- Shared
- _MainNav.cshtml
- Shared
- Pages
Since we have already done the hard work in a previous article we can add the markup for our mobile navigation very easily (a).
_MainNav.cshtml
...
@{
...
var Logout = Html.Raw(Li($"..."));
}
<header>
<nav ...>
...
</nav>
<div class="mobile-menu" id="mobile-menu">
<ul>
@Articles
@Applications
@Videos
<li>
<hr class="separator" />
</li>
@if (isAuthenticated)
{
@Account
@Logout
}
else
{
@Register
@Login
}
</ul>
</div>
</header>
The Styling
- WebUi
- Source
- components
- main-nav
- main-nav.component.scss
- main-nav
- components
- Source
With the markup in place we can turn to adding some styling (b).
main-nav.component.scss
...
@mixin logoutBtn {
button {
background: none;
border: none;
color: $navigation-anchor-color;
height: 100%;
@include padding(null em(10px) null em(10px));
cursor: pointer;
font-weight: 400;
&:hover {
background: none;
color: $action-color;
}
}
}
header {
...
.link-icon {
margin-right: 0.25em;
}
.authentication {
...
form {
...
@include logoutBtn;
}
}
...
.mobile-menu {
background-color: $navigation-background-color;
position: absolute;
z-index: 0;
width: 100%;
transform: translateY(-101%);
@include media-gt($mobile-break-width) {
display: none;
}
ul {
flex-direction: column;
border-color: $navigation-border-color;
border-style: solid;
@include border-width(0 0 1px 0);
}
a {
justify-content: center;
}
a, form {
@include padding(em(15px) null);
}
.separator {
width: 100%;
color: $navigation-border-color;
@include margin(0.5em 0);
}
@include logoutBtn;
.link {
text-align: center;
}
}
}
Interactions
- WebUi
- Source
- components
- main-nav
- main-nav.component.ts
- main-nav
- components
- Source
Of course our menu would be basically useless at is right now since by default it starts out above the viewable area of our page. We will use javascript to animate the menu in and out in response to user interaction with our mobile menu button (c).
main-nav.component.ts
const animationOptions = {
direction: "normal",
duration: 250,
easing: "ease-in-out",
fill: "forwards"
};
function animateOut(element: HTMLElement) {
(element as any).animate(
{
transform: ["translateY(0)", "translateY(-101%)"]
},
animationOptions);
return false;
}
function animateIn(element: HTMLElement) {
(element as any).animate(
{
transform: ["translateY(-101%)", "translateY(0)"]
},
animationOptions);
return true;
}
let isMobileMenuOpen = false;
const mobileMenu = document.getElementById("mobile-menu");
document.getElementById("mobile-toggle").addEventListener("click", (e) => {
e.preventDefault();
const animate = isMobileMenuOpen
? animateOut
: animateIn;
isMobileMenuOpen = animate(mobileMenu);
});
export default function() { return true; }
Adding the javascript code to our page
- WebUi
- Source
- main.page.ts
- Source
With the code written for user interaction with our mobile menu the only thing left to do is to add the code to our main bundle by importing it into our main typescript file (d).
main.page.ts
...
import("./components/main-nav/main-nav.component");