diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
index a01cb8cc202ba0cb08b04bcc3cbb51750b377af2..982b5e8e3731f1da3b29977e47fd4c295739273f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
@@ -1,3 +1,5 @@
+import tooltip from '../../vue_shared/directives/tooltip';
+
 export default {
   name: 'MRWidgetAuthor',
   props: {
@@ -5,11 +7,14 @@ export default {
     showAuthorName: { type: Boolean, required: false, default: true },
     showAuthorTooltip: { type: Boolean, required: false, default: false },
   },
+  directives: {
+    tooltip,
+  },
   template: `
     <a
       :href="author.webUrl || author.web_url"
-      class="author-link"
-      :class="{ 'has-tooltip': showAuthorTooltip }"
+      class="author-link inline"
+      :v-tooltip="showAuthorTooltip"
       :title="author.name">
       <img
         :src="author.avatarUrl || author.avatar_url"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
index 744a1cd24fac839a8ac7668c49c6ba6105cb0294..e98d147733c7864cbb2859509c81fd4be492b31c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
@@ -1,8 +1,8 @@
 /* global Flash */
 
 import '~/lib/utils/datetime_utility';
-import { statusIconEntityMap } from '../../vue_shared/ci_status_icons';
 import MemoryUsage from './mr_widget_memory_usage';
+import StatusIcon from './mr_widget_status_icon';
 import MRWidgetService from '../services/mr_widget_service';
 
 export default {
@@ -13,11 +13,7 @@ export default {
   },
   components: {
     'mr-widget-memory-usage': MemoryUsage,
-  },
-  computed: {
-    svg() {
-      return statusIconEntityMap.icon_status_success;
-    },
+    'status-icon': StatusIcon,
   },
   methods: {
     formatDate(date) {
@@ -51,51 +47,51 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-heading">
+    <div class="mr-widget-heading deploy-heading">
       <div v-for="deployment in mr.deployments">
-        <div class="ci-widget">
+        <div class="ci-widget media">
           <div class="ci-status-icon ci-status-icon-success">
             <span class="js-icon-link icon-link">
-              <span class="ci-status-icon"
-                v-html="svg"
-                aria-hidden="true"></span>
+              <status-icon status="success" />
             </span>
           </div>
-          <span>
-            <span
-              v-if="hasDeploymentMeta(deployment)">
-              Deployed to
-            </span>
-            <a
-              v-if="hasDeploymentMeta(deployment)"
-              :href="deployment.url"
-              target="_blank"
-              rel="noopener noreferrer nofollow"
-              class="js-deploy-meta">
-              {{deployment.name}}
-            </a>
-            <span
-              v-if="hasExternalUrls(deployment)">
-              on
-            </span>
-            <a
-              v-if="hasExternalUrls(deployment)"
-              :href="deployment.external_url"
-              target="_blank"
-              rel="noopener noreferrer nofollow"
-              class="js-deploy-url">
-              <i
-                class="fa fa-external-link"
-                aria-hidden="true" />
-              {{deployment.external_url_formatted}}
-            </a>
-            <span
-              v-if="hasDeploymentTime(deployment)"
-              :data-title="deployment.deployed_at_formatted"
-              class="js-deploy-time"
-              data-toggle="tooltip"
-              data-placement="top">
-              {{formatDate(deployment.deployed_at)}}
+          <div class="media-body space-children">
+            <span>
+              <span
+                v-if="hasDeploymentMeta(deployment)">
+                Deployed to
+              </span>
+              <a
+                v-if="hasDeploymentMeta(deployment)"
+                :href="deployment.url"
+                target="_blank"
+                rel="noopener noreferrer nofollow"
+                class="js-deploy-meta inline">
+                {{deployment.name}}
+              </a>
+              <span
+                v-if="hasExternalUrls(deployment)">
+                on
+              </span>
+              <a
+                v-if="hasExternalUrls(deployment)"
+                :href="deployment.external_url"
+                target="_blank"
+                rel="noopener noreferrer nofollow"
+                class="js-deploy-url inline">
+                <i
+                  class="fa fa-external-link"
+                  aria-hidden="true" />
+                {{deployment.external_url_formatted}}
+              </a>
+              <span
+                v-if="hasDeploymentTime(deployment)"
+                :data-title="deployment.deployed_at_formatted"
+                class="js-deploy-time"
+                data-toggle="tooltip"
+                data-placement="top">
+                {{formatDate(deployment.deployed_at)}}
+              </span>
             </span>
             <button
               type="button"
@@ -104,13 +100,13 @@ export default {
               class="btn btn-default btn-xs">
               Stop environment
             </button>
-          </span>
+            <mr-widget-memory-usage
+              v-if="deployment.metrics_url"
+              :metrics-url="deployment.metrics_url"
+              :metrics-monitoring-url="deployment.metrics_monitoring_url"
+            />
+          </div>
         </div>
-        <mr-widget-memory-usage
-          v-if="deployment.metrics_url"
-          :metrics-url="deployment.metrics_url"
-          :metrics-monitoring-url="deployment.metrics_monitoring_url"
-        />
       </div>
     </div>
   `,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
index 8430548903cb022fe071bed0adba1875f94cda17..c05a76a3b4a54d0d57d01bdd0b10589efa43568b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
@@ -1,3 +1,4 @@
+import tooltip from '../../vue_shared/directives/tooltip';
 import '../../lib/utils/text_utility';
 
 export default {
@@ -5,6 +6,9 @@ export default {
   props: {
     mr: { type: Object, required: true },
   },
+  directives: {
+    tooltip,
+  },
   computed: {
     shouldShowCommitsBehindText() {
       return this.mr.divergedCommitsCount > 0;
@@ -29,18 +33,51 @@ export default {
   },
   template: `
     <div class="mr-source-target">
-      <div
-        v-if="mr.isOpen"
-        class="pull-right">
+      <div class="normal">
+        <strong>
+          Request to merge
+          <span
+            class="label-branch"
+            :class="{'label-truncated': isBranchTitleLong(mr.sourceBranch)}"
+            :title="isBranchTitleLong(mr.sourceBranch) ? mr.sourceBranch : ''"
+            data-placement="bottom"
+            :v-tooltip="isBranchTitleLong(mr.sourceBranch)"
+            v-html="mr.sourceBranchLink"></span>
+          <button
+            v-tooltip
+            class="btn btn-transparent btn-clipboard"
+            data-title="Copy branch name to clipboard"
+            :data-clipboard-text="branchNameClipboardData">
+            <i
+              aria-hidden="true"
+              class="fa fa-clipboard"></i>
+          </button>
+          into
+          <span
+            class="label-branch"
+            :v-tooltip="isBranchTitleLong(mr.sourceBranch)"
+            :class="{'label-truncatedtooltip': isBranchTitleLong(mr.targetBranch)}"
+            :title="isBranchTitleLong(mr.targetBranch) ? mr.targetBranch : ''"
+            data-placement="bottom">
+            <a :href="mr.targetBranchTreePath">{{mr.targetBranch}}</a>
+          </span>
+        </strong>
+        <span
+          v-if="shouldShowCommitsBehindText"
+          class="diverged-commits-count">
+          (<a :href="mr.targetBranchPath">{{mr.divergedCommitsCount}} {{commitsText}} behind</a>)
+        </span>
+      </div>
+      <div v-if="mr.isOpen">
         <a
           href="#modal_merge_info"
           data-toggle="modal"
-          class="btn inline btn-grouped btn-sm">
+          class="btn btn-small inline">
           Check out branch
         </a>
-        <span class="dropdown inline prepend-left-5">
+        <span class="dropdown inline prepend-left-10">
           <a
-            class="btn btn-sm dropdown-toggle"
+            class="btn btn-xs dropdown-toggle"
             data-toggle="dropdown"
             aria-label="Download as"
             role="button">
@@ -69,38 +106,6 @@ export default {
           </ul>
         </span>
       </div>
-      <div class="normal">
-        <strong>
-          Request to merge
-          <span
-            class="label-branch"
-            :class="{'label-truncated has-tooltip': isBranchTitleLong(mr.sourceBranch)}"
-            :title="isBranchTitleLong(mr.sourceBranch) ? mr.sourceBranch : ''"
-            data-placement="bottom"
-            v-html="mr.sourceBranchLink"></span>
-          <button
-            class="btn btn-transparent btn-clipboard has-tooltip"
-            data-title="Copy branch name to clipboard"
-            :data-clipboard-text="branchNameClipboardData">
-            <i
-              aria-hidden="true"
-              class="fa fa-clipboard"></i>
-          </button>
-          into
-          <span
-            class="label-branch"
-            :class="{'label-truncated has-tooltip': isBranchTitleLong(mr.targetBranch)}"
-            :title="isBranchTitleLong(mr.targetBranch) ? mr.targetBranch : ''"
-            data-placement="bottom">
-            <a :href="mr.targetBranchTreePath">{{mr.targetBranch}}</a>
-          </span>
-        </strong>
-        <span
-          v-if="shouldShowCommitsBehindText"
-          class="diverged-commits-count">
-          (<a :href="mr.targetBranchPath">{{mr.divergedCommitsCount}} {{commitsText}} behind</a>)
-        </span>
-      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
index 534e2a88effb06f3169598e15f179d592efb2bb5..a4e34116c3388eceb49be9783d02942e266efb63 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
@@ -120,13 +120,12 @@ export default {
   },
   template: `
     <div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
-      <div class="legend"></div>
       <p
         v-if="shouldShowLoading"
         class="usage-info js-usage-info usage-info-loading">
         <i
           class="fa fa-spinner fa-spin usage-info-load-spinner"
-          aria-hidden="true" />Loading deployment statistics.
+          aria-hidden="true" />Loading deployment statistics
       </p>
       <p
         v-if="shouldShowMemoryGraph"
@@ -136,12 +135,12 @@ export default {
       <p
         v-if="shouldShowLoadFailure"
         class="usage-info js-usage-info usage-info-failed">
-        Failed to load deployment statistics.
+        Failed to load deployment statistics
       </p>
       <p
         v-if="shouldShowMetricsUnavailable"
         class="usage-info js-usage-info usage-info-unavailable">
-        Deployment statistics are not available currently.
+        Deployment statistics are not available currently
       </p>
       <mr-memory-graph
         v-if="shouldShowMemoryGraph"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
index 2fecebce7a0f9db5b884c9ab508d54cc816e7e12..1d9f9863dd9b3578988c25d4fa123d64c6b7d58c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
@@ -16,7 +16,7 @@ export default {
       <a
         data-toggle="modal"
         href="#modal_merge_info">
-        command line.
+        command line
       </a>
     </section>
   `,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
index c02e10128e2bb22c810b891ed8feaf7bb08e8f96..6c2e9ba1d30c0cea042b25c192ae0d5e3ab53c13 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
@@ -29,58 +29,55 @@ export default {
   },
   template: `
     <div class="mr-widget-heading">
-      <div class="ci-widget">
+      <div class="ci-widget media">
         <template v-if="hasCIError">
-          <div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error">
-            <span class="js-icon-link icon-link">
-              <span
-                v-html="svg"
-                aria-hidden="true"></span>
-            </span>
+          <div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-10">
+            <span
+              v-html="svg"
+              aria-hidden="true"></span>
+          </div>
+          <div class="media-body">
+            Could not connect to the CI server. Please check your settings and try again
           </div>
-          <span>Could not connect to the CI server. Please check your settings and try again.</span>
         </template>
         <template v-else>
-          <div>
+          <div class="ci-status-icon append-right-10">
             <a
               class="icon-link"
               :href="this.status.details_path">
               <ci-icon :status="status" />
             </a>
           </div>
-          <span>
-            Pipeline
-            <a
-              :href="mr.pipeline.path"
-              class="pipeline-id">#{{mr.pipeline.id}}</a>
-            {{mr.pipeline.details.status.label}}
-          </span>
-          <span
-            v-if="mr.pipeline.details.stages.length > 0">
-            with {{stageText}}
-          </span>
-          <div class="mr-widget-pipeline-graph">
-            <div class="stage-cell">
-              <div
-                v-if="mr.pipeline.details.stages.length > 0"
-                v-for="stage in mr.pipeline.details.stages"
-                class="stage-container dropdown js-mini-pipeline-graph">
-                <pipeline-stage :stage="stage" />
-              </div>
-            </div>
+          <div class="media-body">
+            <span>
+              Pipeline
+              <a
+                :href="mr.pipeline.path"
+                class="pipeline-id">#{{mr.pipeline.id}}</a>
+            </span>
+            <span class="mr-widget-pipeline-graph">
+              <span class="stage-cell">
+                <div
+                  v-if="mr.pipeline.details.stages.length > 0"
+                  v-for="stage in mr.pipeline.details.stages"
+                  class="stage-container dropdown js-mini-pipeline-graph">
+                  <pipeline-stage :stage="stage" />
+                </div>
+              </span>
+            </span>
+            <span>
+              {{mr.pipeline.details.status.label}} for
+              <a
+                :href="mr.pipeline.commit.commit_path"
+                class="commit-sha js-commit-link">
+                {{mr.pipeline.commit.short_id}}</a>.
+            </span>
+            <span
+              v-if="mr.pipeline.coverage"
+              class="js-mr-coverage">
+              Coverage {{mr.pipeline.coverage}}%
+            </span>
           </div>
-          <span>
-            for
-            <a
-              :href="mr.pipeline.commit.commit_path"
-              class="commit-sha js-commit-link">
-              {{mr.pipeline.commit.short_id}}</a>.
-          </span>
-          <span
-            v-if="mr.pipeline.coverage"
-            class="js-mr-coverage">
-            Coverage {{mr.pipeline.coverage}}%.
-          </span>
         </template>
       </div>
     </div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
index 205804670fa473de6d573ea41d9bbbcb579a946b..563267ad044e7ec7f367d9d49a70c1381c6ed2f4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
@@ -2,37 +2,32 @@ export default {
   name: 'MRWidgetRelatedLinks',
   props: {
     relatedLinks: { type: Object, required: true },
+    state: { type: String, required: false },
   },
   computed: {
     hasLinks() {
       const { closing, mentioned, assignToMe } = this.relatedLinks;
       return closing || mentioned || assignToMe;
     },
-  },
-  methods: {
-    hasMultipleIssues(text) {
-      return !text ? false : text.match(/<\/a> and <a/);
-    },
-    issueLabel(field) {
-      return this.hasMultipleIssues(this.relatedLinks[field]) ? 'issues' : 'issue';
-    },
-    verbLabel(field) {
-      return this.hasMultipleIssues(this.relatedLinks[field]) ? 'are' : 'is';
+    closesText() {
+      if (this.state === 'merged') {
+        return 'Closed';
+      }
+      if (this.state === 'closed') {
+        return 'Did not close';
+      }
+      return 'Closes';
     },
   },
   template: `
     <section
       v-if="hasLinks"
       class="mr-info-list mr-links">
-      <div class="legend"></div>
       <p v-if="relatedLinks.closing">
-        Closes {{issueLabel('closing')}}
-        <span v-html="relatedLinks.closing"></span>.
+        {{closesText}} <span v-html="relatedLinks.closing"></span>
       </p>
       <p v-if="relatedLinks.mentioned">
-        <span class="capitalize">{{issueLabel('mentioned')}}</span>
-        <span v-html="relatedLinks.mentioned"></span>
-        {{verbLabel('mentioned')}} mentioned but will not be closed.
+        Mentions <span v-html="relatedLinks.mentioned"></span>
       </p>
       <p v-if="relatedLinks.assignToMe">
         <span v-html="relatedLinks.assignToMe"></span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js
new file mode 100644
index 0000000000000000000000000000000000000000..b01c923311b1994b88b27eb158673571b931bb71
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js
@@ -0,0 +1,36 @@
+import ciIcon from '../../vue_shared/components/ci_icon.vue';
+import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+
+export default {
+  props: {
+    status: { type: String, required: true },
+    showDisabledButton: { type: Boolean, required: false },
+  },
+  components: {
+    ciIcon,
+    loadingIcon,
+  },
+  computed: {
+    statusObj() {
+      return {
+        group: this.status,
+        icon: `icon_status_${this.status}`,
+      };
+    },
+  },
+  template: `
+    <div class="space-children flex-container-block append-right-10">
+      <div v-if="status === 'loading'" class="mr-widget-icon">
+        <loading-icon />
+      </div>
+      <ci-icon v-else :status="statusObj" />
+      <button
+        v-if="showDisabledButton"
+        type="button"
+        class="btn btn-success btn-small"
+        disabled="true">
+        Merge
+      </button>
+    </div>
+  `,
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
index c7f25a1697c358bca012cffb447f06ce755fa5dd..2b16a2d68171f34968b998ae0dcef6c71214d000 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
@@ -1,16 +1,26 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetArchived',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        This project is archived, write access has been disabled.
-      </span>
+    <div class="mr-widget-body media">
+      <div class="space-children">
+        <status-icon status="failed" />
+        <button
+          type="button"
+          class="btn btn-success btn-small"
+          disabled="true">
+          Merge
+        </button>
+      </div>
+      <div class="media-body">
+        <span class="bold">
+          This project is archived, write access has been disabled
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
index 4063859d5d0b5688610e710e0c29574782ac318f..5648208f7b12abfc9454ca3190201ae6cd4f687f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
@@ -1,4 +1,5 @@
 import eventHub from '../../event_hub';
+import statusIcon from '../mr_widget_status_icon';
 
 export default {
   name: 'MRWidgetAutoMergeFailed',
@@ -10,6 +11,9 @@ export default {
       isRefreshing: false,
     };
   },
+  components: {
+    statusIcon,
+  },
   methods: {
     refreshWidget() {
       this.isRefreshing = true;
@@ -19,18 +23,16 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-body">
-      <button
-        class="btn btn-success btn-small"
-        disabled="true"
-        type="button">
-        Merge
-      </button>
-      <span class="bold danger">
-        This merge request failed to be merged automatically.
+    <div class="mr-widget-body media">
+      <status-icon status="failed" />
+      <div class="media-body space-children">
+        <span class="bold">
+          <template v-if="mr.mergeError">{{mr.mergeError}}.</template>
+          This merge request failed to be merged automatically
+        </span>
         <button
           @click="refreshWidget"
-          :class="{ disabled: isRefreshing }"
+          :disabled="isRefreshing"
           type="button"
           class="btn btn-xs btn-default">
           <i
@@ -39,9 +41,6 @@ export default {
             aria-hidden="true" />
           Refresh
         </button>
-      </span>
-      <div class="merge-error-text danger bold">
-        {{mr.mergeError}}
       </div>
     </div>
   `,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
index 8515b54e62dc540803f197b78f90b1bb64c19f97..aaf9d3304a43cd1a74ee1336dcb5156edc9544fd 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
@@ -1,19 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetChecking',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        Checking ability to merge automatically.
-        <i
-          class="fa fa-spinner fa-spin"
-          aria-hidden="true" />
-      </span>
+    <div class="mr-widget-body media">
+      <status-icon status="loading" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          Checking ability to merge automatically
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
index fc2e42c6821def001ae01e6b02ef40476865972a..4078aad7f83c8055f3e8a9df7d9f92d64cf86e22 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
@@ -1,4 +1,5 @@
 import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
+import statusIcon from '../mr_widget_status_icon';
 
 export default {
   name: 'MRWidgetClosed',
@@ -7,24 +8,28 @@ export default {
   },
   components: {
     'mr-widget-author-and-time': mrWidgetAuthorTime,
+    statusIcon,
   },
   template: `
-    <div class="mr-widget-body">
-      <mr-widget-author-and-time
-        actionText="Closed by"
-        :author="mr.closedBy"
-        :dateTitle="mr.updatedAt"
-        :dateReadable="mr.closedAt"
-      />
-      <section>
-        <p>
-          The changes were not merged into
-          <a
-            :href="mr.targetBranchPath"
-            class="label-branch">
-            {{mr.targetBranch}}</a>.
-        </p>
-      </section>
+    <div class="mr-widget-body media">
+      <status-icon status="failed" />
+      <div class="media-body">
+        <mr-widget-author-and-time
+          actionText="Closed by"
+          :author="mr.closedBy"
+          :dateTitle="mr.updatedAt"
+          :dateReadable="mr.closedAt"
+        />
+        <section class="mr-info-list">
+          <p>
+            The changes were not merged into
+            <a
+              :href="mr.targetBranchPath"
+              class="label-branch">
+              {{mr.targetBranch}}</a>
+          </p>
+        </section>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
index 36596c6f37e753c63fabafeeacd7a1516229b5c6..f9cb79a0bc12d47b5da9ec3be8764a4208d42c2f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
@@ -1,27 +1,25 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetConflicts',
   props: {
     mr: { type: Object, required: true },
   },
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        There are merge conflicts.
-        <span v-if="!mr.canMerge">
-          Resolve these conflicts or ask someone with write access to this repository to merge it locally.
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          There are merge conflicts<span v-if="!mr.canMerge">.</span>
+          <span v-if="!mr.canMerge">
+            Resolve these conflicts or ask someone with write access to this repository to merge it locally
+          </span>
         </span>
-      </span>
-      <div
-        v-if="mr.canMerge"
-        class="btn-group">
         <a
-          v-if="mr.conflictResolutionPath"
+          v-if="mr.canMerge && mr.conflictResolutionPath"
           :href="mr.conflictResolutionPath"
           class="btn btn-default btn-xs js-resolve-conflicts-button">
           Resolve conflicts
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
index 600b4d42e3d445ec89ff6c0c800a2ef7597efcf9..1cb24549d53cf6ec3153752c0f0d0b2a8dcd8a96 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
@@ -1,3 +1,4 @@
+import statusIcon from '../mr_widget_status_icon';
 import eventHub from '../../event_hub';
 
 export default {
@@ -38,39 +39,40 @@ export default {
       }
     },
   },
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        class="btn btn-success btn-small"
-        disabled="true"
-        type="button">
-        Merge
-      </button>
-      <span
-        v-if="!isRefreshing"
-        class="bold danger">
-        <span
-          class="has-error-message"
-          v-if="mr.mergeError">
-          {{mr.mergeError}}
-        </span>
-        <span v-else>Merge failed.</span>
-        <span
-          :class="{ 'has-custom-error': mr.mergeError }">
-          Refreshing in {{timerText}} to show the updated status...
+    <div class="mr-widget-body media">
+      <template v-if="isRefreshing">
+        <status-icon status="loading" />
+        <span class="media-body bold js-refresh-label">
+          Refreshing now
         </span>
-        <button
-          @click="refresh"
-          class="btn btn-default btn-xs js-refresh-button"
-          type="button">
-          Refresh now
-        </button>
-      </span>
-      <span
-        v-if="isRefreshing"
-        class="bold js-refresh-label">
-        Refreshing now...
-      </span>
+      </template>
+      <template v-else>
+        <status-icon status="failed" showDisabledButton />
+        <div class="media-body space-children">
+          <span class="bold">
+            <span
+              class="has-error-message"
+              v-if="mr.mergeError">
+              {{mr.mergeError}}.
+            </span>
+            <span v-else>Merge failed.</span>
+            <span
+              :class="{ 'has-custom-error': mr.mergeError }">
+              Refreshing in {{timerText}} to show the updated status...
+            </span>
+          </span>
+          <button
+            @click="refresh"
+            class="btn btn-default btn-xs js-refresh-button"
+            type="button">
+            Refresh now
+          </button>
+        </div>
+      </template>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
index 0bd31731a0b051f5faf8d192d8730d76bd3bc5bc..a12f418e1af73ef7154b021c34f7dffb5624e915 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
@@ -1,24 +1,29 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetLocked',
   props: {
     mr: { type: Object, required: true },
   },
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body mr-state-locked">
-      <span class="state-label">Locked</span>
-      This merge request is in the process of being merged, during which time it is locked and cannot be closed.
-      <i
-        class="fa fa-spinner fa-spin"
-        aria-hidden="true" />
-      <section class="mr-info-list mr-links">
-        <div class="legend"></div>
-        <p>
-          The changes will be merged into
-          <span class="label-branch">
-            <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
-          </span>.
-        </p>
-      </section>
+    <div class="mr-widget-body mr-state-locked media">
+      <status-icon status="loading" />
+      <div class="media-body">
+        <h4>
+          This merge request is in the process of being merged, during which time it is locked and cannot be closed
+        </h4>
+        <section class="mr-info-list">
+          <p>
+            The changes will be merged into
+            <span class="label-branch">
+              <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
+            </span>
+          </p>
+        </section>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
index 419d174f3ff5ea90f52c107a4beef374520079fd..bdfd4d9667cbfd1561776c74dd1708f1f9d28a12 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
@@ -1,5 +1,5 @@
 /* global Flash */
-
+import statusIcon from '../mr_widget_status_icon';
 import MRWidgetAuthor from '../../components/mr_widget_author';
 import eventHub from '../../event_hub';
 
@@ -11,6 +11,7 @@ export default {
   },
   components: {
     'mr-widget-author': MRWidgetAuthor,
+    statusIcon,
   },
   data() {
     return {
@@ -61,56 +62,56 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-body">
-      <h4>
-        Set by
-        <mr-widget-author :author="mr.setToMWPSBy" />
-        to be merged automatically when the pipeline succeeds.
-        <a
-          v-if="mr.canCancelAutomaticMerge"
-          @click.prevent="cancelAutomaticMerge"
-          :disabled="isCancellingAutoMerge"
-          role="button"
-          href="#"
-          class="btn btn-xs btn-default js-cancel-auto-merge">
-          <i
-            v-if="isCancellingAutoMerge"
-            class="fa fa-spinner fa-spin"
-            aria-hidden="true" />
-            Cancel automatic merge
-        </a>
-      </h4>
-      <section class="mr-info-list">
-        <div class="legend"></div>
-        <p>The changes will be merged into
-          <a
-            :href="mr.targetBranchPath"
-            class="label-branch">
-            {{mr.targetBranch}}
-          </a>.
-        </p>
-        <p v-if="mr.shouldRemoveSourceBranch">
-          The source branch will be removed.
-        </p>
-        <p
-          v-else
-          class="with-button">
-          The source branch will not be removed.
+    <div class="mr-widget-body media">
+      <status-icon status="success" />
+      <div class="media-body">
+        <h4>
+          Set by
+          <mr-widget-author :author="mr.setToMWPSBy" />
+          to be merged automatically when the pipeline succeeds
           <a
-            v-if="canRemoveSourceBranch"
-            :disabled="isRemovingSourceBranch"
-            @click.prevent="removeSourceBranch"
+            v-if="mr.canCancelAutomaticMerge"
+            @click.prevent="cancelAutomaticMerge"
+            :disabled="isCancellingAutoMerge"
             role="button"
-            class="btn btn-xs btn-default js-remove-source-branch"
-            href="#">
+            href="#"
+            class="btn btn-xs btn-default js-cancel-auto-merge">
             <i
-            v-if="isRemovingSourceBranch"
-            class="fa fa-spinner fa-spin"
-            aria-hidden="true" />
-            Remove source branch
+              v-if="isCancellingAutoMerge"
+              class="fa fa-spinner fa-spin"
+              aria-hidden="true" />
+              Cancel automatic merge
           </a>
-        </p>
-      </section>
+        </h4>
+        <section class="mr-info-list">
+          <p>The changes will be merged into
+            <a
+              :href="mr.targetBranchPath"
+              class="label-branch">
+              {{mr.targetBranch}}
+            </a>
+          </p>
+          <p v-if="mr.shouldRemoveSourceBranch">
+            The source branch will be removed
+          </p>
+          <p v-else>
+            The source branch will not be removed
+            <a
+              v-if="canRemoveSourceBranch"
+              :disabled="isRemovingSourceBranch"
+              @click.prevent="removeSourceBranch"
+              role="button"
+              class="btn btn-xs btn-default js-remove-source-branch"
+              href="#">
+              <i
+              v-if="isRemovingSourceBranch"
+              class="fa fa-spinner fa-spin"
+              aria-hidden="true" />
+              Remove source branch
+            </a>
+          </p>
+        </section>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
index c7d32d181411a90a048e25b73862619c576625f9..e452260a4d0cccd932473cd1a9f840e52c07713f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
@@ -1,6 +1,9 @@
 /* global Flash */
 
 import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
+import tooltip from '../../../vue_shared/directives/tooltip';
+import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
+import statusIcon from '../mr_widget_status_icon';
 import eventHub from '../../event_hub';
 
 export default {
@@ -9,14 +12,19 @@ export default {
     mr: { type: Object, required: true },
     service: { type: Object, required: true },
   },
-  components: {
-    'mr-widget-author-and-time': mrWidgetAuthorTime,
-  },
   data() {
     return {
       isMakingRequest: false,
     };
   },
+  directives: {
+    tooltip,
+  },
+  components: {
+    'mr-widget-author-and-time': mrWidgetAuthorTime,
+    loadingIcon,
+    statusIcon,
+  },
   computed: {
     shouldShowRemoveSourceBranch() {
       const { sourceBranchRemoved, isRemovingSourceBranch, canRemoveSourceBranch } = this.mr;
@@ -55,75 +63,77 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-body">
-      <mr-widget-author-and-time
-        actionText="Merged by"
-        :author="mr.mergedBy"
-        :dateTitle="mr.updatedAt"
-        :dateReadable="mr.mergedAt" />
-      <section class="mr-info-list">
-        <div class="legend"></div>
-        <p>
-          The changes were merged into
-          <span class="label-branch">
-            <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
-          </span>
-        </p>
-        <p v-if="mr.sourceBranchRemoved">The source branch has been removed.</p>
-        <p v-if="shouldShowRemoveSourceBranch">
-          You can remove source branch now.
-          <button
-            @click="removeSourceBranch"
-            :class="{ disabled: isMakingRequest }"
-            type="button"
-            class="btn btn-xs btn-default js-remove-branch-button">
-            Remove Source Branch
-          </button>
-        </p>
-        <p v-if="shouldShowSourceBranchRemoving">
-          <i
-            class="fa fa-spinner fa-spin"
-            aria-hidden="true" />
-          The source branch is being removed.
-        </p>
-      </section>
-      <div
-        v-if="shouldShowMergedButtons"
-        class="merged-buttons clearfix">
-        <a
-          v-if="mr.canRevertInCurrentMR"
-          class="btn btn-close btn-sm has-tooltip"
-          href="#modal-revert-commit"
-          data-toggle="modal"
-          data-container="body"
-          title="Revert this merge request in a new merge request">
-          Revert
-        </a>
-        <a
-          v-else-if="mr.revertInForkPath"
-          class="btn btn-close btn-sm has-tooltip"
-          data-method="post"
-          :href="mr.revertInForkPath"
-          title="Revert this merge request in a new merge request">
-          Revert
-        </a>
-        <a
-          v-if="mr.canCherryPickInCurrentMR"
-          class="btn btn-default btn-sm has-tooltip"
-          href="#modal-cherry-pick-commit"
-          data-toggle="modal"
-          data-container="body"
-          title="Cherry-pick this merge request in a new merge request">
-          Cherry-pick
-        </a>
-        <a
-          v-else-if="mr.cherryPickInForkPath"
-          class="btn btn-default btn-sm has-tooltip"
-          data-method="post"
-          :href="mr.cherryPickInForkPath"
-          title="Cherry-pick this merge request in a new merge request">
-          Cherry-pick
-        </a>
+    <div class="mr-widget-body media">
+      <status-icon status="success" />
+      <div class="media-body">
+        <div class="space-children">
+          <mr-widget-author-and-time
+            actionText="Merged by"
+            :author="mr.mergedBy"
+            :dateTitle="mr.updatedAt"
+            :dateReadable="mr.mergedAt" />
+          <a
+            v-if="mr.canRevertInCurrentMR"
+            v-tooltip
+            class="btn btn-close btn-xs"
+            href="#modal-revert-commit"
+            data-toggle="modal"
+            data-container="body"
+            title="Revert this merge request in a new merge request">
+            Revert
+          </a>
+          <a
+            v-else-if="mr.revertInForkPath"
+            v-tooltip
+            class="btn btn-close btn-xs"
+            data-method="post"
+            :href="mr.revertInForkPath"
+            title="Revert this merge request in a new merge request">
+            Revert
+          </a>
+          <a
+            v-if="mr.canCherryPickInCurrentMR"
+            v-tooltip
+            class="btn btn-default btn-xs"
+            href="#modal-cherry-pick-commit"
+            data-toggle="modal"
+            data-container="body"
+            title="Cherry-pick this merge request in a new merge request">
+            Cherry-pick
+          </a>
+          <a
+            v-else-if="mr.cherryPickInForkPath"
+            v-tooltip
+            class="btn btn-default btn-xs"
+            data-method="post"
+            :href="mr.cherryPickInForkPath"
+            title="Cherry-pick this merge request in a new merge request">
+            Cherry-pick
+          </a>
+        </div>
+        <section class="mr-info-list">
+          <p>
+            The changes were merged into
+            <span class="label-branch">
+              <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
+            </span>
+          </p>
+          <p v-if="mr.sourceBranchRemoved">The source branch has been removed</p>
+          <p v-if="shouldShowRemoveSourceBranch" class="space-children">
+            <span>You can remove source branch now</span>
+            <button
+              @click="removeSourceBranch"
+              :disabled="isMakingRequest"
+              type="button"
+              class="btn btn-xs btn-default js-remove-branch-button">
+              Remove Source Branch
+            </button>
+          </p>
+          <p v-if="shouldShowSourceBranchRemoving">
+            <loading-icon inline />
+            <span>The source branch is being removed</span>
+          </p>
+        </section>
       </div>
     </div>
   `,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
index 328382485f65a1b1949c0337e356707554c4ee98..9f0a359d01a06ce86e5ebab84a3465d3f2c47674 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
@@ -1,3 +1,5 @@
+import statusIcon from '../mr_widget_status_icon';
+import tooltip from '../../../vue_shared/directives/tooltip';
 import mrWidgetMergeHelp from '../../components/mr_widget_merge_help';
 
 export default {
@@ -5,30 +7,37 @@ export default {
   props: {
     mr: { type: Object, required: true },
   },
+  directives: {
+    tooltip,
+  },
   components: {
     'mr-widget-merge-help': mrWidgetMergeHelp,
+    statusIcon,
   },
   computed: {
     missingBranchName() {
       return this.mr.sourceBranchRemoved ? 'source' : 'target';
     },
+    message() {
+      return `If the ${this.missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line`;
+    },
   },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold js-branch-text">
-        <span class="capitalize">
-          {{missingBranchName}}
-        </span> branch does not exist.
-        Please restore the {{missingBranchName}} branch or use a different {{missingBranchName}} branch.
-      </span>
-      <mr-widget-merge-help
-        :missing-branch="missingBranchName" />
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold js-branch-text">
+          <span class="capitalize">
+            {{missingBranchName}}
+          </span> branch does not exist.
+          Please restore it or use a different {{missingBranchName}} branch
+          <i
+            v-tooltip
+            class="fa fa-question-circle"
+            :title="message"
+            :aria-label="message"></i>
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
index 07169b349be4e9a0d9da1e7d85b6bf753f33d3a5..797511d4e3a40c84ef8af2ab9d08eb20bdd1b321 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
@@ -1,17 +1,19 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetNotAllowed',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        Ready to be merged automatically.
-        Ask someone with write access to this repository to merge this request.
-      </span>
+    <div class="mr-widget-body media">
+      <status-icon status="success" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          Ready to be merged automatically.
+          Ask someone with write access to this repository to merge this request
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
index 375a382615aeece6a7a4732fce4cac14d0be36ff..ebfd6765934a5fe61bc23bc60c1526bfb2b09406 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
@@ -12,7 +12,7 @@ export default {
     return { emptyStateSVG };
   },
   template: `
-    <div class="mr-widget-body empty-state">
+    <div class="mr-widget-body mr-widget-empty-state">
       <div class="row">
         <div class="artwork col-sm-5 col-sm-push-7 col-xs-12 text-center">
           <span v-html="emptyStateSVG"></span>
@@ -29,12 +29,14 @@ export default {
             Currently there are no changes in this merge request's source branch.
             Please push new commits or use a different branch.
           </p>
-          <a
-            v-if="mr.newBlobPath"
-            :href="mr.newBlobPath"
-            class="btn btn-inverted btn-save">
-            Create file
-          </a>
+          <div>
+            <a
+              v-if="mr.newBlobPath"
+              :href="mr.newBlobPath"
+              class="btn btn-inverted btn-save">
+              Create file
+            </a>
+          </div>
         </div>
       </div>
     </div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
index 31c53b679edb58129445b20026dfaa9d048ea0c9..167a0d4613aae041e72f26f20f6d0c5602727842 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetPipelineBlocked',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        Pipeline blocked. The pipeline for this merge request requires a manual action to proceed.
-      </span>
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          Pipeline blocked. The pipeline for this merge request requires a manual action to proceed
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
index 002820123ca17ce7957dc14255dcfe632c115ecc..c5be9a0530a89a8d4cf3248ce4066e9f733b8f82 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetPipelineBlocked',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        class="btn btn-success btn-small"
-        disabled="true"
-        type="button">
-        Merge
-      </button>
-      <span class="bold">
-        The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.
-      </span>
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
index fcd4fdaf09f64a97dd1e74939c52a2677e3980ae..651877540096e5ce3bc7c6a95f2a29067e835438 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
@@ -1,8 +1,8 @@
 /* global Flash */
-
 import successSvg from 'icons/_icon_status_success.svg';
 import warningSvg from 'icons/_icon_status_warning.svg';
 import simplePoll from '~/lib/utils/simple_poll';
+import statusIcon from '../mr_widget_status_icon';
 import eventHub from '../../event_hub';
 
 export default {
@@ -25,6 +25,9 @@ export default {
       warningSvg,
     };
   },
+  components: {
+    statusIcon,
+  },
   computed: {
     commitMessageLinkTitle() {
       const withDesc = 'Include description in commit message';
@@ -196,84 +199,98 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-body">
-      <span class="btn-group">
-        <button
-          @click="handleMergeButtonClick()"
-          :disabled="isMergeButtonDisabled"
-          :class="mergeButtonClass"
-          type="button">
-          <i
-            v-if="isMakingRequest"
-            class="fa fa-spinner fa-spin"
-            aria-hidden="true" />
-          {{mergeButtonText}}
-        </button>
-        <button
-          v-if="shouldShowMergeOptionsDropdown"
-          :disabled="isMergeButtonDisabled"
-          type="button"
-          class="btn btn-small btn-info dropdown-toggle"
-          data-toggle="dropdown">
-          <i
-            class="fa fa-caret-down"
-            aria-hidden="true" />
-          <span class="sr-only">
-            Select merge moment
+    <div class="mr-widget-body media">
+      <status-icon status="success" />
+      <div class="media-body">
+        <div class="media space-children">
+          <span class="btn-group">
+            <button
+              @click="handleMergeButtonClick()"
+              :disabled="isMergeButtonDisabled"
+              :class="mergeButtonClass"
+              type="button">
+              <i
+                v-if="isMakingRequest"
+                class="fa fa-spinner fa-spin"
+                aria-hidden="true" />
+              {{mergeButtonText}}
+            </button>
+            <button
+              v-if="shouldShowMergeOptionsDropdown"
+              :disabled="isMergeButtonDisabled"
+              type="button"
+              class="btn btn-small btn-info dropdown-toggle js-merge-moment"
+              data-toggle="dropdown"
+              aria-label="Select merge moment">
+              <i
+                class="fa fa-chevron-down"
+                aria-hidden="true" />
+            </button>
+            <ul
+              v-if="shouldShowMergeOptionsDropdown"
+              class="dropdown-menu dropdown-menu-right"
+              role="menu">
+              <li>
+                <a
+                  @click.prevent="handleMergeButtonClick(true)"
+                  class="merge_when_pipeline_succeeds"
+                  href="#">
+                  <span class="media">
+                    <span
+                      v-html="successSvg"
+                      class="merge-opt-icon"
+                      aria-hidden="true"></span>
+                    <span class="media-body merge-opt-title">Merge when pipeline succeeds</span>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a
+                  @click.prevent="handleMergeButtonClick(false, true)"
+                  class="accept-merge-request"
+                  href="#">
+                  <span class="media">
+                    <span
+                      v-html="warningSvg"
+                      class="merge-opt-icon"
+                      aria-hidden="true"></span>
+                    <span class="media-body merge-opt-title">Merge immediately</span>
+                  </span>
+                </a>
+              </li>
+            </ul>
           </span>
-        </button>
-        <ul
-          v-if="shouldShowMergeOptionsDropdown"
-          class="dropdown-menu dropdown-menu-right"
-          role="menu">
-          <li>
-            <a
-              @click.prevent="handleMergeButtonClick(true)"
-              class="merge_when_pipeline_succeeds"
-              href="#">
-              <span
-                v-html="successSvg"
-                class="merge-opt-icon"
-                aria-hidden="true"></span>
-              <span class="merge-opt-title">Merge when pipeline succeeds</span>
-            </a>
-          </li>
-          <li>
-            <a
-              @click.prevent="handleMergeButtonClick(false, true)"
-              class="accept-merge-request"
-              href="#">
-              <span
-                v-html="warningSvg"
-                class="merge-opt-icon"
-                aria-hidden="true"></span>
-              <span class="merge-opt-title">Merge immediately</span>
-            </a>
-          </li>
-        </ul>
-      </span>
-      <template v-if="isMergeAllowed()">
-        <label class="spacing">
-          <input
-            id="remove-source-branch-input"
-            v-model="removeSourceBranch"
-            :disabled="isRemoveSourceBranchButtonDisabled"
-            type="checkbox"/> Remove source branch
-        </label>
+          <div class="media-body space-children">
+            <template v-if="isMergeAllowed()">
+              <label>
+                <input
+                  id="remove-source-branch-input"
+                  v-model="removeSourceBranch"
+                  :disabled="isRemoveSourceBranchButtonDisabled"
+                  type="checkbox"/> Remove source branch
+              </label>
 
-        <!-- Placeholder for EE extension of this component -->
-        <squash-before-merge
-          v-if="shouldShowSquashBeforeMerge"
-          :mr="mr"
-          :is-merge-button-disabled="isMergeButtonDisabled" />
+              <!-- Placeholder for EE extension of this component -->
+              <squash-before-merge
+                v-if="shouldShowSquashBeforeMerge"
+                :mr="mr"
+                :is-merge-button-disabled="isMergeButtonDisabled" />
 
-        <button
-          @click="toggleCommitMessageEditor"
-          :disabled="isMergeButtonDisabled"
-          class="btn btn-default btn-xs"
-          type="button">
-          Modify commit message
-        </button>
+              <button
+                @click="toggleCommitMessageEditor"
+                :disabled="isMergeButtonDisabled"
+                class="btn btn-default btn-xs"
+                type="button">
+                Modify commit message
+              </button>
+            </template>
+            <template v-else>
+              <span class="bold">
+                The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
+              </span>
+            </template>
+          </div>
+        </div>
         <div
           v-if="showCommitMessageEditor"
           class="prepend-top-default commit-message-editor">
@@ -293,7 +310,7 @@ export default {
                   rows="14"
                   name="Commit message"></textarea>
               </div>
-              <p class="hint">Try to keep the first line under 52 characters and the others under 72.</p>
+              <p class="hint">Try to keep the first line under 52 characters and the others under 72</p>
               <div class="hint">
                 <a
                   @click.prevent="updateCommitMessage"
@@ -302,12 +319,7 @@ export default {
             </div>
           </div>
         </div>
-      </template>
-      <template v-else>
-        <span class="bold">
-          The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.
-        </span>
-      </template>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
index 79f8ef408e6860c568cb0bc82b6ea7c0000feb1f..89f38e5bd2a02019b9e43952c3c2f765e390e957 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetSHAMismatch',
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        The source branch HEAD has recently changed. Please reload the page and review the changes before merging.
-      </span>
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          The source branch HEAD has recently changed. Please reload the page and review the changes before merging
+        </span>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
index f4ab2d9fa5825b8c3919b6ce1f913c31c1a8f960..d762ca6e640c1ce2378855726c9ed1bd7e50216b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
@@ -1,27 +1,27 @@
+import statusIcon from '../mr_widget_status_icon';
+
 export default {
   name: 'MRWidgetUnresolvedDiscussions',
   props: {
     mr: { type: Object, required: true },
   },
+  components: {
+    statusIcon,
+  },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge
-      </button>
-      <span class="bold">
-        There are unresolved discussions. Please resolve these discussions
-        <span v-if="mr.canCreateIssue">or</span>
-        <span v-else>.</span>
-      </span>
-      <a
-        v-if="mr.createIssueToResolveDiscussionsPath"
-        :href="mr.createIssueToResolveDiscussionsPath"
-        class="btn btn-default btn-xs js-create-issue">
-        Create an issue to resolve them later
-      </a>
+    <div class="mr-widget-body media">
+      <status-icon status="failed" showDisabledButton />
+      <div class="media-body space-children">
+        <span class="bold">
+          There are unresolved discussions. Please resolve these discussions
+        </span>
+        <a
+          v-if="mr.createIssueToResolveDiscussionsPath"
+          :href="mr.createIssueToResolveDiscussionsPath"
+          class="btn btn-default btn-xs js-create-issue">
+          Create an issue to resolve them later
+        </a>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
index cb02ffe93bd970c04d6bd4cc3ce5e3362b469d0f..b11a06899cfc85b1dd321717866ce75eb756d277 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
@@ -1,4 +1,6 @@
 /* global Flash */
+import statusIcon from '../mr_widget_status_icon';
+import tooltip from '../../../vue_shared/directives/tooltip';
 import eventHub from '../../event_hub';
 
 export default {
@@ -7,11 +9,17 @@ export default {
     mr: { type: Object, required: true },
     service: { type: Object, required: true },
   },
+  directives: {
+    tooltip,
+  },
   data() {
     return {
       isMakingRequest: false,
     };
   },
+  components: {
+    statusIcon,
+  },
   methods: {
     removeWIP() {
       this.isMakingRequest = true;
@@ -29,20 +37,20 @@ export default {
     },
   },
   template: `
-    <div class="mr-widget-body">
-      <button
-        type="button"
-        class="btn btn-success btn-small"
-        disabled="true">
-        Merge</button>
-      <span class="bold">
-        This merge request is currently Work In Progress and therefore unable to merge
-      </span>
-      <template v-if="mr.removeWIPPath">
-        <i
-          class="fa fa-question-circle has-tooltip"
-          title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged." />
+    <div class="mr-widget-body media">
+      <status-icon status="failed" :showDisabledButton="Boolean(mr.removeWIPPath)" />
+      <div class="media-body space-children">
+        <span class="bold">
+          This is a Work in Progress
+          <i
+            v-tooltip
+            class="fa fa-question-circle"
+            title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged"
+            aria-label="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged">
+           </i>
+        </span>
         <button
+          v-if="mr.removeWIPPath"
           @click="removeWIP"
           :disabled="isMakingRequest"
           type="button"
@@ -53,7 +61,7 @@ export default {
             aria-hidden="true" />
             Resolve WIP status
         </button>
-      </template>
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index 2339a00ddd03384b3a3534dee903deb5247ef5b2..577d77f09a69ebee7129f6dd5365f45446e7b9a8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -35,8 +35,14 @@ import {
 export default {
   el: '#js-vue-mr-widget',
   name: 'MRWidget',
+  props: {
+    mrData: {
+      type: Object,
+      required: false,
+    },
+  },
   data() {
-    const store = new MRWidgetStore(gl.mrWidgetData);
+    const store = new MRWidgetStore(this.mrData || window.gl.mrWidgetData);
     const service = this.createService(store);
     return {
       mr: store,
@@ -234,14 +240,21 @@ export default {
         v-if="shouldRenderDeployments"
         :mr="mr"
         :service="service" />
-      <component
-        :is="componentName"
-        :mr="mr"
-        :service="service" />
-      <mr-widget-related-links
-        v-if="shouldRenderRelatedLinks"
-        :related-links="mr.relatedLinks" />
-      <mr-widget-merge-help v-if="shouldRenderMergeHelp" />
+      <div class="mr-widget-section">
+        <component
+          :is="componentName"
+          :mr="mr"
+          :service="service" />
+        <mr-widget-related-links
+          v-if="shouldRenderRelatedLinks"
+          :state="mr.state"
+          :related-links="mr.relatedLinks" />
+      </div>
+      <div
+        class="mr-widget-footer"
+        v-if="shouldRenderMergeHelp">
+        <mr-widget-merge-help />
+      </div>
     </div>
   `,
 };
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 6ce331a9129ee4abe9072e7bcfd9e37f90480be8..b2b3297e880ea1eb552dd918486866242bece373 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -26,6 +26,7 @@
 @import "framework/lists";
 @import "framework/logo";
 @import "framework/markdown_area";
+@import "framework/media_object";
 @import "framework/mobile";
 @import "framework/modal";
 @import "framework/nav";
diff --git a/app/assets/stylesheets/framework/media_object.scss b/app/assets/stylesheets/framework/media_object.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b573052c14affa5bdca02ac9e3e7a4168768925b
--- /dev/null
+++ b/app/assets/stylesheets/framework/media_object.scss
@@ -0,0 +1,8 @@
+.media {
+  display: flex;
+  align-items: flex-start;
+}
+
+.media-body {
+  flex: 1;
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 0df6f24bfe6e86bd8355fd65649967cb5a9ff1d7..1d0f10d6a326da8cc54155f9867fc58bacfdf9b9 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -206,7 +206,6 @@ $general-hover-transition-curve: linear;
 $highlight-changes-color: rgb(235, 255, 232);
 $performance-bar-height: 35px;
 
-
 /*
 * Common component specific colors
 */
@@ -315,6 +314,12 @@ $btn-white-active: #848484;
 $badge-bg: rgba(0, 0, 0, 0.07);
 $badge-color: $gl-text-color-secondary;
 
+/*
+ *  Status icons
+ */
+$status-icon-size: 22px;
+$status-icon-margin: $gl-btn-padding;
+
 /*
  *  Award emoji
  */
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index a4e190945088c063dcccc827afccad5ffb46ca09..6bb013cca85655f2f4bc02f1a2d27beda82932d3 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -2,10 +2,35 @@
  * MR -> show: Automerge widget
  *
  */
+
+.space-children {
+  @include clearfix;
+
+  > * {
+    float: left;
+  }
+
+  > *:not(:last-child) {
+    margin-right: 10px;
+  }
+}
+
 .mr-state-widget {
   color: $gl-text-color;
   border: 1px solid $border-color;
   border-radius: 2px;
+  line-height: 28px;
+
+  .mr-widget-heading,
+  .mr-widget-section,
+  .mr-widget-footer {
+    padding: $gl-padding;
+    border-top: solid 1px $border-color;
+  }
+
+  .mr-widget-footer {
+    padding: 0;
+  }
 
   form {
     margin-bottom: 0;
@@ -15,15 +40,35 @@
     }
   }
 
+  label {
+    margin-bottom: 0;
+  }
+
+  .btn {
+    font-size: $gl-font-size;
+
+    &[disabled] {
+      opacity: 0.3;
+    }
+
+    &.btn-xs {
+      line-height: 1;
+      padding: 5px 10px;
+      margin-top: 1px;
+    }
+
+    &.dropdown-toggle {
+      .fa {
+        color: inherit;
+      }
+    }
+  }
+
   .accept-merge-holder {
     .accept-action {
       display: inline-block;
       float: left;
 
-      .btn-success.dropdown-toggle .fa {
-        color: inherit;
-      }
-
       .accept-merge-request {
         &.ci-pending,
         &.ci-running {
@@ -84,77 +129,64 @@
 
   .ci-widget {
     color: $gl-text-color;
-    display: -webkit-flex;
     display: flex;
-    -webkit-align-items: center;
-    align-items: center;
-    padding: $gl-padding-top $gl-padding 0;
-
-    svg {
-      position: relative;
-      top: 1px;
-      overflow: visible;
-    }
-
-    > span {
-      padding-right: 4px;
-    }
 
     @media (max-width: $screen-xs-max) {
       flex-wrap: wrap;
     }
+  }
 
-    .icon-link > .ci-status-icon > svg {
-      width: 22px;
-      height: 22px;
-      margin-right: 8px;
-    }
+  .mr-widget-icon {
+    font-size: 22px;
+    margin-right: $status-icon-margin;
+  }
 
-    .ci-error {
-      margin-right: $btn-side-margin;
-    }
+  .ci-status-icon svg {
+    width: $status-icon-size;
+    height: $status-icon-size;
+    margin: 3px 0;
+    position: relative;
+    overflow: visible;
+    display: block;
   }
 
-  .mr-widget-body,
-  .mr-widget-footer {
-    margin: 16px;
+  .mr-widget-body {
+    @include clearfix;
+
+    &.media > *:first-child {
+      margin-right: 10px;
+    }
   }
 
   .mr-widget-pipeline-graph {
-    flex-shrink: 0;
+    padding: 0 4px;
 
     .dropdown-menu {
-      margin-top: 11px;
       z-index: 300;
     }
 
     .ci-action-icon-wrapper {
       line-height: 16px;
     }
+  }
 
-    @media (max-width: $screen-xs-max) {
-      order: 1;
-      margin-top: $gl-padding-top;
-      border-radius: 3px;
-      background-color: $white-light;
-      border: 1px solid $gray-darker;
-      width: 100%;
-      text-align: center;
+  .mini-pipeline-graph-dropdown-toggle {
+    vertical-align: top;
+  }
 
-      .dropdown-menu {
-        margin-left: -97.5px;
-      }
+  .mini-pipeline-graph-dropdown-menu .mini-pipeline-graph-dropdown-item {
+    display: flex;
+    align-items: center;
 
-      .arrow-up::before,
-      .arrow-up::after, {
-        margin-left: 97.5px;
-      }
+    .ci-status-text,
+    .ci-status-icon {
+      top: 0;
+      margin-right: 10px;
     }
   }
 
   .normal {
-    color: $gl-text-color;
-    font-size: 15px;
+    line-height: 28px;
   }
 
   .capitalize {
@@ -165,9 +197,8 @@
     @extend .ref-name;
 
     color: $gl-text-color;
-    font-weight: bold;
+    font-weight: 600;
     overflow: hidden;
-    margin: 0 3px;
     word-break: break-all;
 
     &.label-truncated {
@@ -189,52 +220,19 @@
     }
   }
 
-  .js-deployment-link {
-    display: inline-block;
-  }
-
   .mr-widget-help {
-    margin: $gl-padding;
-    color: $ci-skipped-color;
-  }
-
-  .mr-info-list {
-
-    &.mr-links {
-      margin-left: 28px;
-    }
-
-    &.mr-memory-usage {
-      margin: 5px 0 10px 25px;
-    }
-  }
-
-  .mr-widget-heading {
-    .btn-default.btn-xs {
-      margin-left: 5px;
-    }
-  }
-
-  .mr-widget-body {
-    .btn {
-      font-size: 15px;
-    }
-
-    .btn-group .btn {
-      padding: 5px 10px;
-
-      &.dropdown-toggle {
-        padding: 5px 7px;
-      }
-    }
+    padding: 10px 16px 10px 48px;
+    font-style: italic;
   }
 
   .mr-widget-body {
     h4 {
-      font-weight: bold;
-      font-size: 15px;
-      margin: 5px 0;
-      color: $gl-text-color;
+      float: left;
+      font-weight: 600;
+      font-size: 14px;
+      line-height: inherit;
+      margin-top: 0;
+      margin-bottom: 0;
 
       &.has-conflicts .fa-exclamation-triangle {
         color: $gl-warning;
@@ -255,18 +253,16 @@
     }
 
     .spacing {
-      margin: 0 $gl-padding;
+      margin: 0 0 0 10px;
     }
 
     .bold {
-      font-weight: bold;
-      font-size: 15px;
+      font-weight: 600;
       color: $gl-gray-light;
     }
 
     .state-label {
-      font-size: 16px;
-      font-weight: bold;
+      font-weight: 600;
       padding-right: 10px;
     }
 
@@ -274,16 +270,6 @@
       color: $gl-danger;
     }
 
-    .mr-widget-help {
-      margin: $gl-padding 0;
-    }
-
-    .with-button {
-      position: relative;
-      top: 6px;
-      margin-bottom: 24px;
-    }
-
     .spacing,
     .bold {
       vertical-align: middle;
@@ -294,15 +280,8 @@
         padding: 5px;
       }
 
-      .merge-opt-icon,
-      .merge-opt-title {
-        display: inline-block;
-        float: left;
-      }
-
-      .merge-opt-icon svg {
-        height: 15px;
-        width: 15px;
+      .merge-opt-icon {
+        line-height: 1.5;
       }
 
       .merge-opt-title {
@@ -316,34 +295,15 @@
       }
     }
 
-    .has-error-message + .has-custom-error {
-      margin-left: 0;
-    }
-
     .has-custom-error {
       display: inline-block;
-      margin-left: 70px;
-    }
-
-    .merge-error-text {
-      margin-left: 70px;
     }
 
     @media (max-width: $screen-xs-max) {
-      h4 {
-        font-size: 14px;
-      }
-
       p {
         font-size: 13px;
       }
 
-      .btn,
-      .btn-group,
-      .accept-action {
-        margin-bottom: 4px;
-      }
-
       .btn-grouped {
         float: none;
         margin-right: 0;
@@ -367,19 +327,16 @@
       }
     }
 
-    &.mr-state-locked .mr-info-list {
-      margin-top: 10px;
-      margin-left: 12px;
-    }
+    &.mr-widget-empty-state {
+      line-height: 20px;
 
-    &.empty-state {
       .artwork {
         margin-bottom: $gl-padding;
       }
 
       .text {
         span {
-          font-weight: bold;
+          font-weight: 600;
         }
 
         p {
@@ -389,10 +346,6 @@
     }
   }
 
-  .mr-widget-footer {
-    border-top: 1px solid $gray-darker;
-  }
-
   .ci-coverage {
     float: right;
   }
@@ -497,8 +450,6 @@
   }
 
   .btn-clipboard {
-    @extend .pull-right;
-
     margin-right: 20px;
     margin-top: 5px;
     position: absolute;
@@ -506,56 +457,29 @@
   }
 }
 
+.mr-links {
+  padding-left: $status-icon-size + $status-icon-margin;
+}
+
 .mr-info-list {
+  clear: left;
   position: relative;
-  margin: 10px 0 $gl-padding 12px;
+  padding-top: 4px;
 
   p {
-    margin: 6px 0;
+    margin: 0;
     position: relative;
-    padding-left: 15px;
-
-    &::before {
-      content: '';
-      position: absolute;
-      border-top: 2px solid $border-color;
-      height: 1px;
-      top: 9px;
-      width: 8px;
-      left: 0;
-    }
+    padding: 4px 0;
 
     &:last-child {
-      margin-bottom: 0;
+      padding-bottom: 0;
     }
   }
-
-  .legend {
-    height: 100%;
-    width: 2px;
-    background: $border-color;
-    position: absolute;
-    top: -9px;
-  }
 }
 
 .mr-info-list.mr-memory-usage {
-  .legend {
-    height: 65%;
-    top: 0;
-
-    @media (max-width: $screen-xs-max) {
-      height: 20px;
-    }
-  }
-
   p {
     float: left;
-    padding-left: 21px;
-
-    &::before {
-      top: 13px;
-    }
   }
 
   .memory-graph-container {
@@ -565,12 +489,13 @@
 }
 
 .mr-source-target {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  align-items: center;
   background-color: $gray-light;
-  border-radius: 3px 3px 0 0;
-  border-bottom: 1px solid $border-color;
-  padding: 0 $gl-padding;
-  margin-bottom: 6px;
-  line-height: 44px;
+  border-radius: $border-radius-default $border-radius-default 0 0;
+  padding: $gl-padding / 2 $gl-padding;
 
   .dropdown-toggle .fa {
     color: $gl-text-color;
@@ -679,14 +604,8 @@
 }
 
 .merged-buttons {
-  margin-top: 20px;
-
   .btn {
     float: left;
-
-    &:not(:last-child) {
-      margin-right: 10px;
-    }
   }
 }
 
@@ -803,20 +722,8 @@
 }
 
 .mr-memory-usage {
-  p.usage-info-loading,
-  p.usage-info-unavailable,
-  p.usage-info-failed {
-    margin-bottom: 5px;
-  }
-
   p.usage-info-loading .usage-info-load-spinner {
     margin-right: 10px;
     font-size: 16px;
   }
-
-  @media (max-width: $screen-md-min) {
-    .mr-info-list.mr-memory-usage .legend {
-      height: 80%;
-    }
-  }
 }
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index d3862df20d397cc3a995808e95442a8ccbfc7b09..6185342b495d9ad84395d01a1676810fc2b2ac46 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -220,7 +220,11 @@
     position: relative;
     vertical-align: middle;
     height: 22px;
-    margin: 3px 6px 3px 0;
+    margin: 3px 0;
+
+    + .stage-container {
+      margin-left: 6px;
+    }
 
     // Hack to show a button tooltip inline
     button.has-tooltip + .tooltip {
diff --git a/changelogs/unreleased/33095-mr-widget-ui.yml b/changelogs/unreleased/33095-mr-widget-ui.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9ce3086df27705a44c23440a069eaebf1904ac01
--- /dev/null
+++ b/changelogs/unreleased/33095-mr-widget-ui.yml
@@ -0,0 +1,4 @@
+---
+title: clean up merge request widget UI
+merge_request:
+author:
diff --git a/spec/features/merge_requests/closes_issues_spec.rb b/spec/features/merge_requests/closes_issues_spec.rb
index 0e97254eada02846f5c925769a591917f2963b08..299b4f5708a147328da383336a3cc7472bbeb12e 100644
--- a/spec/features/merge_requests/closes_issues_spec.rb
+++ b/spec/features/merge_requests/closes_issues_spec.rb
@@ -26,17 +26,11 @@ feature 'Merge Request closing issues message', js: true do
     wait_for_requests
   end
 
-  context 'not closing or mentioning any issue' do
-    it 'does not display closing issue message' do
-      expect(page).not_to have_css('.mr-widget-footer')
-    end
-  end
-
   context 'closing issues but not mentioning any other issue' do
     let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Closes issues #{issue_1.to_reference} and #{issue_2.to_reference}")
+      expect(page).to have_content("Closes #{issue_1.to_reference} and #{issue_2.to_reference}")
     end
   end
 
@@ -44,7 +38,7 @@ feature 'Merge Request closing issues message', js: true do
     let(:merge_request_description) { "Description\n\nRefers to #{issue_1.to_reference} and #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Issues #{issue_1.to_reference} and #{issue_2.to_reference} are mentioned but will not be closed.")
+      expect(page).to have_content("Mentions #{issue_1.to_reference} and #{issue_2.to_reference}")
     end
   end
 
@@ -52,8 +46,8 @@ feature 'Merge Request closing issues message', js: true do
     let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Closes issue #{issue_1.to_reference}.")
-      expect(page).to have_content("Issue #{issue_2.to_reference} is mentioned but will not be closed.")
+      expect(page).to have_content("Closes #{issue_1.to_reference}")
+      expect(page).to have_content("Mentions #{issue_2.to_reference}")
     end
   end
 
@@ -61,7 +55,7 @@ feature 'Merge Request closing issues message', js: true do
     let(:merge_request_title) { "closing #{issue_1.to_reference}, #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Closes issues #{issue_1.to_reference} and #{issue_2.to_reference}")
+      expect(page).to have_content("Closes #{issue_1.to_reference} and #{issue_2.to_reference}")
     end
   end
 
@@ -69,7 +63,7 @@ feature 'Merge Request closing issues message', js: true do
     let(:merge_request_title) { "Refers to #{issue_1.to_reference} and #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Issues #{issue_1.to_reference} and #{issue_2.to_reference} are mentioned but will not be closed.")
+      expect(page).to have_content("Mentions #{issue_1.to_reference} and #{issue_2.to_reference}")
     end
   end
 
@@ -77,8 +71,8 @@ feature 'Merge Request closing issues message', js: true do
     let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" }
 
     it 'does not display closing issue message' do
-      expect(page).to have_content("Closes issue #{issue_1.to_reference}. Issue #{issue_2.to_reference} is mentioned but will not be closed.")
-      expect(page).to have_content("Issue #{issue_2.to_reference} is mentioned but will not be closed.")
+      expect(page).to have_content("Closes #{issue_1.to_reference}")
+      expect(page).to have_content("Mentions #{issue_2.to_reference}")
     end
   end
 end
diff --git a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
index 574f5fe353edd9d0a2851523c5f15da14e65a475..ac46cc1f0e46f38854e1cc82eb5ede5a5821a38b 100644
--- a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
@@ -41,8 +41,8 @@ feature 'Merge When Pipeline Succeeds', :js do
         it 'activates the Merge when pipeline succeeds feature' do
           click_button "Merge when pipeline succeeds"
 
-          expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds."
-          expect(page).to have_content "The source branch will not be removed."
+          expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
+          expect(page).to have_content "The source branch will not be removed"
           expect(page).to have_selector ".js-cancel-auto-merge"
           visit_merge_request(merge_request) # Needed to refresh the page
           expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
@@ -97,11 +97,11 @@ feature 'Merge When Pipeline Succeeds', :js do
 
     describe 'enabling Merge when pipeline succeeds via dropdown' do
       it 'activates the Merge when pipeline succeeds feature' do
-        click_button 'Select merge moment'
+        find('.js-merge-moment').click
         click_link 'Merge when pipeline succeeds'
 
-        expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds."
-        expect(page).to have_content "The source branch will not be removed."
+        expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
+        expect(page).to have_content "The source branch will not be removed"
         expect(page).to have_link "Cancel automatic merge"
       end
     end
diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb
index 5c6eec44ff76bd2a868d15eba6bf0b467e61ceae..59e6742033351a0eef4eb3ed08c9897d7068bc0c 100644
--- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb
+++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb
@@ -43,7 +43,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
           wait_for_requests
 
           expect(page).to have_button 'Merge when pipeline succeeds'
-          expect(page).not_to have_button 'Select merge moment'
+          expect(page).not_to have_button '.js-merge-moment'
         end
       end
 
@@ -56,7 +56,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
           wait_for_requests
 
           expect(page).to have_css('button[disabled="disabled"]', text: 'Merge')
-          expect(page).to have_content('Please retry the job or push a new commit to fix the failure.')
+          expect(page).to have_content('Please retry the job or push a new commit to fix the failure')
         end
       end
 
@@ -69,7 +69,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
           wait_for_requests
 
           expect(page).not_to have_button 'Merge'
-          expect(page).to have_content('Please retry the job or push a new commit to fix the failure.')
+          expect(page).to have_content('Please retry the job or push a new commit to fix the failure')
         end
       end
 
@@ -113,7 +113,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
 
           expect(page).to have_button 'Merge when pipeline succeeds'
 
-          click_button 'Select merge moment'
+          page.find('.js-merge-moment').click
           expect(page).to have_content 'Merge immediately'
         end
       end
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js
index ab8a3f6c64c3a5bcda49ac3961bbaaa3f1b9cf45..7ee998c8fce96e317c3bbdaba7a8f21b1428aea7 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js
@@ -1,7 +1,6 @@
 import Vue from 'vue';
 import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment';
 import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-import { statusIconEntityMap } from '~/vue_shared/ci_status_icons';
 
 const deploymentMockData = [
   {
@@ -43,15 +42,6 @@ describe('MRWidgetDeployment', () => {
     });
   });
 
-  describe('computed', () => {
-    describe('svg', () => {
-      it('should have the proper SVG icon', () => {
-        const vm = createComponent(deploymentMockData);
-        expect(vm.svg).toEqual(statusIconEntityMap.icon_status_success);
-      });
-    });
-  });
-
   describe('methods', () => {
     let vm = createComponent();
     const deployment = deploymentMockData[0];
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
index 6adcbc73ed7a25f415ca544a559b02eb89cad0c0..2ae3adc1f93fa3b3a35b0b09175da84c18110af2 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
@@ -52,10 +52,10 @@ const createComponent = () => {
 };
 
 const messages = {
-  loadingMetrics: 'Loading deployment statistics.',
+  loadingMetrics: 'Loading deployment statistics',
   hasMetrics: 'Memory usage unchanged from 0MB to 0MB',
-  loadFailed: 'Failed to load deployment statistics.',
-  metricsUnavailable: 'Deployment statistics are not available currently.',
+  loadFailed: 'Failed to load deployment statistics',
+  metricsUnavailable: 'Deployment statistics are not available currently',
 };
 
 describe('MemoryUsage', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 647b59520f8a1779ba35072082dbc03fe7efe0d8..c763487d12f39d3704c8e7ffbaa5c6ad983544fc 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -81,13 +81,12 @@ describe('MRWidgetPipeline', () => {
       expect(el.querySelectorAll('.ci-status-icon.ci-status-icon-success').length).toEqual(1);
       expect(el.querySelector('.pipeline-id').textContent).toContain(`#${pipeline.id}`);
       expect(el.innerText).toContain('passed');
-      expect(el.innerText).toContain('with stages');
       expect(el.querySelector('.pipeline-id').getAttribute('href')).toEqual(pipeline.path);
       expect(el.querySelectorAll('.stage-container').length).toEqual(2);
       expect(el.querySelector('.js-ci-error')).toEqual(null);
       expect(el.querySelector('.js-commit-link').getAttribute('href')).toEqual(pipeline.commit.commit_path);
       expect(el.querySelector('.js-commit-link').textContent).toContain(pipeline.commit.short_id);
-      expect(el.querySelector('.js-mr-coverage').textContent).toContain(`Coverage ${pipeline.coverage}%.`);
+      expect(el.querySelector('.js-mr-coverage').textContent).toContain(`Coverage ${pipeline.coverage}%`);
     });
 
     it('should list single stage', (done) => {
@@ -95,7 +94,6 @@ describe('MRWidgetPipeline', () => {
 
       Vue.nextTick(() => {
         expect(el.querySelectorAll('.stage-container button').length).toEqual(1);
-        expect(el.innerText).toContain('with stage');
         done();
       });
     });
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
index f6e0c3dfb746cf946e837f9a6b35036fa0d43a6c..f86fb6a0b4b2d3d98a96958dfb7c2402c5281b8c 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
@@ -22,15 +22,16 @@ describe('MRWidgetRelatedLinks', () => {
   });
 
   describe('computed', () => {
+    const data = {
+      relatedLinks: {
+        closing: '/foo',
+        mentioned: '/foo',
+        assignToMe: '/foo',
+      },
+    };
+
     describe('hasLinks', () => {
       it('should return correct value when we have links reference', () => {
-        const data = {
-          relatedLinks: {
-            closing: '/foo',
-            mentioned: '/foo',
-            assignToMe: '/foo',
-          },
-        };
         const vm = createComponent(data);
         expect(vm.hasLinks).toBeTruthy();
 
@@ -44,44 +45,24 @@ describe('MRWidgetRelatedLinks', () => {
         expect(vm.hasLinks).toBeFalsy();
       });
     });
-  });
-
-  describe('methods', () => {
-    const data = {
-      relatedLinks: {
-        closing: '<a href="#">#23</a> and <a>#42</a>',
-        mentioned: '<a href="#">#7</a>',
-      },
-    };
-    const vm = createComponent(data);
-
-    describe('hasMultipleIssues', () => {
-      it('should return true if the given text has multiple issues', () => {
-        expect(vm.hasMultipleIssues(data.relatedLinks.closing)).toBeTruthy();
-      });
-
-      it('should return false if the given text has one issue', () => {
-        expect(vm.hasMultipleIssues(data.relatedLinks.mentioned)).toBeFalsy();
-      });
-    });
 
-    describe('issueLabel', () => {
-      it('should return true if the given text has multiple issues', () => {
-        expect(vm.issueLabel('closing')).toEqual('issues');
-      });
-
-      it('should return false if the given text has one issue', () => {
-        expect(vm.issueLabel('mentioned')).toEqual('issue');
+    describe('closesText', () => {
+      it('returns correct text for open merge request', () => {
+        data.state = 'open';
+        const vm = createComponent(data);
+        expect(vm.closesText).toEqual('Closes');
       });
-    });
 
-    describe('verbLabel', () => {
-      it('should return true if the given text has multiple issues', () => {
-        expect(vm.verbLabel('closing')).toEqual('are');
+      it('returns correct text for closed merge request', () => {
+        data.state = 'closed';
+        const vm = createComponent(data);
+        expect(vm.closesText).toEqual('Did not close');
       });
 
-      it('should return false if the given text has one issue', () => {
-        expect(vm.verbLabel('mentioned')).toEqual('is');
+      it('returns correct tense for merged request', () => {
+        data.state = 'merged';
+        const vm = createComponent(data);
+        expect(vm.closesText).toEqual('Closed');
       });
     });
   });
@@ -95,8 +76,8 @@ describe('MRWidgetRelatedLinks', () => {
       });
       const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim();
 
-      expect(content).toContain('Closes issues #23 and #42');
-      expect(content).not.toContain('mentioned');
+      expect(content).toContain('Closes #23 and #42');
+      expect(content).not.toContain('Mentions');
     });
 
     it('should have only have mentioned issues text', () => {
@@ -106,8 +87,7 @@ describe('MRWidgetRelatedLinks', () => {
         },
       });
 
-      expect(vm.$el.innerText).toContain('issue #7');
-      expect(vm.$el.innerText).toContain('is mentioned but will not be closed.');
+      expect(vm.$el.innerText).toContain('Mentions #7');
       expect(vm.$el.innerText).not.toContain('Closes');
     });
 
@@ -120,9 +100,8 @@ describe('MRWidgetRelatedLinks', () => {
       });
       const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim();
 
-      expect(content).toContain('Closes issue #7.');
-      expect(content).toContain('issues #23 and #42');
-      expect(content).toContain('are mentioned but will not be closed.');
+      expect(content).toContain('Closes #7');
+      expect(content).toContain('Mentions #23 and #42');
     });
 
     it('should have assing issues link', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
index cac2f561a0b373b0f2786c6f738a3db2e4ec9d86..4869fb17d96c7e604ef2944e9997978c11e2b91b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
@@ -12,7 +12,7 @@ describe('MRWidgetArchived', () => {
       expect(el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy();
       expect(el.querySelector('button').disabled).toBeTruthy();
-      expect(el.innerText).toContain('This project is archived, write access has been disabled.');
+      expect(el.innerText).toContain('This project is archived, write access has been disabled');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
index 47b4ba893e0247ef284477716edaf278fb6762a5..6042d7384d581e4141dd5bc78f76d23b38d1538b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
@@ -24,8 +24,8 @@ describe('MRWidgetAutoMergeFailed', () => {
 
     it('should have correct elements', () => {
       expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
-      expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
-      expect(vm.$el.innerText).toContain('This merge request failed to be merged automatically.');
+      expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeFalsy();
+      expect(vm.$el.innerText).toContain('This merge request failed to be merged automatically');
       expect(vm.$el.innerText).toContain(mergeError);
     });
   });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
index 3be11d47227fe95fe9f20c72bf8c1c7530e57b88..6b7aa935ad34a001f5432ba61d5b12e978ee6907 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
@@ -12,7 +12,7 @@ describe('MRWidgetChecking', () => {
       expect(el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy();
       expect(el.querySelector('button').disabled).toBeTruthy();
-      expect(el.innerText).toContain('Checking ability to merge automatically.');
+      expect(el.innerText).toContain('Checking ability to merge automatically');
       expect(el.querySelector('i')).toBeDefined();
     });
   });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index e7ae85caec4cca9a5af55e5eb7691c5c65ffb43b..3b7b7d936624df7b44c67cbc435f97fbd2ed85d5 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -29,15 +29,16 @@ describe('MRWidgetConflicts', () => {
   describe('template', () => {
     it('should have correct elements', () => {
       const el = createComponent().$el;
-      const resolveButton = el.querySelectorAll('.btn-group .btn')[0];
-      const mergeLocallyButton = el.querySelectorAll('.btn-group .btn')[1];
+      const resolveButton = el.querySelector('.js-resolve-conflicts-button');
+      const mergeButton = el.querySelector('.mr-widget-body .btn');
+      const mergeLocallyButton = el.querySelector('.js-merge-locally-button');
 
-      expect(el.textContent).toContain('There are merge conflicts.');
+      expect(el.textContent).toContain('There are merge conflicts');
       expect(el.textContent).not.toContain('ask someone with write access');
       expect(el.querySelector('.btn-success').disabled).toBeTruthy();
-      expect(el.querySelectorAll('.btn-group .btn').length).toBe(2);
       expect(resolveButton.textContent).toContain('Resolve conflicts');
       expect(resolveButton.getAttribute('href')).toEqual(path);
+      expect(mergeButton.textContent).toContain('Merge');
       expect(mergeLocallyButton.textContent).toContain('Merge locally');
     });
 
@@ -59,8 +60,8 @@ describe('MRWidgetConflicts', () => {
       it('should not have action buttons', (done) => {
         Vue.nextTick(() => {
           expect(vm.$el.querySelectorAll('.btn').length).toBe(1);
-          expect(vm.$el.querySelector('a.js-resolve-conflicts-button')).toEqual(null);
-          expect(vm.$el.querySelector('a.js-merge-locally-button')).toEqual(null);
+          expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toEqual(null);
+          expect(vm.$el.querySelector('.js-merge-locally-button')).toEqual(null);
           done();
         });
       });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
index 587b83430d9fe18276ff77821f2c43fc811e8e39..cef365eec8a5faa0ed83efeeb08720fc9395d556 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -94,7 +94,7 @@ describe('MRWidgetFailedToMerge', () => {
       expect(el.querySelector('button').innerText).toContain('Merge');
       expect(el.querySelector('.js-refresh-button').innerText).toContain('Refresh now');
       expect(el.querySelector('.js-refresh-label')).toEqual(null);
-      expect(el.innerText).not.toContain('Refreshing now...');
+      expect(el.innerText).not.toContain('Refreshing now');
       setTimeout(() => {
         expect(el.innerText).toContain('Refreshing in 9 seconds');
         done();
@@ -115,7 +115,7 @@ describe('MRWidgetFailedToMerge', () => {
       vm.refresh();
       Vue.nextTick(() => {
         expect(el.innerText).not.toContain('Merge failed. Refreshing');
-        expect(el.innerText).toContain('Refreshing now...');
+        expect(el.innerText).toContain('Refreshing now');
       });
     });
   });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
index 8d8b90cea168de9af431cf1ab313d31d3a1924ba..9a71d0b47d79bbdeecf98edc02994d6491bf234c 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
@@ -162,10 +162,10 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
 
     it('should have correct elements', () => {
       expect(el.classList.contains('mr-widget-body')).toBeTruthy();
-      expect(el.innerText).toContain('to be merged automatically when the pipeline succeeds.');
+      expect(el.innerText).toContain('to be merged automatically when the pipeline succeeds');
       expect(el.innerText).toContain('The changes will be merged into');
       expect(el.innerText).toContain(targetBranch);
-      expect(el.innerText).toContain('The source branch will not be removed.');
+      expect(el.innerText).toContain('The source branch will not be removed');
       expect(el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge');
       expect(el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
       expect(el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch');
@@ -186,8 +186,8 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
 
       Vue.nextTick(() => {
         const normalizedText = el.innerText.replace(/\s+/g, ' ');
-        expect(normalizedText).toContain('The source branch will be removed.');
-        expect(normalizedText).not.toContain('The source branch will not be removed.');
+        expect(normalizedText).toContain('The source branch will be removed');
+        expect(normalizedText).not.toContain('The source branch will not be removed');
         done();
       });
     });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
index 6628010112d4c3c02e09848ac465e5e50877bfc7..afaa750199a5e932c1e0e8f74a50242a479822a1 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -142,19 +142,19 @@ describe('MRWidgetMerged', () => {
       expect(el.querySelector('.js-mr-widget-author')).toBeDefined();
       expect(el.innerText).toContain('The changes were merged into');
       expect(el.innerText).toContain(targetBranch);
-      expect(el.innerText).toContain('The source branch has been removed.');
+      expect(el.innerText).toContain('The source branch has been removed');
       expect(el.innerText).toContain('Revert');
       expect(el.innerText).toContain('Cherry-pick');
-      expect(el.innerText).not.toContain('You can remove source branch now.');
-      expect(el.innerText).not.toContain('The source branch is being removed.');
+      expect(el.innerText).not.toContain('You can remove source branch now');
+      expect(el.innerText).not.toContain('The source branch is being removed');
     });
 
     it('should not show source branch removed text', (done) => {
       vm.mr.sourceBranchRemoved = false;
 
       Vue.nextTick(() => {
-        expect(el.innerText).toContain('You can remove source branch now.');
-        expect(el.innerText).not.toContain('The source branch has been removed.');
+        expect(el.innerText).toContain('You can remove source branch now');
+        expect(el.innerText).not.toContain('The source branch has been removed');
         done();
       });
     });
@@ -164,9 +164,9 @@ describe('MRWidgetMerged', () => {
       vm.mr.sourceBranchRemoved = false;
 
       Vue.nextTick(() => {
-        expect(el.innerText).toContain('The source branch is being removed.');
-        expect(el.innerText).not.toContain('You can remove source branch now.');
-        expect(el.innerText).not.toContain('The source branch has been removed.');
+        expect(el.innerText).toContain('The source branch is being removed');
+        expect(el.innerText).not.toContain('You can remove source branch now');
+        expect(el.innerText).not.toContain('The source branch has been removed');
         done();
       });
     });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
index 98674d12afb4bbc8f5f6ccafb3b37a252c210ddd..720effb5c1cb6a85877810bee3c6bfb885f26c5c 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
@@ -49,7 +49,7 @@ describe('MRWidgetMissingBranch', () => {
       expect(el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
       expect(content).toContain('source branch does not exist.');
-      expect(content).toContain('Please restore the source branch or use a different source branch.');
+      expect(content).toContain('Please restore it or use a different source branch');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
index 61e00f4cf79c4a940a4c6bef343cf24302dbebbf..33f20ab132de48ee6d1b17fbeddd3fd9058ec20b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
@@ -11,7 +11,7 @@ describe('MRWidgetNotAllowed', () => {
       expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
       expect(vm.$el.innerText).toContain('Ready to be merged automatically.');
-      expect(vm.$el.innerText).toContain('Ask someone with write access to this repository to merge this request.');
+      expect(vm.$el.innerText).toContain('Ask someone with write access to this repository to merge this request');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
index b293d1185710b7e1d57bdcf50753cf882d1f0c7d..d0702f9f50338ebc2051b2e3704a7ed8e0fb0000 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
@@ -10,7 +10,7 @@ describe('MRWidgetPipelineBlocked', () => {
     it('should have correct elements', () => {
       expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
-      expect(vm.$el.innerText).toContain('Pipeline blocked. The pipeline for this merge request requires a manual action to proceed.');
+      expect(vm.$el.innerText).toContain('Pipeline blocked. The pipeline for this merge request requires a manual action to proceed');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
index 807fba705d41a2be24ea491eab85aa9699ef36e4..78bac1c61a5f6c272a9454eb2ddade457ec4ab32 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -10,7 +10,7 @@ describe('MRWidgetPipelineFailed', () => {
     it('should have correct elements', () => {
       expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
-      expect(vm.$el.innerText).toContain('The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.');
+      expect(vm.$el.innerText).toContain('The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 732b516badd301a9c038fe1c5019dbf52f2eb175..c607c9746a4c210376a9fd951547bb0e21a090bc 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -72,7 +72,7 @@ describe('MRWidgetReadyToMerge', () => {
       const withDesc = 'Include description in commit message';
       const withoutDesc = "Don't include description in commit message";
 
-      it('should return message wit description', () => {
+      it('should return message with description', () => {
         expect(vm.commitMessageLinkTitle).toEqual(withDesc);
       });
 
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
index 5fb1d69a8b364d76f4c7ddcbb888b7ecfe18d4bc..4c67504b642af7bac340d25c58215dbbe8e1f072 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
@@ -10,7 +10,7 @@ describe('MRWidgetSHAMismatch', () => {
     it('should have correct elements', () => {
       expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
       expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
-      expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging.');
+      expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging');
     });
   });
 });
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
index 45bd1a6996454b1cb6e832f55f63a705f7b06797..2cb3aaa6951e0e99a743601d3fbb3e9eed3b2aa2 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -78,7 +78,7 @@ describe('MRWidgetWIP', () => {
 
     it('should have correct elements', () => {
       expect(el.classList.contains('mr-widget-body')).toBeTruthy();
-      expect(el.innerText).toContain('This merge request is currently Work In Progress and therefore unable to merge');
+      expect(el.innerText).toContain('This is a Work in Progress');
       expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
       expect(el.querySelector('button').innerText).toContain('Merge');
       expect(el.querySelector('.js-remove-wip').innerText).toContain('Resolve WIP status');
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index e6f96d5588ba4a33c670c1fcc02bcb47f51c72b4..ad2f28b24f02cb39286f772bee661cf993a2c57a 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -30,6 +30,7 @@ export default {
   "merge_user_id": null,
   "merge_when_pipeline_succeeds": false,
   "source_branch": "daaaa",
+  "source_branch_link": "daaaa",
   "source_project_id": 19,
   "target_branch": "master",
   "target_project_id": 19,