diff --git a/app/assets/javascripts/discourse/components/composer-editor.js.es6 b/app/assets/javascripts/discourse/components/composer-editor.js.es6
index 9dbd7f25d14..ddc86134cf6 100644
--- a/app/assets/javascripts/discourse/components/composer-editor.js.es6
+++ b/app/assets/javascripts/discourse/components/composer-editor.js.es6
@@ -5,7 +5,7 @@ import { linkSeenCategoryHashtags, fetchUnseenCategoryHashtags } from 'discourse
 
 export default Ember.Component.extend({
   classNames: ['wmd-controls'],
-  classNameBindings: [':wmd-controls', 'showPreview', 'showPreview::hide-preview'],
+  classNameBindings: ['showToolbar:toolbar-visible', ':wmd-controls', 'showPreview', 'showPreview::hide-preview'],
 
   uploadProgress: 0,
   showPreview: true,
@@ -343,12 +343,34 @@ export default Ember.Component.extend({
     },
 
     showOptions() {
+      // long term we want some smart positioning algorithm in popup-menu
+      // the problem is that positioning in a fixed panel is a nightmare
+      // cause offsetParent can end up returning a fixed element and then
+      // using offset() is not going to work, so you end up needing special logic
+      // especially since we allow for negative .top, provided there is room on screen
       const myPos = this.$().position();
       const buttonPos = this.$('.options').position();
 
+      const popupHeight = $('#reply-control .popup-menu').height();
+      const popupWidth = $('#reply-control .popup-menu').width();
+
+      var top = myPos.top + buttonPos.top - 15;
+      var left = myPos.left + buttonPos.left - (popupWidth/2);
+
+      const composerPos = $('#reply-control').position();
+
+      if (composerPos.top + top - popupHeight < 0) {
+        top = top + popupHeight + this.$('.options').height() + 50;
+      }
+
+      var replyWidth = $('#reply-control').width();
+      if (left + popupWidth > replyWidth) {
+        left = replyWidth - popupWidth - 40;
+      }
+
       this.sendAction('showOptions', { position: "absolute",
-                                       left: myPos.left + buttonPos.left,
-                                       top: myPos.top + buttonPos.top });
+                                       left: left,
+                                       top: top });
     },
 
     showUploadModal(toolbarEvent) {
diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6
index 5ebd6ed92bc..e81f14c212a 100644
--- a/app/assets/javascripts/discourse/components/d-editor.js.es6
+++ b/app/assets/javascripts/discourse/components/d-editor.js.es6
@@ -31,7 +31,7 @@ function Toolbar() {
   this.groups = [
     {group: 'fontStyles', buttons: []},
     {group: 'insertions', buttons: []},
-    {group: 'extras', buttons: [], lastGroup: true}
+    {group: 'extras', buttons: []}
   ];
 
   this.addButton({
@@ -105,6 +105,20 @@ function Toolbar() {
     title: 'composer.hr_title',
     perform: e => e.addText("\n\n----------\n")
   });
+
+  if (Discourse.Mobile.mobileView) {
+    this.groups.push({group: 'mobileExtras', buttons: []});
+
+    this.addButton({
+      id: 'preview',
+      group: 'mobileExtras',
+      icon: 'television',
+      title: 'composer.hr_preview',
+      perform: e => e.preview()
+    });
+  }
+
+  this.groups[this.groups.length-1].lastGroup = true;
 };
 
 Toolbar.prototype.addButton = function(button) {
@@ -166,6 +180,7 @@ export function onToolbarCreate(func) {
 export default Ember.Component.extend({
   classNames: ['d-editor'],
   ready: false,
+  forcePreview: false,
   insertLinkHidden: true,
   link: '',
   lastSel: null,
@@ -446,6 +461,10 @@ export default Ember.Component.extend({
     Ember.run.scheduleOnce("afterRender", () => this.$("textarea.d-editor-input").focus());
   },
 
+  _togglePreview() {
+    this.toggleProperty('forcePreview');
+  },
+
   actions: {
     toolbarButton(button) {
       const selected = this._getSelected();
@@ -453,7 +472,8 @@ export default Ember.Component.extend({
         selected,
         applySurround: (head, tail, exampleKey) => this._applySurround(selected, head, tail, exampleKey),
         applyList: (head, exampleKey) => this._applyList(selected, head, exampleKey),
-        addText: text => this._addText(selected, text)
+        addText: text => this._addText(selected, text),
+        preview: () => this._togglePreview()
       };
 
       if (button.sendAction) {
@@ -463,6 +483,10 @@ export default Ember.Component.extend({
       }
     },
 
+    hidePreview() {
+      this.set('forcePreview', false);
+    },
+
     showLinkModal() {
       this._lastSel = this._getSelected();
       this.set('insertLinkHidden', false);
diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6
index 1c7384c254b..88e6c532be8 100644
--- a/app/assets/javascripts/discourse/controllers/composer.js.es6
+++ b/app/assets/javascripts/discourse/controllers/composer.js.es6
@@ -54,12 +54,10 @@ export default Ember.Controller.extend({
   similarTopicsMessage: null,
   lastSimilaritySearch: null,
   optionsVisible: false,
-
   lastValidatedAt: null,
-
   isUploading: false,
-
   topic: null,
+  showToolbar: false,
 
   _initializeSimilar: function() {
     this.set('similarTopics', []);
@@ -90,6 +88,10 @@ export default Ember.Controller.extend({
       this.toggleProperty('model.whisper');
     },
 
+    toggleToolbar() {
+      this.toggleProperty('showToolbar');
+    },
+
     showOptions(loc) {
       this.appEvents.trigger('popup-menu:open', loc);
       this.set('optionsVisible', true);
diff --git a/app/assets/javascripts/discourse/lib/safari-hacks.js.es6 b/app/assets/javascripts/discourse/lib/safari-hacks.js.es6
index c14aa64b632..93e584f2395 100644
--- a/app/assets/javascripts/discourse/lib/safari-hacks.js.es6
+++ b/app/assets/javascripts/discourse/lib/safari-hacks.js.es6
@@ -89,11 +89,15 @@ function positioningWorkaround($fixedElement) {
   }
 
   const checkForInputs = _.debounce(function(){
-    $fixedElement.find('button,a:not(.mobile-file-upload)').each(function(idx, elem){
+    $fixedElement.find('button:not(.hide-preview),a:not(.mobile-file-upload):not(.toggle-toolbar)').each(function(idx, elem){
       if ($(elem).parents('.autocomplete').length > 0) {
         return;
       }
 
+      if ($(elem).parents('.d-editor-button-bar').length > 0) {
+        return;
+      }
+
       attachTouchStart(this, function(evt){
         done = true;
         $(document.activeElement).blur();
diff --git a/app/assets/javascripts/discourse/templates/components/d-editor.hbs b/app/assets/javascripts/discourse/templates/components/d-editor.hbs
index 64ea8909867..e9226920d14 100644
--- a/app/assets/javascripts/discourse/templates/components/d-editor.hbs
+++ b/app/assets/javascripts/discourse/templates/components/d-editor.hbs
@@ -25,9 +25,12 @@
     {{popup-input-tip validation=validation}}
   </div>
 
-  <div class="d-editor-preview-wrapper">
+  <div class="d-editor-preview-wrapper {{if forcePreview 'force-preview'}}">
     <div class="d-editor-preview">
       {{{preview}}}
     </div>
+    {{#if site.mobileView}}
+      {{d-button action='hidePreview' class='hide-preview' label='composer.hide_preview'}}
+    {{/if}}
   </div>
 </div>
diff --git a/app/assets/javascripts/discourse/templates/composer.hbs b/app/assets/javascripts/discourse/templates/composer.hbs
index bc3fa3270f5..06ebfdfbeff 100644
--- a/app/assets/javascripts/discourse/templates/composer.hbs
+++ b/app/assets/javascripts/discourse/templates/composer.hbs
@@ -11,6 +11,10 @@
 
   {{render "composer-messages"}}
   <div class='control'>
+
+    {{#if site.mobileView}}
+    <a href class='toggle-toolbar' {{action "toggleToolbar" bubbles=false}}></a>
+    {{/if}}
     <a href class='toggler' {{action "toggle" bubbles=false}} title={{i18n 'composer.toggler'}}></a>
 
     {{#if model.viewOpen}}
@@ -20,9 +24,11 @@
 
           <div class='reply-to'>
             {{{model.actionTitle}}}
+            {{#unless site.mobileView}}
             {{#if model.whisper}}
               <span class='whisper'>({{i18n "composer.whisper"}})</span>
             {{/if}}
+            {{/unless}}
 
             {{#if canEdit}}
               {{#if showEditReason}}
@@ -85,6 +91,7 @@
                           groupsMentioned="groupsMentioned"
                           importQuote="importQuote"
                           showOptions="showOptions"
+                          showToolbar=showToolbar
                           showUploadSelector="showUploadSelector"}}
 
         {{#if currentUser}}
@@ -92,6 +99,12 @@
             {{plugin-outlet "composer-fields-below"}}
             <button {{action "save"}} tabindex="5" {{bind-attr class=":btn :btn-primary :create disableSubmit:disabled"}} title="{{i18n 'composer.title'}}">{{{model.saveIcon}}}{{model.saveText}}</button>
             <a href {{action "cancel"}} class='cancel' tabindex="6">{{i18n 'cancel'}}</a>
+
+            {{#if site.mobileView}}
+            {{#if model.whisper}}
+            <span class='whisper'><i class='fa fa-eye-slash'></i></span>
+            {{/if}}
+            {{/if}}
           </div>
         {{/if}}
       </div>
diff --git a/app/assets/stylesheets/mobile/compose.scss b/app/assets/stylesheets/mobile/compose.scss
index aac01b2e9a8..d7372c53a31 100644
--- a/app/assets/stylesheets/mobile/compose.scss
+++ b/app/assets/stylesheets/mobile/compose.scss
@@ -36,7 +36,7 @@ input {
   bottom: 0;
   font-size: 1em;
   position: fixed;
-  .toggler {
+  .toggle-toolbar, .toggler {
     width: 15px;
     right: 1px;
     position: absolute;
@@ -48,6 +48,14 @@ input {
       content: "\f078";
     }
   }
+
+  .toggle-toolbar {
+    right: 30px;
+    &:before {
+      content: "\f0c9";
+    }
+  }
+
   a.cancel {
     padding-left: 7px;
     line-height: 30px;
@@ -56,7 +64,7 @@ input {
     margin: 0 0 0 5px;
     .reply-to {
       overflow: hidden;
-      max-width: 92%;
+      max-width: 80%;
       white-space: nowrap;
       i {
         color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
@@ -235,6 +243,31 @@ input {
     .d-editor-preview-wrapper {
       display: none;
     }
+
+    .d-editor-preview-wrapper.force-preview {
+      display: block;
+      position: fixed;
+      z-index: 1000000;
+      top: 0;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      background-color: $secondary;
+
+      .d-editor-preview {
+        height: 90%;
+        height: calc(100% - 60px);
+        border: 0;
+        overflow: auto;
+      }
+
+      .hide-preview {
+        position: fixed;
+        right: 5px;
+        bottom: 5px;
+        z-index: 1000001;
+      }
+    }
     .d-editor-input {
       width: 100%;
       height: 100%;
@@ -260,6 +293,40 @@ input {
   .d-editor-button-bar {
     display: none;
   }
+
+
+  .wmd-controls.toolbar-visible .d-editor-input {
+    padding-top: 40px;
+  }
+
+  .wmd-controls.toolbar-visible .d-editor-button-bar {
+
+    .btn.link, .btn.upload, .btn.rule, .btn.bullet, .btn.list, .btn.heading {
+      display: none;
+    }
+
+    display: block;
+    margin: 1px 4px;
+    position: absolute;
+    color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
+    background-color: $secondary;
+    z-index: 100;
+    overflow: hidden;
+    width: 100%;
+    width: calc(100% - 10px);
+
+    -moz-box-sizing: border-box;
+    box-sizing: border-box;
+
+    button {
+      color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
+    }
+    button.btn.no-text {
+      margin: 0 2px;
+      padding: 2px 5px;
+      position: static;
+    }
+  }
 }
 
 // make sure the category selector *NEVER* gets focus by default on mobile anywhere