diff --git a/app/assets/javascripts/admin/templates/user_index.hbs b/app/assets/javascripts/admin/templates/user_index.hbs
index e6347ff68c2..4dff9338a43 100644
--- a/app/assets/javascripts/admin/templates/user_index.hbs
+++ b/app/assets/javascripts/admin/templates/user_index.hbs
@@ -455,7 +455,7 @@
     {{#unless anonymizeForbidden}}
       {{d-button label="admin.user.anonymize"
                  icon="exclamation-triangle"
-                 class="btn btn-danger"
+                 class="btn-danger"
                  disabled=anonymizeForbidden
                  action="anonymize"}}
     {{/unless}}
@@ -463,7 +463,7 @@
     {{#unless deleteForbidden}}
       {{d-button label="admin.user.delete"
                  icon="exclamation-triangle"
-                 class="btn btn-danger"
+                 class="btn-danger"
                  disabled=deleteForbidden
                  action="destroy"}}
     {{/unless}}
diff --git a/app/assets/javascripts/discourse/components/avatar-uploader.js.es6 b/app/assets/javascripts/discourse/components/avatar-uploader.js.es6
index b67da9c65fe..f00f6742806 100644
--- a/app/assets/javascripts/discourse/components/avatar-uploader.js.es6
+++ b/app/assets/javascripts/discourse/components/avatar-uploader.js.es6
@@ -1,19 +1,19 @@
 import UploadMixin from 'discourse/mixins/upload';
 
 export default Em.Component.extend(UploadMixin, {
+  type: 'avatar',
   tagName: 'span',
   imageIsNotASquare: false,
-  type: 'avatar',
 
   uploadUrl: Discourse.computed.url('username', '/users/%@/preferences/user_image'),
 
   uploadButtonText: function() {
-    return this.get("uploading") ? I18n.t("uploading") : I18n.t("user.change_avatar.upload_picture");
+    return this.get("uploading") ?
+           I18n.t("uploading") :
+           I18n.t("user.change_avatar.upload_picture");
   }.property("uploading"),
 
-  uploadDone: function(data) {
-    var self = this;
-
+  uploadDone(data) {
     // display a warning whenever the image is not a square
     this.set("imageIsNotASquare", data.result.width !== data.result.height);
 
@@ -21,13 +21,13 @@ export default Em.Component.extend(UploadMixin, {
     // indeed, the server gives us back the url to the file we've just uploaded
     // often, this file is not a square, so we need to crop it properly
     // this will also capture the first frame of animated avatars when they're not allowed
-    Discourse.Utilities.cropAvatar(data.result.url, data.files[0].type).then(function(avatarTemplate) {
-      self.set("uploadedAvatarTemplate", avatarTemplate);
+    Discourse.Utilities.cropAvatar(data.result.url, data.files[0].type).then(avatarTemplate => {
+      this.set("uploadedAvatarTemplate", avatarTemplate);
 
       // indicates the users is using an uploaded avatar (must happen after cropping, otherwise
       //  we will attempt to load an invalid avatar and cache a redirect to old one, uploadedAvatarTemplate
       //  trumps over custom avatar upload id)
-      self.set("custom_avatar_upload_id", data.result.upload_id);
+      this.set("custom_avatar_upload_id", data.result.upload_id);
     });
 
     // the upload is now done
diff --git a/app/assets/javascripts/discourse/components/d-button.js.es6 b/app/assets/javascripts/discourse/components/d-button.js.es6
index 21ebedc8e82..973405128f3 100644
--- a/app/assets/javascripts/discourse/components/d-button.js.es6
+++ b/app/assets/javascripts/discourse/components/d-button.js.es6
@@ -32,5 +32,6 @@ export default Ember.Component.extend({
 
   click() {
     this.sendAction("action", this.get("actionParam"));
+    return false;
   }
 });
diff --git a/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6 b/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6
index e856b5a09f8..3909f31aff4 100644
--- a/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6
+++ b/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6
@@ -2,8 +2,10 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
 import DiscourseController from 'discourse/controllers/controller';
 
 export default DiscourseController.extend(ModalFunctionality, {
+  uploadedAvatarTemplate: null,
+  hasUploadedAvatar: Em.computed.or('uploadedAvatarTemplate', 'custom_avatar_upload_id'),
 
-  selectedUploadId: function(){
+  selectedUploadId: function() {
       switch (this.get("selected")) {
         case "system": return this.get("system_avatar_upload_id");
         case "gravatar": return this.get("gravatar_avatar_upload_id");
@@ -12,18 +14,16 @@ export default DiscourseController.extend(ModalFunctionality, {
   }.property('selected', 'system_avatar_upload_id', 'gravatar_avatar_upload_id', 'custom_avatar_upload_id'),
 
   actions: {
-    useUploadedAvatar: function() { this.set("selected", "uploaded"); },
-    useGravatar: function() { this.set("selected", "gravatar"); },
-    useSystem: function() { this.set("selected", "system"); },
-    refreshGravatar: function() {
-      var self = this;
-      self.set("gravatarRefreshDisabled", true);
-      Discourse
-          .ajax("/user_avatar/" + this.get("username") + "/refresh_gravatar", {method: 'POST'})
-          .then(function(result){
-            self.set("gravatarRefreshDisabled", false);
-            self.set("gravatar_avatar_upload_id", result.upload_id);
-          });
+    useUploadedAvatar() { this.set("selected", "uploaded"); },
+    useGravatar() { this.set("selected", "gravatar"); },
+    useSystem() { this.set("selected", "system"); },
+
+    refreshGravatar() {
+      this.set("gravatarRefreshDisabled", true);
+      return Discourse
+        .ajax("/user_avatar/" + this.get("username") + "/refresh_gravatar.json", { method: 'POST' })
+        .then(result => this.set("gravatar_avatar_upload_id", result.upload_id))
+        .finally(() => this.set("gravatarRefreshDisabled", false));
     }
   }
 
diff --git a/app/assets/javascripts/discourse/lib/show-modal.js.es6 b/app/assets/javascripts/discourse/lib/show-modal.js.es6
index 667a344ddda..7fac8a1158e 100644
--- a/app/assets/javascripts/discourse/lib/show-modal.js.es6
+++ b/app/assets/javascripts/discourse/lib/show-modal.js.es6
@@ -1,4 +1,4 @@
-export default function showModal(name, model) {
+export default (name, model) => {
   // We use the container here because modals are like singletons
   // in Discourse. Only one can be shown with a particular state.
   const route = Discourse.__container__.lookup('route:application');
@@ -12,5 +12,4 @@ export default function showModal(name, model) {
     if (controller.onShow) { controller.onShow(); }
     controller.set('flashMessage', null);
   }
-  return controller;
-}
+};
diff --git a/app/assets/javascripts/discourse/mixins/show-footer.js.es6 b/app/assets/javascripts/discourse/mixins/show-footer.js.es6
index a83fdbcf2d0..b97014153af 100644
--- a/app/assets/javascripts/discourse/mixins/show-footer.js.es6
+++ b/app/assets/javascripts/discourse/mixins/show-footer.js.es6
@@ -1,14 +1,13 @@
 export default Em.Mixin.create({
   actions: {
-    didTransition: function() {
-      var self = this;
-      Em.run.schedule("afterRender", function() {
-        self.controllerFor("application").set("showFooter", true);
+    didTransition() {
+      Em.run.schedule("afterRender", () => {
+        this.controllerFor("application").set("showFooter", true);
       });
       return true;
     },
 
-    willTransition: function() {
+    willTransition() {
       this.controllerFor("application").set("showFooter", false);
       return true;
     }
diff --git a/app/assets/javascripts/discourse/routes/preferences.js.es6 b/app/assets/javascripts/discourse/routes/preferences.js.es6
index 79712f495eb..7fb2ba4a41f 100644
--- a/app/assets/javascripts/discourse/routes/preferences.js.es6
+++ b/app/assets/javascripts/discourse/routes/preferences.js.es6
@@ -8,7 +8,10 @@ export default RestrictedUserRoute.extend(ShowFooter, {
   },
 
   setupController(controller, user) {
-    controller.setProperties({ model: user, newNameInput: user.get('name') });
+    controller.setProperties({
+      model: user,
+      newNameInput: user.get('name')
+    });
   },
 
   actions: {
@@ -16,15 +19,15 @@ export default RestrictedUserRoute.extend(ShowFooter, {
       showModal('avatar-selector');
 
       // all the properties needed for displaying the avatar selector modal
-      const controller = this.controllerFor('avatar-selector');
-      const user = this.modelFor('user');
-      const props = user.getProperties(
-        'username', 'email',
-        'uploaded_avatar_id',
-        'system_avatar_upload_id',
-        'gravatar_avatar_upload_id',
-        'custom_avatar_upload_id'
-      );
+      const controller = this.controllerFor('avatar-selector'),
+            props = this.modelFor('user').getProperties(
+              'email',
+              'username',
+              'uploaded_avatar_id',
+              'system_avatar_upload_id',
+              'gravatar_avatar_upload_id',
+              'custom_avatar_upload_id'
+            );
 
       switch (props.uploaded_avatar_id) {
         case props.system_avatar_upload_id:
@@ -40,20 +43,20 @@ export default RestrictedUserRoute.extend(ShowFooter, {
       controller.setProperties(props);
     },
 
-    saveAvatarSelection: function() {
-      const user = this.modelFor('user');
-      const avatarSelector = this.controllerFor('avatar-selector');
+    saveAvatarSelection() {
+      const user = this.modelFor('user'),
+            avatarSelector = this.controllerFor('avatar-selector');
 
       // sends the information to the server if it has changed
       if (avatarSelector.get('selectedUploadId') !== user.get('uploaded_avatar_id')) {
         user.pickAvatar(avatarSelector.get('selectedUploadId'))
-          .then(function(){
-            user.setProperties(avatarSelector.getProperties(
-              'system_avatar_upload_id',
-              'gravatar_avatar_upload_id',
-              'custom_avatar_upload_id'
-            ));
-          });
+            .then(() => {
+              user.setProperties(avatarSelector.getProperties(
+                'system_avatar_upload_id',
+                'gravatar_avatar_upload_id',
+                'custom_avatar_upload_id'
+              ));
+            });
       }
 
       // saves the data back
diff --git a/app/assets/javascripts/discourse/routes/restricted-user.js.es6 b/app/assets/javascripts/discourse/routes/restricted-user.js.es6
index ad9cb411efd..46cc1fe6fe3 100644
--- a/app/assets/javascripts/discourse/routes/restricted-user.js.es6
+++ b/app/assets/javascripts/discourse/routes/restricted-user.js.es6
@@ -2,9 +2,8 @@
 
 export default Discourse.Route.extend({
 
-  afterModel: function() {
-    var user = this.modelFor('user');
-    if (!user.get('can_edit')) {
+  afterModel() {
+    if (!this.modelFor('user').get('can_edit')) {
       this.replaceWith('userActivity');
     }
   }
diff --git a/app/assets/javascripts/discourse/templates/modal/avatar_selector.hbs b/app/assets/javascripts/discourse/templates/modal/avatar_selector.hbs
index caad9187acd..0e375179c2b 100644
--- a/app/assets/javascripts/discourse/templates/modal/avatar_selector.hbs
+++ b/app/assets/javascripts/discourse/templates/modal/avatar_selector.hbs
@@ -7,14 +7,14 @@
     <div>
       <input type="radio" id="gravatar" name="avatar" value="gravatar" {{action "useGravatar"}}>
       <label class="radio" for="gravatar">{{bound-avatar controller "large" gravatar_avatar_upload_id}} {{{i18n 'user.change_avatar.gravatar'}}} {{email}}</label>
-      <button href {{action "refreshGravatar"}} title="{{i18n 'user.change_avatar.refresh_gravatar_title'}}" {{bind-attr enabled="view.gravatarRefreshEnabled"}} class="btn no-text"><i class="fa fa-refresh"></i></button>
+      {{d-button action="refreshGravatar" title="user.change_avatar.refresh_gravatar_title" disabled=gravatarRefreshDisabled class="no-text" icon="refresh"}}
     </div>
     <div>
       <input type="radio" id="uploaded_avatar" name="avatar" value="uploaded" {{action "useUploadedAvatar"}}>
       <label class="radio" for="uploaded_avatar">
-        {{#if view.hasUploadedAvatar}}
-          {{#if view.uploadedAvatarTemplate}}
-            {{bound-avatar-template view.uploadedAvatarTemplate "large"}}
+        {{#if hasUploadedAvatar}}
+          {{#if uploadedAvatarTemplate}}
+            {{bound-avatar-template uploadedAvatarTemplate "large"}}
           {{else}}
             {{bound-avatar controller "large" custom_avatar_upload_id}} {{i18n 'user.change_avatar.uploaded_avatar'}}
           {{/if}}
@@ -23,14 +23,14 @@
         {{/if}}
       </label>
       {{avatar-uploader username=username
-                        uploadedAvatarTemplate=view.uploadedAvatarTemplate
-                        custom_avatar_upload_id=controller.custom_avatar_upload_id
+                        uploadedAvatarTemplate=uploadedAvatarTemplate
+                        custom_avatar_upload_id=custom_avatar_upload_id
                         done="useUploadedAvatar"}}
     </div>
   </div>
 </div>
 
 <div class="modal-footer">
-  <button class="btn btn-primary" {{action "saveAvatarSelection"}} {{bind-attr disabled="view.saveDisabled"}}>{{i18n 'save'}}</button>
+  {{d-button action="saveAvatarSelection" class="btn-primary" disabled=saveDisabled label="save"}}
   <a {{action "closeModal"}}>{{i18n 'cancel'}}</a>
 </div>
diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs
index 4a617f999a3..d7cc7b20c34 100644
--- a/app/assets/javascripts/discourse/templates/user/preferences.hbs
+++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs
@@ -54,7 +54,7 @@
           <div class="controls">
             <span class='static'>{{email}}</span>
             {{#if can_edit_email}}
-              {{#link-to "preferences.email" class="btn btn-small pad-left no-text"}}<i class="fa fa-pencil"></i>{{/link-to}}
+              {{#link-to "preferences.email" class="btn btn-small pad-left no-text"}}{{fa-icon "pencil"}}{{/link-to}}
             {{/if}}
           </div>
           <div class='instructions'>
@@ -62,7 +62,7 @@
           </div>
         {{else}}
           <div class="controls">
-            <button class="btn" title="{{i18n 'admin.users.check_email.title'}}" {{action "checkEmail" this}}>{{fa-icon "envelope-o"}} {{i18n 'admin.users.check_email.text'}}</button>
+            {{d-button action="checkEmail" actionParam=this title="admin.users.check_email.title" icon="envelope-o" label="admin.users.check_email.text"}}
           </div>
         {{/if}}
       </div>
@@ -72,7 +72,8 @@
     <div class="control-group pref-password">
       <label class="control-label">{{i18n 'user.password.title'}}</label>
       <div class="controls">
-        <a href="#" {{action "changePassword"}} class='btn'><i class="fa fa-envelope"></i>
+        <a href="#" {{action "changePassword"}} class='btn'>
+          {{fa-icon "envelope"}}
           {{#if no_password}}
             {{i18n 'user.change_password.set_password'}}
           {{else}}
@@ -87,9 +88,10 @@
     <div class="control-group pref-avatar">
       <label class="control-label">{{i18n 'user.avatar.title'}}</label>
       <div class="controls">
-        {{bound-avatar model "large"}}
+        {{! we want the "huge" version even though we're downsizing it to "large" in CSS }}
+        {{bound-avatar model "huge"}}
         {{#if allowAvatarUpload}}
-          <button {{action "showAvatarSelector"}} class="btn pad-left no-text">{{fa-icon "pencil"}}</button>
+          {{d-button action="showAvatarSelector" class="pad-left no-text" icon="pencil"}}
         {{else}}
           {{#unless ssoOverridesAvatar}}
             <a href="//gravatar.com/emails" target="_blank" title="{{i18n 'user.change_avatar.gravatar_title'}}" class="btn no-text">{{fa-icon "pencil"}}</a>
@@ -245,7 +247,7 @@
       <div class="control-group delete-account">
         <hr/>
         <div class="controls">
-            <button {{action "delete"}} {{bind-attr disabled="deleteDisabled"}} class="btn btn-danger"><i class="fa fa-trash-o"></i> {{i18n 'user.delete_account'}}</button>
+          {{d-button action="delete" disabled="deleteDisabled" class="btn-danger" icon="trash-o" label="user.delete_account"}}
         </div>
       </div>
     {{/if}}
diff --git a/app/assets/javascripts/discourse/views/avatar-selector.js.es6 b/app/assets/javascripts/discourse/views/avatar-selector.js.es6
index 40414660a6d..ed60610505b 100644
--- a/app/assets/javascripts/discourse/views/avatar-selector.js.es6
+++ b/app/assets/javascripts/discourse/views/avatar-selector.js.es6
@@ -4,9 +4,6 @@ export default ModalBodyView.extend({
   templateName: 'modal/avatar_selector',
   classNames: ['avatar-selector'],
   title: I18n.t('user.change_avatar.title'),
-  saveDisabled: false,
-  gravatarRefreshEnabled: Em.computed.not('controller.gravatarRefreshDisabled'),
-  hasUploadedAvatar: Em.computed.or('uploadedAvatarTemplate', 'controller.custom_avatar_upload_id'),
 
   // *HACK* used to select the proper radio button, cause {{action}}
   //  stops the default behavior
diff --git a/app/assets/stylesheets/desktop/user.scss b/app/assets/stylesheets/desktop/user.scss
index cc3fe231583..6936c8d6055 100644
--- a/app/assets/stylesheets/desktop/user.scss
+++ b/app/assets/stylesheets/desktop/user.scss
@@ -170,6 +170,13 @@
         border-bottom: 1px solid scale-color-diff();
       }
     }
+
+    .pref-avatar {
+      .avatar {
+        max-width: 45px;
+        max-height: 45px;
+      }
+    }
   }
 
   .about {
diff --git a/test/javascripts/controllers/avatar-selector-test.js.es6 b/test/javascripts/controllers/avatar-selector-test.js.es6
index 8d7441d6e24..3f2f0af811e 100644
--- a/test/javascripts/controllers/avatar-selector-test.js.es6
+++ b/test/javascripts/controllers/avatar-selector-test.js.es6
@@ -3,7 +3,8 @@ moduleFor("controller:avatar-selector", "controller:avatar-selector", {
 });
 
 test("avatarTemplate", function() {
-  var avatarSelectorController = this.subject();
+  const avatarSelectorController = this.subject();
+
   avatarSelectorController.setProperties({
     selected: "system",
     system_avatar_upload_id:1,
@@ -11,17 +12,11 @@ test("avatarTemplate", function() {
     custom_avatar_upload_id: 3
   });
 
-  equal(avatarSelectorController.get("selectedUploadId"), 1,
-        "we are using system by default");
+  equal(avatarSelectorController.get("selectedUploadId"), 1, "we are using system by default");
 
   avatarSelectorController.set('selected', 'gravatar');
-
-  equal(avatarSelectorController.get("selectedUploadId"), 2,
-        "we are using gravatar when set");
+  equal(avatarSelectorController.get("selectedUploadId"), 2, "we are using gravatar when set");
 
   avatarSelectorController.set("selected", "custom");
-
-  equal(avatarSelectorController.get("selectedUploadId"), 3,
-        "we are using custom when set");
-
+  equal(avatarSelectorController.get("selectedUploadId"), 3, "we are using custom when set");
 });