diff --git a/src/plugins/navigation-ui/README.md b/src/plugins/navigation-ui/README.md
new file mode 100644
index 0000000..0b30202
--- /dev/null
+++ b/src/plugins/navigation-ui/README.md
@@ -0,0 +1,13 @@
+Navigation UI plugin
+====================
+
+This plugin provides UI elements "back", "forward" and a list to select
+a specific slide number.
+
+The navigation controls are visible if the toolbar plugin is enabled. To add the toolbar to your
+presentations, [see toolbar plugin README](../toolbar/README.md).
+
+Author
+------
+
+Henrik Ingo (@henrikingo), 2016
diff --git a/src/plugins/navigation-ui/navigation-ui.js b/src/plugins/navigation-ui/navigation-ui.js
new file mode 100644
index 0000000..507e945
--- /dev/null
+++ b/src/plugins/navigation-ui/navigation-ui.js
@@ -0,0 +1,123 @@
+/**
+ * Navigation UI plugin
+ *
+ * This plugin provides UI elements "back", "forward" and a list to select
+ * a specific slide number.
+ *
+ * The navigation controls are added to the toolbar plugin via DOM events. User must enable the
+ * toolbar in a presentation to have them visible.
+ *
+ * Copyright 2016 Henrik Ingo (@henrikingo)
+ * Released under the MIT license.
+ */
+
+// This file contains so much HTML, that we will just respectfully disagree about js
+/* jshint quotmark:single */
+/* global document */
+
+( function( document ) {
+ 'use strict';
+ var toolbar;
+ var api;
+ var root;
+ var steps;
+ var hideSteps = [];
+ var prev;
+ var select;
+ var next;
+
+ var triggerEvent = function( el, eventName, detail ) {
+ var event = document.createEvent( 'CustomEvent' );
+ event.initCustomEvent( eventName, true, true, detail );
+ el.dispatchEvent( event );
+ };
+
+ var makeDomElement = function( html ) {
+ var tempDiv = document.createElement( 'div' );
+ tempDiv.innerHTML = html;
+ return tempDiv.firstChild;
+ };
+
+ var selectOptionsHtml = function() {
+ var options = '';
+ for ( var i = 0; i < steps.length; i++ ) {
+
+ // Omit steps that are listed as hidden from select widget
+ if ( hideSteps.indexOf( steps[ i ] ) < 0 ) {
+ options = options + '' + '\n'; // jshint ignore:line
+ }
+ }
+ return options;
+ };
+
+ var addNavigationControls = function( event ) {
+ api = event.detail.api;
+ var gc = api.lib.gc;
+ root = event.target;
+ steps = root.querySelectorAll( '.step' );
+
+ var prevHtml = '';
+ var selectHtml = '';
+ var nextHtml = '';
+
+ prev = makeDomElement( prevHtml );
+ prev.addEventListener( 'click',
+ function() {
+ api.prev();
+ } );
+ select = makeDomElement( selectHtml );
+ select.addEventListener( 'change',
+ function( event ) {
+ api.goto( event.target.value );
+ } );
+ gc.addEventListener( root, 'impress:steprefresh', function( event ) {
+
+ // As impress.js core now allows to dynamically edit the steps, including adding,
+ // removing, and reordering steps, we need to requery and redraw the select list on
+ // every stepenter event.
+ steps = root.querySelectorAll( '.step' );
+ select.innerHTML = '\n' + selectOptionsHtml();
+
+ // Make sure the list always shows the step we're actually on, even if it wasn't
+ // selected from the list
+ select.value = event.target.id;
+ } );
+ next = makeDomElement( nextHtml );
+ next.addEventListener( 'click',
+ function() {
+ api.next();
+ } );
+
+ triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: prev } );
+ triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: select } );
+ triggerEvent( toolbar, 'impress:toolbar:appendChild', { group: 0, element: next } );
+
+ };
+
+ // API for not listing given step in the select widget.
+ // For example, if you set class="skip" on some element, you may not want it to show up in the
+ // list either. Otoh we cannot assume that, or anything else, so steps that user wants omitted
+ // must be specifically added with this API call.
+ document.addEventListener( 'impress:navigation-ui:hideStep', function( event ) {
+ hideSteps.push( event.target );
+ if ( select ) {
+ select.innerHTML = selectOptionsHtml();
+ }
+ }, false );
+
+ // Wait for impress.js to be initialized
+ document.addEventListener( 'impress:init', function( event ) {
+ toolbar = document.querySelector( '#impress-toolbar' );
+ if ( toolbar ) {
+ addNavigationControls( event );
+ }
+ }, false );
+
+} )( document );
+