diff --git a/reviewboard/static/rb/css/pages/diffviewer.less b/reviewboard/static/rb/css/pages/diffviewer.less
index 7b8bfe51c6f4d6edb5f6d30fd051850b3dc17311..320db1b2474453695d2644847f0e9d4caef84413 100644
--- a/reviewboard/static/rb/css/pages/diffviewer.less
+++ b/reviewboard/static/rb/css/pages/diffviewer.less
@@ -585,6 +585,24 @@
   }
 }
 
+.diff-banner {
+  padding-bottom: 4em;
+
+  .banner {
+    background: #FEFADF;
+    border-color: #9E9A7F;
+    border-left: 0;
+    border-right: 0;
+    border-top: 0;
+    margin-bottom: 0px;
+    box-shadow: @box-shadow;
+    left: 0;
+    position: fixed;
+    width: 100%;
+    z-index: @z-index-banner;
+  }
+}
+
 #diffs {
   list-style: none;
   margin: 0;
@@ -625,6 +643,7 @@
 }
 
 #diff_index,
+#diff_banner_index,
 .diff-index {
   @icon-size: 20px;
   @icon-offset: 2px;
@@ -729,7 +748,8 @@
 /****************************************************************************
  * Diff information
  ****************************************************************************/
-#diff-details {
+#diff-details,
+#diff-banner-details {
   border-spacing: 8px;
 
   &.loading {
diff --git a/reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js b/reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
new file mode 100644
index 0000000000000000000000000000000000000000..70e5b49e193f7bcb90a6c580bbbbad1ff53144a6
--- /dev/null
+++ b/reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
@@ -0,0 +1,28 @@
+/*
+ * A model with all the data for the DiffFileIndexView
+ */
+RB.DiffFileIndex = Backbone.Model.Extend({
+
+    //needs to contain the state on what diffs are loading / already there
+
+    defaults: {
+        targetView: null,      //banner or review-request-body
+        isLoading: null,
+        isFileDeleted: null,
+        isFileAdded: null,
+        diffReviewable: null,  //diffReviewable view
+    },
+
+    /*
+     * Parse the data given to us by the server.
+     */
+    parse: function(rsp) {
+        return {
+            targetView: rsp.target_view,
+            isLoading: rsp.is_loading,
+            isFileDeleted: rsp.is_file_deleted,
+            isFileAdded: rsp.is_file_added,
+            diffReviewable: rsp.diff_reviewable,
+        };
+    },
+});
\ No newline at end of file
diff --git a/reviewboard/static/rb/js/pages/views/diffViewerPageView.js b/reviewboard/static/rb/js/pages/views/diffViewerPageView.js
index 99464ac742c3ce68036580599780381f94244302..6a045f8eda1201d04557b4e4ede27daf7ff0c1a3 100644
--- a/reviewboard/static/rb/js/pages/views/diffViewerPageView.js
+++ b/reviewboard/static/rb/js/pages/views/diffViewerPageView.js
@@ -50,6 +50,7 @@ RB.DiffViewerPageView = RB.ReviewablePageView.extend({
         this._diffReviewableViews = [];
         this._diffFileIndexView = null;
         this._highlightedChunk = null;
+        this._floatingBannerView = null;
 
         this.listenTo(this.model.get('files'), 'update', this._setFiles);
 
@@ -215,7 +216,18 @@ RB.DiffViewerPageView = RB.ReviewablePageView.extend({
         this._chunkHighlighter = new RB.ChunkHighlighterView();
         this._chunkHighlighter.render().$el.prependTo($diffs);
 
+        this._floatingBannerView = new RB.FloatingBannerView({
+            el: $('.diff-banner').find('.banner'),
+            collection: this.model.get('files'),
+            $floatContainer: $diffs,
+            $numDiffs: numDiffs,
+            $revisionModel: revisionModel,
+            $diffFileIndexView: this._diffFileIndexView
+        });
+        this._floatingBannerView.render().$el.prependTo($('.diff-banner'));
+
         $('#diff-details').removeClass('loading');
+        $('#diff-banner-details').removeClass('loading');
 
         return this;
     },
diff --git a/reviewboard/static/rb/js/views/floatingBannerView.js b/reviewboard/static/rb/js/views/floatingBannerView.js
index e96f2f880a4a94beefe8614ae0837f9c60e0decb..7d02aed4556cd49c01d3adb06221d9b7697897b0 100644
--- a/reviewboard/static/rb/js/views/floatingBannerView.js
+++ b/reviewboard/static/rb/js/views/floatingBannerView.js
@@ -12,6 +12,10 @@ RB.FloatingBannerView = Backbone.View.extend({
     initialize: function() {
         this._$floatSpacer = null;
 
+        this._diffFileIndexView = null;
+
+        this.collection = this.options.collection;
+
         _.bindAll(this, '_updateFloatPosition', '_updateSize');
     },
 
@@ -19,6 +23,28 @@ RB.FloatingBannerView = Backbone.View.extend({
      * Renders the banner and listens for scroll and resize updates.
      */
     render: function() {
+        $numDiffs = this.options.$numDiffs;
+        $revisionModel = this.options.$revisionModel;
+
+        this._diffFileIndexView = new RB.DiffFileIndexView({
+            el: $('#diff_banner_index'),
+            collection: this.collection,
+        });
+        this._diffFileIndexView.render();
+        this.listenTo(this._diffFileIndexView, 'anchorClicked',
+                      this._onAnchorClicked);
+
+        if ($numDiffs > 1) {
+            this._diffRevisionSelectorView = new RB.DiffRevisionSelectorView({
+                el: $('#diff_banner_revision_selector'),
+                model: $revisionModel,
+                numDiffs: $numDiffs
+            });
+            this._diffRevisionSelectorView.render();
+            this.listenTo(this._diffRevisionSelectorView, 'revisionSelected',
+                          this._onRevisionSelected);
+        }
+
         $(window)
             .scroll(this._updateFloatPosition)
             .resize(this._updateSize);
@@ -136,5 +162,14 @@ RB.FloatingBannerView = Backbone.View.extend({
                 .height('auto')
                 .css('margin', 0);
         }
+    },
+
+    /*
+     * Handler for when the navigate button is clicked.
+     *
+     * Navigates to the selected file.
+     */
+    _onAnchorClicked: function _onAnchorClicked(index) {
+        $('html, body').scrollTop($("a[name='" + index + "']").offset().top);
     }
 });
diff --git a/reviewboard/templates/diffviewer/view_diff.html b/reviewboard/templates/diffviewer/view_diff.html
index 4dfb5dbe2afe4b70ad3013786c43bbb63c25bfe3..4c92c0480dc4bd8c189e49c590390e4471e827b9 100644
--- a/reviewboard/templates/diffviewer/view_diff.html
+++ b/reviewboard/templates/diffviewer/view_diff.html
@@ -61,6 +61,18 @@
  <li  class="ws" style="display:none;"><a href="#" class="toggle-whitespace-only-chunks"><span class="fa fa-plus"></span> {% trans "Show whitespace changes" %}</a></li>
 </ul>
 
+<div class="diff-banner">
+ <div class="banner">
+  <div id="diff-banner-details" class="loading">
+   <a name="index_header"></a>
+   <div id="diff_banner_revision_label"></div>
+   <div id="diff_banner_revision_selector"></div>
+   <div id="diff_banner_comments_hint"></div>
+   <div id="diff_banner_index"></div>
+  </div>
+  <div id="dropdown_button" class="btn drop-down-btn">&#9662;</div>
+ </div>
+</div>
 <div id="diffs"></div>
 <div id="pagination2"></div>
 
