diff --git a/apps/dashboard/js/dashboard.js b/apps/dashboard/js/dashboard.js
index 5e046c7924c30510ad9f66216a93245677e7ca66..ddc28fcdd9bd55f3907832b11661b6eb19baf207 100644
Binary files a/apps/dashboard/js/dashboard.js and b/apps/dashboard/js/dashboard.js differ
diff --git a/apps/dashboard/js/dashboard.js.map b/apps/dashboard/js/dashboard.js.map
index 15797b4628160710cb816e754aa7b4d03fd06996..342df6e3bcb24d3397e18b181db74de15cf69572 100644
Binary files a/apps/dashboard/js/dashboard.js.map and b/apps/dashboard/js/dashboard.js.map differ
diff --git a/apps/files/js/dist/personal-settings.js b/apps/files/js/dist/personal-settings.js
index c7b5ef759faeef87182b48e8a70c1b9e5de61526..be56fe43a4069ecaab54e29236cc509bf4499d87 100644
Binary files a/apps/files/js/dist/personal-settings.js and b/apps/files/js/dist/personal-settings.js differ
diff --git a/apps/files/js/dist/personal-settings.js.map b/apps/files/js/dist/personal-settings.js.map
index a2d787a264072286d150e289c1e6bb01b14acee9..4e08921d8dc8cb7734f31687bd5d68afd909afee 100644
Binary files a/apps/files/js/dist/personal-settings.js.map and b/apps/files/js/dist/personal-settings.js.map differ
diff --git a/apps/files/js/dist/sidebar.js b/apps/files/js/dist/sidebar.js
index 6136fe1958a42914fb36dd8dd7ca84293d18e622..ddcff7405072220524bd7a944858a042ad446b58 100644
Binary files a/apps/files/js/dist/sidebar.js and b/apps/files/js/dist/sidebar.js differ
diff --git a/apps/files/js/dist/sidebar.js.map b/apps/files/js/dist/sidebar.js.map
index 09fb8f25b149f32e3a08eee281a0ce5e64b1a6ab..14dfff7bb316d140e3dd7d356df34e711b1cf236 100644
Binary files a/apps/files/js/dist/sidebar.js.map and b/apps/files/js/dist/sidebar.js.map differ
diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js b/apps/files_sharing/js/dist/files_sharing_tab.js
index b50abdbd779b2122dff2e9797654a5b2e7827397..5ce0c586009a77235d6075b2aa532116ba0f8394 100644
Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js and b/apps/files_sharing/js/dist/files_sharing_tab.js differ
diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js.map b/apps/files_sharing/js/dist/files_sharing_tab.js.map
index 69ba9ec688730fe13ef9bb41df0cf8085df8adbd..fa6243aff70c95b68f441966f1b0d13d6e3e0635 100644
Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js.map and b/apps/files_sharing/js/dist/files_sharing_tab.js.map differ
diff --git a/apps/settings/js/vue-settings-admin-security.js b/apps/settings/js/vue-settings-admin-security.js
index b389530e0e8c6247aad99e2c868325af328d7683..ff5039b3974eab928f272edaad72e1432f37fc92 100644
Binary files a/apps/settings/js/vue-settings-admin-security.js and b/apps/settings/js/vue-settings-admin-security.js differ
diff --git a/apps/settings/js/vue-settings-admin-security.js.map b/apps/settings/js/vue-settings-admin-security.js.map
index ff94b2915b40a4c01a0c9fed2c484b955525f7b6..865b5417905efa55e564b54845c137181a22dbc4 100644
Binary files a/apps/settings/js/vue-settings-admin-security.js.map and b/apps/settings/js/vue-settings-admin-security.js.map differ
diff --git a/apps/settings/js/vue-settings-apps-users-management.js b/apps/settings/js/vue-settings-apps-users-management.js
index e019f4950dcb27de743166de9934e4ee0fe47529..0b59b9f7344045b1e2d8b065f7d3302e4113f837 100644
Binary files a/apps/settings/js/vue-settings-apps-users-management.js and b/apps/settings/js/vue-settings-apps-users-management.js differ
diff --git a/apps/settings/js/vue-settings-apps-users-management.js.map b/apps/settings/js/vue-settings-apps-users-management.js.map
index 285e335dbac5ffb2e00f244f0999638c399b86e0..bbf376e22f8094636caf94ded68bcaadcf4040dc 100644
Binary files a/apps/settings/js/vue-settings-apps-users-management.js.map and b/apps/settings/js/vue-settings-apps-users-management.js.map differ
diff --git a/apps/settings/js/vue-settings-personal-security.js b/apps/settings/js/vue-settings-personal-security.js
index 59efe314dace5bd1ebdf9e6ae76692a6d234498f..fa2630d1450b1a77129f91f3a9d67c522df9affa 100644
Binary files a/apps/settings/js/vue-settings-personal-security.js and b/apps/settings/js/vue-settings-personal-security.js differ
diff --git a/apps/settings/js/vue-settings-personal-security.js.map b/apps/settings/js/vue-settings-personal-security.js.map
index 7d3f4c87386dea542c6094676e7302ec9c20f7ee..2dfa970b22b2434a9a944850a0b3df479de43abb 100644
Binary files a/apps/settings/js/vue-settings-personal-security.js.map and b/apps/settings/js/vue-settings-personal-security.js.map differ
diff --git a/apps/settings/js/vue-settings-personal-webauthn.js b/apps/settings/js/vue-settings-personal-webauthn.js
index 78dbaa73703b721336a21aacaa473d44dc8e9f7b..f9c11c69f5b8098d011b3cf42cd78011e5b67af9 100644
Binary files a/apps/settings/js/vue-settings-personal-webauthn.js and b/apps/settings/js/vue-settings-personal-webauthn.js differ
diff --git a/apps/settings/js/vue-settings-personal-webauthn.js.map b/apps/settings/js/vue-settings-personal-webauthn.js.map
index 789082827deb1fd8a7d074eb95d6c7257fecbbb2..94cadd41f8a481e96300aecbf74707f7a0b333d7 100644
Binary files a/apps/settings/js/vue-settings-personal-webauthn.js.map and b/apps/settings/js/vue-settings-personal-webauthn.js.map differ
diff --git a/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js
new file mode 100644
index 0000000000000000000000000000000000000000..7305c753f3f8bfe1d019b80bfdd46c5b12a38dc1
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js differ
diff --git a/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..55b5ba548e7ea86e63c1ef72230adc722022ffc2
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map differ
diff --git a/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js
new file mode 100644
index 0000000000000000000000000000000000000000..f0e1c1d2c2012c509fa1cc8c7a25b98f17a75298
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js differ
diff --git a/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..08f81bf5abc86b10b547f716cc0ecc4979801cff
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map differ
diff --git a/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js
new file mode 100644
index 0000000000000000000000000000000000000000..d92450f77b2fe885385bf114d3de75c853e66ae1
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js differ
diff --git a/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..7a04c3d6a956fdb933d450cc7302330c458da425
Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map differ
diff --git a/apps/updatenotification/js/updatenotification.js b/apps/updatenotification/js/updatenotification.js
index 0a5a0e159010c17be569b92ed69ba9440849e0bf..3619bf9165f6667905721bb62ec9162b2aca7227 100644
Binary files a/apps/updatenotification/js/updatenotification.js and b/apps/updatenotification/js/updatenotification.js differ
diff --git a/apps/updatenotification/js/updatenotification.js.map b/apps/updatenotification/js/updatenotification.js.map
index 05e55db672dff2ecb80235c37088dd30bbfaf3c4..832b0b5ce53cfb674a3fc91180ef7d59dd90490d 100644
Binary files a/apps/updatenotification/js/updatenotification.js.map and b/apps/updatenotification/js/updatenotification.js.map differ
diff --git a/apps/user_status/js/dashboard.js b/apps/user_status/js/dashboard.js
index 7d5329b46cace3b1bd42da3f37f1ddbde2a41106..f0ecdf7c439d9edcc82803f28baa0f47d96f06a7 100644
Binary files a/apps/user_status/js/dashboard.js and b/apps/user_status/js/dashboard.js differ
diff --git a/apps/user_status/js/dashboard.js.map b/apps/user_status/js/dashboard.js.map
index 66a62e017ba2a27a46fc770dcc535a628d8188b5..33dcd6872b3f6def445a07f8506f963feabe8670 100644
Binary files a/apps/user_status/js/dashboard.js.map and b/apps/user_status/js/dashboard.js.map differ
diff --git a/apps/user_status/js/user-status-menu.js b/apps/user_status/js/user-status-menu.js
index ba402ebac9b11815c32f8eb1ec95e08646654ad7..988b4931baa1b5ed0637f221a478205896f7927b 100644
Binary files a/apps/user_status/js/user-status-menu.js and b/apps/user_status/js/user-status-menu.js differ
diff --git a/apps/user_status/js/user-status-menu.js.map b/apps/user_status/js/user-status-menu.js.map
index 3593802a1769279b66c2a23223fd4b7231951524..659c0667d1afa4d37b0e890c876a1ce2aea693a3 100644
Binary files a/apps/user_status/js/user-status-menu.js.map and b/apps/user_status/js/user-status-menu.js.map differ
diff --git a/apps/user_status/js/user-status-modal.js b/apps/user_status/js/user-status-modal.js
new file mode 100644
index 0000000000000000000000000000000000000000..c55e254481b977a42f96dc85f3d7d4da0e71742c
Binary files /dev/null and b/apps/user_status/js/user-status-modal.js differ
diff --git a/apps/user_status/js/user-status-modal.js.map b/apps/user_status/js/user-status-modal.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..5a8841c0b0b3f7614ece326d6d784c30f2f87e6c
Binary files /dev/null and b/apps/user_status/js/user-status-modal.js.map differ
diff --git a/apps/user_status/js/vendors-user-status-modal.js b/apps/user_status/js/vendors-user-status-modal.js
new file mode 100644
index 0000000000000000000000000000000000000000..cbe81fef86bcec2c358516625f732e19c50a6e6e
Binary files /dev/null and b/apps/user_status/js/vendors-user-status-modal.js differ
diff --git a/apps/user_status/js/vendors-user-status-modal.js.map b/apps/user_status/js/vendors-user-status-modal.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..1f48916798c7c26d097a100603b8b3284f9b11e8
Binary files /dev/null and b/apps/user_status/js/vendors-user-status-modal.js.map differ
diff --git a/apps/user_status/src/App.vue b/apps/user_status/src/UserStatus.vue
similarity index 50%
rename from apps/user_status/src/App.vue
rename to apps/user_status/src/UserStatus.vue
index ff927505baeeaa21773881e9be8a51a2b32c1e26..517615825955e8c3226b971b8a0f9804e3e1ba66 100644
--- a/apps/user_status/src/App.vue
+++ b/apps/user_status/src/UserStatus.vue
@@ -20,70 +20,59 @@
   -->
 
 <template>
