Ember.js Mobile: Responsive Swipe/Push Menu Navigation

Live Demo |



Github Repo

Facebook-style left-swipe menu navs are pretty common in native apps these days and I wanted to quickly run through one approach to achieve this with responsive CSS and ember swipe gestures.

I looked around at different CSS approaches and ended up choosing one similar to Mary Lou’s approach in this great article.

Let’s get started, shall we?

First, create a menu in our application.emblem template

.menu h3 Push Menu = outlet

…and hide it left of the main screen with css in our custom.css stylesheet (width: 60%, position left:-60%).

.menu { width:60%;

left: -60%; position: fixed; height:100%; background-color: #47a3da; padding: 0px; box-shadow: -3px 3px 3px #ddd; }

Now add a button that when clicked will pop open the menu in our posts_index.emblem template by toggling a toggleMenu function in the application route events hook.

header.navbar a.navbar-brand AnimGest button.btn.btn-link click="toggleMenu" i.icon-reorder.icon-xlarge

The toggleMenu function toggles a menuVisible boolean property on the application controller that defaults to false.

App.ApplicationRoute = Em.Route.extend({ events: { toggleMenu: function() { this.controller.toggleProperty('menuVisible'); } });

App.ApplicationController = Em.Controller.extend({ menuVisible: false });

Let’s add a bindAttr dynamic class property on the menu that will add a menu.visible class when menuVisible on the controller is set to true.

.menu class=controller.menuVisible:visible h3Push Menu

.menu.visible { left: 0px; } .menu, body { -webkit-transition: all 0.3s ease; -moz-transition: all 0.3s ease; transition: all 0.3s ease; }

Sweet, we have a menu that pops out when a nav button is clicked!

Now, let’s add a few menu items to our application.emblem and to push the document body to the right at the same time.

.menu class=controller.menuVisible:visible h3 Push Menu ul.nav.affix-top style="margin-top:50px;" li.menu-text click="goToPostsFromMenu" a Posts li.menu-text click="goToRealTimeGraph" a Real Time Graph = outlet

App.ApplicationRoute = Em.Route.extend({ events: { toggleMenu: function() { this.controller.toggleProperty('menuVisible'); this.controller.pushBody(); }, goToPostsFromMenu: function() { this.send('toggleMenu'); this.transitionTo('posts.index'); }, goToRealTimeGraph: function() { this.send('toggleMenu'); this.transitionTo('realTimeGraph'); } });

App.ApplicationController = Em.Controller.extend({ menuVisible: false, pushBody: function() { if (this.get('menuVisible')){ return $('.ember-application').addClass('push-right'); } $('body').removeClass('push-right'); } });

push-right { left: 60%; } body { overflow-x: hidden; position: relative; left: 0; }

Awesome, we have a fully functioning push menu! For the cherry on top, we just have to add the swipe gestures:

App.PostsIndexView = Ember.View.extend({ templateName: 'posts_index', swipeOptions: { direction: Em.OneGestureDirection.Left | Em.OneGestureDirection.Right, cancelPeriod: 100, swipeThreshold: 10 }, touchMove: function(event) { event.preventDefault(); }, swipeEnd: function(recognizer, evt) { var direction = recognizer.get('swipeDirection'); if (direction === Em.OneGestureDirection.Right) { this.get('controller').send('goToPostsFromMenu'); } else if (direction === Em.OneGestureDirection.Left) { this.get('controller').send('toggleMenu'); } } });

And finally, we are done! Go grab a drink and have some fun!

(*Note: We took a bit of a different approach to pushing the body [than making the menu visible] for the sake of illustration.)