-	<li :class="{ inline }">
-		<div id="user-status-menu-item">
+	<li>
+		<div class="user-status-menu-item">
+			<!-- Username display -->
 			<span
 				v-if="!inline"
-				id="user-status-menu-item__header"
+				class="user-status-menu-item__header"
 				:title="displayName">
 				{{ displayName }}
 			</span>
-			<Actions
-				id="user-status-menu-item__subheader"
-				:default-icon="statusIcon"
-				container="header"
-				:menu-title="visibleMessage"
-				:title="visibleMessage">
-				<ActionButton
-					v-for="status in statuses"
-					:key="status.type"
-					:icon="status.icon"
-					:close-after-click="true"
-					:title="status.label"
-					@click.prevent.stop="changeStatus(status.type)">
-					{{ status.subline }}
-				</ActionButton>
-				<ActionButton
-					icon="icon-rename"
-					:close-after-click="true"
-					:title="$t('user_status', 'Set status message')"
-					@click.prevent.stop="openModal" />
-			</Actions>
-			<SetStatusModal
-				v-if="isModalOpen"
-				@close="closeModal" />
+
+			<!-- Status modal toggle -->
+			<toggle :is="inline ? 'button' : 'a'"
+				:class="{'user-status-menu-item__toggle--inline': inline}"
+				class="user-status-menu-item__toggle"
+				href="#"
+				@click.prevent.stop="openModal">
+				<span :class="statusIcon" class="user-status-menu-item__toggle-icon" />
+				{{ visibleMessage }}
+			</toggle>
 		</div>
+
+		<!-- Status management modal -->
+		<SetStatusModal
+			v-if="isModalOpen"
+			@close="closeModal" />
 	</li>
 </template>
 
 <script>
 import { getCurrentUser } from '@nextcloud/auth'
-import SetStatusModal from './components/SetStatusModal'
-import Actions from '@nextcloud/vue/dist/Components/Actions'
-import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
-import { mapState } from 'vuex'
-import { showError } from '@nextcloud/dialogs'
-import { getAllStatusOptions } from './services/statusOptionsService'
-import { sendHeartbeat } from './services/heartbeatService'
 import debounce from 'debounce'
 
+import { sendHeartbeat } from './services/heartbeatService'
+import OnlineStatusMixin from './mixins/OnlineStatusMixin'
+
 export default {
-	name: 'App',
+	name: 'UserStatus',
+
 	components: {
-		Actions,
-		ActionButton,
-		SetStatusModal,
+		SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal'),
 	},
+	mixins: [OnlineStatusMixin],
+
 	props: {
 		inline: {
 			type: Boolean,
 			default: false,
 		},
 	},
+
 	data() {
 		return {
 			isModalOpen: false,
-			statuses: getAllStatusOptions(),
 			heartbeatInterval: null,
 			setAwayTimeout: null,
 			mouseMoveListener: null,
@@ -91,12 +80,6 @@ export default {
 		}
 	},
 	computed: {
-		...mapState({
-			statusType: state => state.userStatus.status,
-			statusIsUserDefined: state => state.userStatus.statusIsUserDefined,
-			customIcon: state => state.userStatus.icon,
-			customMessage: state => state.userStatus.message,
-		}),
 		/**
 		 * The display-name of the current user
 		 *
@@ -105,64 +88,8 @@ export default {
 		displayName() {
 			return getCurrentUser().displayName
 		},
-		/**
-		 * The message displayed in the top right corner
-		 *
-		 * @returns {String}
-		 */
-		visibleMessage() {
-			if (this.customIcon && this.customMessage) {
-				return `${this.customIcon} ${this.customMessage}`
-			}
-			if (this.customMessage) {
-				return this.customMessage
-			}
-
-			if (this.statusIsUserDefined) {
-				switch (this.statusType) {
-				case 'online':
-					return this.$t('user_status', 'Online')
-
-				case 'away':
-					return this.$t('user_status', 'Away')
-
-				case 'dnd':
-					return this.$t('user_status', 'Do not disturb')
-
-				case 'invisible':
-					return this.$t('user_status', 'Invisible')
-
-				case 'offline':
-					return this.$t('user_status', 'Offline')
-				}
-			}
-
-			return this.$t('user_status', 'Set status')
-		},
-		/**
-		 * The status indicator icon
-		 *
-		 * @returns {String|null}
-		 */
-		statusIcon() {
-			switch (this.statusType) {
-			case 'online':
-				return 'icon-user-status-online'
-
-			case 'away':
-				return 'icon-user-status-away'
-
-			case 'dnd':
-				return 'icon-user-status-dnd'
-
-			case 'invisible':
-			case 'offline':
-				return 'icon-user-status-invisible'
-			}
-
-			return ''
-		},
 	},
+
 	/**
 	 * Loads the current user's status from initial state
 	 * and stores it in Vuex
@@ -198,6 +125,7 @@ export default {
 			this._backgroundHeartbeat()
 		}
 	},
+
 	/**
 	 * Some housekeeping before destroying the component
 	 */
@@ -205,6 +133,7 @@ export default {
 		window.removeEventListener('mouseMove', this.mouseMoveListener)
 		clearInterval(this.heartbeatInterval)
 	},
+
 	methods: {
 		/**
 		 * Opens the modal to set a custom status
@@ -218,19 +147,7 @@ export default {
 		closeModal() {
 			this.isModalOpen = false
 		},
-		/**
-		 * Changes the user-status
-		 *
-		 * @param {String} statusType (online / away / dnd / invisible)
-		 */
-		async changeStatus(statusType) {
-			try {
-				await this.$store.dispatch('setStatus', { statusType })
-			} catch (err) {
-				showError(this.$t('user_status', 'There was an error saving the new status'))
-				console.debug(err)
-			}
-		},
+
 		/**
 		 * Sends the status heartbeat to the server
 		 *
@@ -248,65 +165,55 @@ export default {
 <style lang="scss">
 $max-width-user-status: 200px;
 
-li:not(.inline) #user-status-menu-item {
+.user-status-menu-item {
 	&__header {
 		display: block;
+		overflow: hidden;
 		box-sizing: border-box;
-		color: var(--color-text-maxcontrast);
+		max-width: $max-width-user-status;
 		padding: 10px 12px 5px 38px;
-		opacity: 1;
-		white-space: nowrap;
 		text-align: left;
-		max-width: $max-width-user-status;
-		overflow: hidden;
+		white-space: nowrap;
 		text-overflow: ellipsis;
+		opacity: 1;
+		color: var(--color-text-maxcontrast);
 	}
 
-	&__subheader {
-		width: 100%;
-
-		button.action-item__menutoggle {
-			display: block;
-			box-sizing: border-box;
-			background-color: var(--color-main-background);
-			background-position: 12px center;
+	&__toggle {
+		&-icon {
+			width: 16px;
+			height: 16px;
+			margin-right: 10px;
+			opacity: 1 !important;
 			background-size: 16px;
+		}
+
+		// In dashboard
+		&--inline {
+			width: auto;
+			min-width: 44px;
+			height: 44px;
+			margin: 0;
 			border: 0;
-			border-radius: 0;
+			border-radius: var(--border-radius-pill);
+			background-color: var(--color-background-translucent);
+			font-size: inherit;
 			font-weight: normal;
-			padding-left: 38px;
-			opacity: 1;
-			max-width: $max-width-user-status;
-			overflow: hidden;
-			text-overflow: ellipsis;
 
+			-webkit-backdrop-filter: var(--background-blur);
+			backdrop-filter: var(--background-blur);
+
+			&:active,
 			&:hover,
 			&:focus {
-				box-shadow: inset 4px 0 var(--color-primary-element);
+				background-color: var(--color-background-hover);
 			}
 		}
 	}
 }
 
-.inline #user-status-menu-item__subheader {
-	width: 100%;
-
-	button.action-item__menutoggle {
-		background-size: 16px;
-		border: 0;
-		border-radius: var(--border-radius-pill);
-		font-weight: normal;
-		padding-left: 40px;
-
-		&.icon-loading-small {
-			&::after {
-				left: 21px;
-			}
-		}
-	}
+li {
+	list-style-type: none;
 }
 
-	li {
-		list-style-type: none;
-	}
 </style>
diff --git a/apps/user_status/src/components/OnlineStatusSelect.vue b/apps/user_status/src/components/OnlineStatusSelect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b03af75681eba5512e49d76a255b526b7edfe5e2
--- /dev/null
+++ b/apps/user_status/src/components/OnlineStatusSelect.vue
@@ -0,0 +1,103 @@
+<!--
+ - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
+ -
+ - @author John Molakvoæ <skjnldsv@protonmail.com>
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -
+ -->
+<template>
+	<div class="user-status-online-select">
+		<input :id="id"
+			:checked="checked"
+			class="user-status-online-select__input"
+			type="radio"
+			name="user-status-online"
+			@change="onChange">
+		<label :for="id" :class="icon" class="user-status-online-select__label">
+			<slot />
+		</label>
+	</div>
+</template>
+
+<script>
+export default {
+	name: 'OnlineStatusSelect',
+
+	props: {
+		checked: {
+			type: Boolean,
+			default: false,
+		},
+		icon: {
+			type: String,
+			required: true,
+		},
+		type: {
+			type: String,
+			required: true,
+		},
+	},
+
+	computed: {
+		id() {
+			return `user-status-online-status-${this.type}`
+		},
+	},
+
+	methods: {
+		onChange() {
+			this.$emit('select', this.type)
+		},
+	},
+}
+</script>
+
+<style lang="scss" scoped>
+$icon-size: 24px;
+$label-padding: 8px;
+
+.user-status-online-select {
+	// Inputs are here for keyboard navigation, they are not visually visible
+	&__input {
+		position: absolute;
+		top: auto;
+		left: -10000px;
+		overflow: hidden;
+		width: 1px;
+		height: 1px;
+	}
+
+	&__label {
+		display: block;
+		margin: $label-padding;
+		padding: $label-padding;
+		padding-left: $icon-size + $label-padding * 2;
+		border: 2px solid var(--color-main-background);
+		border-radius: var(--border-radius-large);
+		background-color: var(--color-background-hover);
+		background-position: $label-padding center;
+		background-size: $icon-size;
+	}
+
+	&__input:checked + &__label,
+	&__input:focus + &__label,
+	&__label:hover {
+		border-color: var(--color-primary);
+	}
+}
+
+</style>
diff --git a/apps/user_status/src/components/SetStatusModal.vue b/apps/user_status/src/components/SetStatusModal.vue
index c0652ce990b43e6078afbb279324d0f2970f8b31..c6d48d493cea877f20011eea08dfe02981c9bc60 100644
--- a/apps/user_status/src/components/SetStatusModal.vue
+++ b/apps/user_status/src/components/SetStatusModal.vue
@@ -22,11 +22,27 @@
 <template>
 	<Modal
 		size="normal"
-		:title="$t('user_status', 'Set status message')"
+		:title="$t('user_status', 'Set status')"
 		@close="closeModal">
 		<div class="set-status-modal">
+			<!-- Status selector -->
 			<div class="set-status-modal__header">
-				<h3>{{ $t('user_status', 'Set status message') }}</h3>
+				<h3>{{ $t('user_status', 'Online status') }}</h3>
+			</div>
+			<div class="set-status-modal__online-status">
+				<OnlineStatusSelect v-for="status in statuses"
+					:key="status.type"
+					v-bind="status"
+					:checked="status.type === statusType"
+					@select="changeStatus">
+					{{ status.label }}
+					<em class="subline">{{ status.subline }}</em>
+				</OnlineStatusSelect>
+			</div>
+
+			<!-- Status message -->
+			<div class="set-status-modal__header">
+				<h3>{{ $t('user_status', 'Status message') }}</h3>
 			</div>
 			<div class="set-status-modal__custom-input">
 				<EmojiPicker @select="setIcon">
@@ -57,27 +73,36 @@
 </template>
 
 <script>
+import { showError } from '@nextcloud/dialogs'
 import EmojiPicker from '@nextcloud/vue/dist/Components/EmojiPicker'
 import Modal from '@nextcloud/vue/dist/Components/Modal'
+
+import { getAllStatusOptions } from '../services/statusOptionsService'
+import OnlineStatusMixin from '../mixins/OnlineStatusMixin'
 import PredefinedStatusesList from './PredefinedStatusesList'
 import CustomMessageInput from './CustomMessageInput'
 import ClearAtSelect from './ClearAtSelect'
-import { showError } from '@nextcloud/dialogs'
+import OnlineStatusSelect from './OnlineStatusSelect'
 
 export default {
 	name: 'SetStatusModal',
+
 	components: {
+		ClearAtSelect,
+		CustomMessageInput,
 		EmojiPicker,
 		Modal,
-		CustomMessageInput,
+		OnlineStatusSelect,
 		PredefinedStatusesList,
-		ClearAtSelect,
 	},
+	mixins: [OnlineStatusMixin],
+
 	data() {
 		return {
+			clearAt: null,
 			icon: null,
 			message: null,
-			clearAt: null,
+			statuses: getAllStatusOptions(),
 		}
 	},
 	computed: {
@@ -90,6 +115,7 @@ export default {
 			return this.icon || '😀'
 		},
 	},
+
 	/**
 	 * Loads the current status when a user opens dialog
 	 */
@@ -208,6 +234,25 @@ export default {
 	min-width: 500px;
 	min-height: 200px;
 	padding: 8px 20px 20px 20px;
+	// Enable scrollbar for too long content, same way as in Dashboard customize
+	max-height: 70vh;
+	overflow: auto;
+
+	&__header {
+		text-align: center;
+		font-weight: bold;
+	}
+
+	&__online-status {
+		display: grid;
+		// Space between the two sections
+		margin-bottom: 40px;
+		grid-template-columns: 1fr 1fr;
+
+		.subline {
+			display: block;
+		}
+	}
 
 	&__custom-input {
 		display: flex;
@@ -216,12 +261,12 @@ export default {
 
 		.custom-input__emoji-button {
 			flex-basis: 40px;
-			width: 40px;
 			flex-grow: 0;
-			border-radius: var(--border-radius) 0 0 var(--border-radius);
+			width: 40px;
 			height: 34px;
 			margin-right: 0;
 			border-right: none;
+			border-radius: var(--border-radius) 0 0 var(--border-radius);
 		}
 	}
 
@@ -233,4 +278,5 @@ export default {
 		}
 	}
 }
+
 </style>
diff --git a/apps/user_status/src/main-user-status-menu.js b/apps/user_status/src/main-user-status-menu.js
index 322585c3f0c57a198e05a58f4f5c61597ccc28ef..12fda36e85b8baff995fd31e916a42f6ab9e69b2 100644
--- a/apps/user_status/src/main-user-status-menu.js
+++ b/apps/user_status/src/main-user-status-menu.js
@@ -21,7 +21,7 @@
  */
 import Vue from 'vue'
 import { getRequestToken } from '@nextcloud/auth'
-import App from './App'
+import UserStatus from './UserStatus'
 import store from './store'
 
 // eslint-disable-next-line camelcase
@@ -36,18 +36,23 @@ __webpack_public_path__ = OC.linkTo('user_status', 'js/')
 Vue.prototype.t = t
 Vue.prototype.$t = t
 
-const app = new Vue({
-	render: h => h(App),
+// Register settings menu entry
+export default new Vue({
+	el: 'li[data-id="user_status-menuitem"]',
+	// eslint-disable-next-line vue/match-component-file-name
+	name: 'UserStatusRoot',
+	render: h => h(UserStatus),
 	store,
-}).$mount('li[data-id="user_status-menuitem"]')
+})
 
+// Register dashboard status
 document.addEventListener('DOMContentLoaded', function() {
 	if (!OCA.Dashboard) {
 		return
 	}
 
 	OCA.Dashboard.registerStatus('status', (el) => {
-		const Dashboard = Vue.extend(App)
+		const Dashboard = Vue.extend(UserStatus)
 		return new Dashboard({
 			propsData: {
 				inline: true,
@@ -56,5 +61,3 @@ document.addEventListener('DOMContentLoaded', function() {
 		}).$mount(el)
 	})
 })
-
-export { app }
diff --git a/apps/user_status/src/mixins/OnlineStatusMixin.js b/apps/user_status/src/mixins/OnlineStatusMixin.js
new file mode 100644
index 0000000000000000000000000000000000000000..ceba40f05e7179c63fa492283b30b69fe1cea40d
--- /dev/null
+++ b/apps/user_status/src/mixins/OnlineStatusMixin.js
@@ -0,0 +1,110 @@
+/**
+ * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+import { mapState } from 'vuex'
+import { showError } from '@nextcloud/dialogs'
+
+export default {
+	computed: {
+		...mapState({
+			statusType: state => state.userStatus.status,
+			statusIsUserDefined: state => state.userStatus.statusIsUserDefined,
+			customIcon: state => state.userStatus.icon,
+			customMessage: state => state.userStatus.message,
+		}),
+
+		/**
+		 * The message displayed in the top right corner
+		 *
+		 * @returns {String}
+		 */
+		visibleMessage() {
+			if (this.customIcon && this.customMessage) {
+				return `${this.customIcon} ${this.customMessage}`
+			}
+
+			if (this.customMessage) {
+				return this.customMessage
+			}
+
+			if (this.statusIsUserDefined) {
+				switch (this.statusType) {
+				case 'online':
+					return this.$t('user_status', 'Online')
+
+				case 'away':
+					return this.$t('user_status', 'Away')
+
+				case 'dnd':
+					return this.$t('user_status', 'Do not disturb')
+
+				case 'invisible':
+					return this.$t('user_status', 'Invisible')
+
+				case 'offline':
+					return this.$t('user_status', 'Offline')
+				}
+			}
+
+			return this.$t('user_status', 'Set status')
+		},
+
+		/**
+		 * The status indicator icon
+		 *
+		 * @returns {String|null}
+		 */
+		statusIcon() {
+			switch (this.statusType) {
+			case 'online':
+				return 'icon-user-status-online'
+
+			case 'away':
+				return 'icon-user-status-away'
+
+			case 'dnd':
+				return 'icon-user-status-dnd'
+
+			case 'invisible':
+			case 'offline':
+				return 'icon-user-status-invisible'
+			}
+
+			return ''
+		},
+	},
+
+	methods: {
+		/**
+		 * Changes the user-status
+		 *
+		 * @param {String} statusType (online / away / dnd / invisible)
+		 */
+		async changeStatus(statusType) {
+			try {
+				await this.$store.dispatch('setStatus', { statusType })
+			} catch (err) {
+				showError(this.$t('user_status', 'There was an error saving the new status'))
+				console.debug(err)
+			}
+		},
+	},
+}
diff --git a/apps/user_status/src/services/statusOptionsService.js b/apps/user_status/src/services/statusOptionsService.js
index 9c646915a651bd06cbf1c1f6fbcc3eb9713f872a..266f33230cd7d6817dd251838c143039a4ff1f8f 100644
--- a/apps/user_status/src/services/statusOptionsService.js
+++ b/apps/user_status/src/services/statusOptionsService.js
@@ -44,6 +44,7 @@ const getAllStatusOptions = () => {
 	}, {
 		type: 'invisible',
 		label: t('user_status', 'Invisible'),
+		subline: t('user_status', 'Appear offline'),
 		icon: 'icon-user-status-invisible',
 	}]
 }
diff --git a/apps/user_status/webpack.js b/apps/user_status/webpack.js
index 4b3372b25c737f915c500b7e4e851bb5e7faf771..178bd28e7a5e5206a4c88ae3d6ce386646b17010 100644
--- a/apps/user_status/webpack.js
+++ b/apps/user_status/webpack.js
@@ -2,18 +2,18 @@ const path = require('path')
 
 module.exports = {
 	entry: {
-		'dashboard': path.join(__dirname, 'src', 'dashboard'),
-		'user-status-menu': path.join(__dirname, 'src', 'main-user-status-menu')
+		dashboard: path.join(__dirname, 'src', 'dashboard'),
+		'user-status-menu': path.join(__dirname, 'src', 'main-user-status-menu'),
 	},
 	output: {
 		path: path.resolve(__dirname, './js'),
 		publicPath: '/js/',
 		filename: '[name].js?v=[chunkhash]',
-		jsonpFunction: 'webpackJsonpUserStatus'
+		jsonpFunction: 'webpackJsonpUserStatus',
 	},
 	optimization: {
 		splitChunks: {
 			automaticNameDelimiter: '-',
-		}
-	}
+		},
+	},
 }
diff --git a/apps/weather_status/js/weather-status.js b/apps/weather_status/js/weather-status.js
index 3561299491bc08de97fcb76abda8cd0dc5dab9f4..3999da95ad1aae6e99dcf9be7e87534d6607b29d 100644
Binary files a/apps/weather_status/js/weather-status.js and b/apps/weather_status/js/weather-status.js differ
diff --git a/apps/weather_status/js/weather-status.js.map b/apps/weather_status/js/weather-status.js.map
index 61d31ae91edb46d33951626988a12846030cb885..6597b4b158cf79e552aaa5216ab0a09604652810 100644
Binary files a/apps/weather_status/js/weather-status.js.map and b/apps/weather_status/js/weather-status.js.map differ
diff --git a/apps/workflowengine/js/workflowengine.js b/apps/workflowengine/js/workflowengine.js
index 6a66ee01c897cbb369bbc7bd2c88c0aae560d0c4..42d57d5ea5801b1eb294c647ea7279540704d4d1 100644
Binary files a/apps/workflowengine/js/workflowengine.js and b/apps/workflowengine/js/workflowengine.js differ
diff --git a/apps/workflowengine/js/workflowengine.js.map b/apps/workflowengine/js/workflowengine.js.map
index ee6783c472442548034bd2ba9d53cba5084f3839..4d8e5b5626d7750ec7b2bf086a8540a729e1b329 100644
Binary files a/apps/workflowengine/js/workflowengine.js.map and b/apps/workflowengine/js/workflowengine.js.map differ
diff --git a/core/js/dist/unified-search.js b/core/js/dist/unified-search.js
index 5e6068c585e480645d5a7bfff31ec5f24a686a86..9558f11c55206df9f24a4128c2a25f050b5568d9 100644
Binary files a/core/js/dist/unified-search.js and b/core/js/dist/unified-search.js differ
diff --git a/core/js/dist/unified-search.js.map b/core/js/dist/unified-search.js.map
index 227dcc73656c618989d60229f5b15fedef31e6f5..bfa696930a780d627917c60864dbfb38619a1f84 100644
Binary files a/core/js/dist/unified-search.js.map and b/core/js/dist/unified-search.js.map differ
diff --git a/package-lock.json b/package-lock.json
index 0ac83eb145fdbe04eba2bd343852adffa32f6ec5..5343f8fc8ce680fc1aabf8024380bbf065d6f4b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1272,9 +1272,9 @@
       }
     },
     "@nextcloud/vue": {
-      "version": "2.6.6",
-      "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.6.tgz",
-      "integrity": "sha512-amlFNT5uDnz8ryFeD4birEXXx2K0KyV5nthYoIuz6A7liOxFwOF7BX7jNwhYkM21JvSloMCfm76BcK+DxtShOw==",
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.7.tgz",
+      "integrity": "sha512-ISu1ceEifRpQ7TiXykCnr/mPPtmlmGLW2hOOq3DBbpxueiEk8w6JCBB7SCwNbSg01T/vm01dlnT1ibHm1HjAIg==",
       "requires": {
         "@nextcloud/auth": "^1.2.3",
         "@nextcloud/axios": "^1.3.2",
diff --git a/package.json b/package.json
index b542abb479a9b1c71b3999c268b20dc7da0fb76f..9e10317ddb1431235e2d5fb4d0b5c5c34a008104 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
     "@nextcloud/password-confirmation": "^1.0.1",
     "@nextcloud/paths": "^1.1.2",
     "@nextcloud/router": "^1.1.0",
-    "@nextcloud/vue": "^2.6.6",
+    "@nextcloud/vue": "^2.6.7",
     "@nextcloud/vue-dashboard": "^1.0.1",
     "autosize": "^4.0.2",
     "backbone": "^1.4.0",
diff --git a/tests/acceptance/features/header.feature b/tests/acceptance/features/header.feature
index 94b08e8f6d94bfd9d1ac8d3396636b5142762124..df9d8045b8b36eb49a5371f743c5ce61dab20b6c 100644
--- a/tests/acceptance/features/header.feature
+++ b/tests/acceptance/features/header.feature
@@ -5,7 +5,8 @@ Feature: header
     Given I am logged in as the admin
     When I open the Settings menu
     Then I see that the Settings menu is shown
-    And I see that the Settings menu has only 5 items
+    And I see that the Settings menu has only 6 items
+    And I see that the "Set status" item in the Settings menu is shown
     And I see that the "Settings" item in the Settings menu is shown
     And I see that the "Apps" item in the Settings menu is shown
     And I see that the "Users" item in the Settings menu is shown
@@ -16,7 +17,8 @@ Feature: header
     Given I am logged in
     When I open the Settings menu
     Then I see that the Settings menu is shown
-    And I see that the Settings menu has only 3 items
+    And I see that the Settings menu has only 4 items
+    And I see that the "Set status" item in the Settings menu is shown
     And I see that the "Settings" item in the Settings menu is shown
     And I see that the "Help" item in the Settings menu is shown
     And I see that the "Log out" item in the Settings menu is shown