diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac4e0a920543655ee4bdcc667b77ddb94c0f4297..e3c7f13219e3fc320a503b3bb8a07eee24bf7501 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 - Ability to see local statuses in Statuses by instance section
 - Ability to configure Oban.Cron settings and settings for notifications streamer
+- Settings search
 
 ### Fixed
 
diff --git a/src/store/modules/normalizers.js b/src/store/modules/normalizers.js
index 4d23c957490725e8ad9f3d619db6d442f22a6da1..6eecebca359a9b53356e3ac0019f63438bb7fd90 100644
--- a/src/store/modules/normalizers.js
+++ b/src/store/modules/normalizers.js
@@ -267,3 +267,25 @@ const wrapValues = (settings, currentState) => {
     }
   })
 }
+
+export const formSearchObject = description => {
+  const parseNestedSettings = (description, label, key) => description.reduce((acc, setting) => {
+    const searchArray = _.compact([setting.key, setting.label, setting.description]).map(el => el.toLowerCase())
+    const resultObject = { label: setting.label, key: setting.key || setting.group, groupKey: key, groupLabel: label, search: searchArray }
+    if (setting.children) {
+      const updatedAcc = [...acc, resultObject]
+      return [...updatedAcc, ...parseNestedSettings(setting.children, label, key)]
+    }
+    return [...acc, resultObject]
+  }, [])
+
+  return description.reduce((acc, setting) => {
+    const searchArray = _.compact([setting.key, setting.label, setting.description]).map(el => el.toLowerCase())
+    const resultObject = { label: setting.label, key: setting.key || setting.group, groupKey: setting.key || setting.group, groupLabel: setting.label, search: searchArray }
+    if (setting.children) {
+      const updatedAcc = !setting.key && setting.group === ':pleroma' ? acc : [...acc, resultObject]
+      return [...updatedAcc, ...parseNestedSettings(setting.children, setting.label, setting.key || setting.group)]
+    }
+    return !setting.key && setting.group === ':pleroma' ? acc : [...acc, resultObject]
+  }, [])
+}
diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js
index ab7a3b361bdf714e4cd336953c8f77c3cfccf0f7..5adc16a0df31865d590ec8ae611461fad2b3f399 100644
--- a/src/store/modules/settings.js
+++ b/src/store/modules/settings.js
@@ -1,5 +1,5 @@
 import { fetchDescription, fetchSettings, removeSettings, restartApp, updateSettings } from '@/api/settings'
-import { checkPartialUpdate, parseNonTuples, parseTuples, valueHasTuples, wrapUpdatedSettings } from './normalizers'
+import { checkPartialUpdate, formSearchObject, parseNonTuples, parseTuples, valueHasTuples, wrapUpdatedSettings } from './normalizers'
 import _ from 'lodash'
 
 const settings = {
@@ -10,6 +10,7 @@ const settings = {
     description: [],
     loading: true,
     needReboot: false,
+    searchData: {},
     settings: {},
     updatedSettings: {}
   },
@@ -32,6 +33,9 @@ const settings = {
     SET_LOADING: (state, status) => {
       state.loading = status
     },
+    SET_SEARCH: (state, searchObject) => {
+      state.searchData = searchObject
+    },
     SET_SETTINGS: (state, data) => {
       const newSettings = data.reduce((acc, { group, key, value }) => {
         const parsedValue = valueHasTuples(key, value)
@@ -77,6 +81,8 @@ const settings = {
         const response = await fetchSettings(getters.authHost, getters.token)
         const description = await fetchDescription(getters.authHost, getters.token)
         commit('SET_DESCRIPTION', description.data)
+        const searchObject = formSearchObject(description.data)
+        commit('SET_SEARCH', searchObject)
         commit('SET_SETTINGS', response.data.configs)
         commit('TOGGLE_REBOOT', response.data.need_reboot)
       } catch (_e) {
diff --git a/src/views/invites/index.vue b/src/views/invites/index.vue
index 60111430f2d113b6a57da0ccbd653db1fd3c407d..55aa6fc09956aedca59d7b0cdb42084b99ffcf12 100644
--- a/src/views/invites/index.vue
+++ b/src/views/invites/index.vue
@@ -39,7 +39,7 @@
         </el-form-item>
       </el-form>
       <span slot="footer">
-        <el-button @click="closeDialogWindow">{{ $t('invites.cancel') }}</el-button>
+        <el-button class="invites-close-dialog" @click="closeDialogWindow">{{ $t('invites.cancel') }}</el-button>
         <el-button type="primary" @click="createToken">{{ $t('invites.create') }}</el-button>
       </span>
       <el-card v-if="'token' in newToken">
diff --git a/src/views/settings/components/ActivityPub.vue b/src/views/settings/components/ActivityPub.vue
index abd03f10ffed71e9b14c13d0f352637cfa93c5c8..3e71e0c2f787eb709e55e3c4afec37ec0710ffca 100644
--- a/src/views/settings/components/ActivityPub.vue
+++ b/src/views/settings/components/ActivityPub.vue
@@ -1,10 +1,10 @@
 <template>
   <div v-if="!loading" class="form-container">
-    <el-form ref="activitypubData" :model="activitypubData" :label-width="labelWidth">
+    <el-form ref="activitypubData" :model="activitypubData" :label-width="labelWidth" data-search=":activitypub">
       <setting :setting-group="activitypub" :data="activitypubData"/>
     </el-form>
     <el-divider class="divider thick-line"/>
-    <el-form ref="userData" :model="userData" :label-width="labelWidth">
+    <el-form ref="userData" :model="userData" :label-width="labelWidth" data-search=":user">
       <setting :setting-group="user" :data="userData"/>
     </el-form>
     <div class="submit-button-container">
diff --git a/src/views/settings/components/Frontend.vue b/src/views/settings/components/Frontend.vue
index 188a74cae304356bd9e42f58a5a14dd13c1111da..2dcacaaba13ff2c8e3f0af1d43629bb5877816f3 100644
--- a/src/views/settings/components/Frontend.vue
+++ b/src/views/settings/components/Frontend.vue
@@ -15,7 +15,7 @@
     </el-form>
     <el-divider class="divider thick-line"/>
     <el-form ref="emojiData" :model="emojiData" :label-width="labelWidth">
-      <el-form-item class="grouped-settings-header">
+      <el-form-item data-search=":emoji" class="grouped-settings-header">
         <span class="label-font">{{ $t('settings.emoji') }}</span>
       </el-form-item>
       <setting :setting-group="emoji" :data="emojiData"/>
@@ -26,7 +26,7 @@
     </el-form>
     <el-divider class="divider thick-line"/>
     <el-form ref="markupData" :model="markupData" :label-width="labelWidth">
-      <el-form-item class="grouped-settings-header">
+      <el-form-item data-search=":markup" class="grouped-settings-header">
         <span class="label-font">{{ $t('settings.markup') }}</span>
       </el-form-item>
       <setting :setting-group="markup" :data="markupData"/>
diff --git a/src/views/settings/components/Http.vue b/src/views/settings/components/Http.vue
index a94000b274e8027a8b0370faadda89f54f970fac..d14cced4cc9c06a7a558cdb5bf36a8c1b478b1c4 100644
--- a/src/views/settings/components/Http.vue
+++ b/src/views/settings/components/Http.vue
@@ -4,7 +4,7 @@
       <setting :setting-group="http" :data="httpData"/>
     </el-form>
     <el-form ref="corsPlugData" :model="corsPlugData" :label-width="labelWidth">
-      <el-form-item class="grouped-settings-header">
+      <el-form-item data-search=":cors_plug" class="grouped-settings-header">
         <span class="label-font">{{ $t('settings.corsPlug') }}</span>
       </el-form-item>
       <setting :setting-group="corsPlug" :data="corsPlugData"/>
diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue
index 300f09c7b39a708f0503c06480d360657afc8f31..981270cf109a1846095a9514e80a3b102cf6a683 100644
--- a/src/views/settings/components/Inputs.vue
+++ b/src/views/settings/components/Inputs.vue
@@ -1,7 +1,11 @@
 <template>
   <div class="input-container">
     <div v-if="setting.type === 'keyword'" class="keyword-container">
-      <el-form-item :label-width="customLabelWidth" :class="labelClass" :style="`margin-left:${margin}px;margin-bottom:0`" >
+      <el-form-item
+        :label-width="customLabelWidth"
+        :class="labelClass"
+        :style="`margin-left:${margin}px;margin-bottom:0`"
+        :data-search="setting.key || setting.group">
         <span slot="label">
           {{ setting.label }}
           <el-tooltip v-if="canBeDeleted && isDesktop" :content="$t('settings.removeFromDB')" placement="bottom-end">
@@ -33,11 +37,13 @@
           v-if="setting.type === 'string' || (setting.type.includes('string') && setting.type.includes('atom'))"
           :value="inputValue"
           :placeholder="setting.suggestions ? setting.suggestions[0] : null"
+          :data-search="setting.key || setting.group"
           class="input"
           @input="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"/>
         <el-switch
           v-if="setting.type === 'boolean'"
           :value="inputValue"
+          :data-search="setting.key || setting.group"
           class="switch-input"
           @change="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"/>
         <el-input-number
@@ -46,10 +52,12 @@
           :placeholder="setting.suggestions ? setting.suggestions[0].toString() : null"
           :min="0"
           :size="isDesktop ? 'large' : 'medium'"
+          :data-search="setting.key || setting.group"
           @change="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"/>
         <el-select
           v-if="setting.type === 'module' || (setting.type.includes('atom') && setting.type.includes('dropdown'))"
           :value="inputValue === false ? 'false' : inputValue"
+          :data-search="setting.key || setting.group"
           clearable
           class="input"
           @change="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)">
@@ -61,6 +69,7 @@
         <el-select
           v-if="renderMultipleSelect(setting.type)"
           :value="setting.key === ':rewrite_policy' ? rewritePolicyValue : inputValue"
+          :data-search="setting.key || setting.group"
           multiple
           filterable
           allow-create
@@ -71,6 +80,7 @@
         <el-input
           v-if="setting.key === ':ip'"
           :value="inputValue"
+          :data-search="setting.key || setting.group"
           placeholder="xxx.xxx.xxx.xx"
           class="input"
           @input="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"/>
@@ -78,6 +88,7 @@
           v-if="setting.type === 'atom'"
           :value="inputValue"
           :placeholder="setting.suggestions[0] ? setting.suggestions[0].substr(1) : ''"
+          :data-search="setting.key || setting.group"
           class="input"
           @input="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)">
           <template slot="prepend">:</template>
diff --git a/src/views/settings/components/Instance.vue b/src/views/settings/components/Instance.vue
index a8698350c0eb5593b020b3230cc5ba7609a6c49a..a426323eadc25ff037109daad467510d96690b30 100644
--- a/src/views/settings/components/Instance.vue
+++ b/src/views/settings/components/Instance.vue
@@ -20,7 +20,7 @@
       <setting :setting-group="manifest" :data="manifestData"/>
     </el-form>
     <el-divider class="divider thick-line"/>
-    <el-form ref="pleromaUser" :model="pleromaUserData" :label-width="labelWidth">
+    <el-form ref="pleromaUser" :model="pleromaUserData" :label-width="labelWidth" data-search="Pleroma.User">
       <setting :setting-group="pleromaUser" :data="pleromaUserData"/>
     </el-form>
     <el-divider class="divider thick-line"/>
diff --git a/src/views/settings/components/Mailer.vue b/src/views/settings/components/Mailer.vue
index 1624eff2c2ece24547e631972cce5bdc01887992..4938479835d41dcfee0cf0391ced63d891ee6c2d 100644
--- a/src/views/settings/components/Mailer.vue
+++ b/src/views/settings/components/Mailer.vue
@@ -11,9 +11,12 @@
     <el-form ref="emailNotifications" :model="emailNotificationsData" :label-width="labelWidth">
       <setting :setting-group="emailNotifications" :data="emailNotificationsData"/>
     </el-form>
-    <el-form ref="userEmail" :model="userEmail" :label-width="labelWidth">
+    <el-form ref="userEmail" :model="userEmailData" :label-width="labelWidth">
       <setting :setting-group="userEmail" :data="userEmailData"/>
     </el-form>
+    <el-form ref="newUsersDigestEmail" :model="newUsersDigestEmailData" :label-width="labelWidth">
+      <setting :setting-group="newUsersDigestEmail" :data="newUsersDigestEmailData"/>
+    </el-form>
     <div class="submit-button-container">
       <el-button class="submit-button" type="primary" @click="onSubmit">Submit</el-button>
     </div>
@@ -65,6 +68,12 @@ export default {
     mailerData() {
       return _.get(this.settings.settings, [':pleroma', 'Pleroma.Emails.Mailer']) || {}
     },
+    newUsersDigestEmail() {
+      return this.settings.description.find(setting => setting.key === 'Pleroma.Emails.NewUsersDigestEmail')
+    },
+    newUsersDigestEmailData() {
+      return _.get(this.settings.settings, [':pleroma', 'Pleroma.Emails.NewUsersDigestEmail']) || {}
+    },
     swoosh() {
       return this.settings.description.find(setting => setting.group === ':swoosh')
     },
diff --git a/src/views/settings/components/Setting.vue b/src/views/settings/components/Setting.vue
index d676da299e07790fb248b8fe92e44c0848d27315..9794cc632aa65da2a61686a4a05296aaa3408123 100644
--- a/src/views/settings/components/Setting.vue
+++ b/src/views/settings/components/Setting.vue
@@ -1,6 +1,6 @@
 <template>
   <div v-if="!loading">
-    <el-form-item v-if="settingGroup.description" class="description-container">
+    <el-form-item v-if="settingGroup.description" :data-search="settingGroup.key || settingGroup.group" class="description-container">
       <span class="description" v-html="getFormattedDescription(settingGroup.description)"/>
     </el-form-item>
     <div v-if="settingGroup.key === 'Pleroma.Emails.Mailer'">
@@ -39,7 +39,7 @@
           </div>
           <div v-else>
             <div class="input-container">
-              <el-form-item class="grouped-settings-header">
+              <el-form-item :data-search="setting.key || setting.group" class="grouped-settings-header">
                 <span slot="label">
                   <el-tooltip v-if="isDesktop && canBeDeleted(setting.key)" :content="$t('settings.removeFromDB')" placement="bottom-end">
                     <el-button icon="el-icon-delete" circle size="mini" style="margin-left:5px" @click="removeSetting(setting.key)"/>
diff --git a/src/views/settings/components/inputComponents/AutoLinkerInput.vue b/src/views/settings/components/inputComponents/AutoLinkerInput.vue
index 756eeb1c1135debb2398136462ec33b8548e2384..b14f914e132b5a3be5f2039ace78efbdc14e78cc 100644
--- a/src/views/settings/components/inputComponents/AutoLinkerInput.vue
+++ b/src/views/settings/components/inputComponents/AutoLinkerInput.vue
@@ -1,10 +1,10 @@
 <template>
   <div>
-    <div v-if="setting.key === ':class' || setting.key === ':rel'">
+    <div v-if="setting.key === ':class' || setting.key === ':rel'" :data-search="setting.key || setting.group">
       <el-switch :value="autoLinkerBooleanValue(setting.key)" @change="processTwoTypeValue($event, setting.key)"/>
       <el-input v-if="autoLinkerBooleanValue(setting.key)" :value="autoLinkerStringValue(setting.key)" @input="processTwoTypeValue($event, setting.key)"/>
     </div>
-    <div v-if="setting.key === ':truncate'">
+    <div v-if="setting.key === ':truncate'" :data-search="setting.key || setting.group">
       <el-switch :value="autoLinkerBooleanValue(setting.key)" @change="processTwoTypeValue($event, setting.key)"/>
       <el-input-number v-if="autoLinkerBooleanValue(setting.key)" :value="autoLinkerIntegerValue(setting.key)" @input="processTwoTypeValue($event, setting.key)"/>
     </div>
diff --git a/src/views/settings/components/inputComponents/CrontabInput.vue b/src/views/settings/components/inputComponents/CrontabInput.vue
index f3f16d26aef333e16800d743c0315a113c116305..89a1491549784d8c0295c047d1ac3e21e774089d 100644
--- a/src/views/settings/components/inputComponents/CrontabInput.vue
+++ b/src/views/settings/components/inputComponents/CrontabInput.vue
@@ -1,6 +1,6 @@
 <template>
   <el-form :label-width="labelWidth" :label-position="isMobile ? 'top' : 'right'" class="crontab">
-    <el-form-item v-for="worker in workers" :key="worker" :label="worker" class="crontab-container">
+    <el-form-item v-for="worker in workers" :key="worker" :label="worker" :data-search="setting.key" class="crontab-container">
       <el-input
         :value="data[worker]"
         :placeholder="getSuggestion(worker) || null"
diff --git a/src/views/settings/components/inputComponents/EditableKeywordInput.vue b/src/views/settings/components/inputComponents/EditableKeywordInput.vue
index fe5b9c7b24ef962b7efa6d736855f0be55417fdb..009b2033bcf750d296a6471e98466e085b89c318 100644
--- a/src/views/settings/components/inputComponents/EditableKeywordInput.vue
+++ b/src/views/settings/components/inputComponents/EditableKeywordInput.vue
@@ -1,6 +1,6 @@
 <template>
   <div class="editable-keyword-container">
-    <div v-if="setting.key === ':replace'">
+    <div v-if="setting.key === ':replace'" :data-search="setting.key || setting.group">
       <div v-for="element in data" :key="getId(element)" class="setting-input">
         <el-input :value="getKey(element)" placeholder="pattern" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
         <el-input :value="getValue(element)" placeholder="replacement" class="value-input" @input="parseEditableKeyword($event, 'value', element)"/>
@@ -8,7 +8,7 @@
       </div>
       <el-button :size="isDesktop ? 'medium' : 'mini'" icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
     </div>
-    <div v-else-if="editableKeywordWithInteger">
+    <div v-else-if="editableKeywordWithInteger" :data-search="setting.key || setting.group">
       <div v-for="element in data" :key="getId(element)" class="setting-input">
         <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
         <el-input-number :value="getValue(element)" :min="0" size="large" class="value-input" @change="parseEditableKeyword($event, 'value', element)"/>
@@ -16,7 +16,7 @@
       </div>
       <el-button :size="isDesktop ? 'medium' : 'mini'" icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
     </div>
-    <div v-else>
+    <div v-else :data-search="setting.key || setting.group">
       <div v-for="element in data" :key="getId(element)" class="setting-input">
         <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
         <el-select :value="getValue(element)" multiple filterable allow-create class="value-input" @change="parseEditableKeyword($event, 'value', element)"/>
diff --git a/src/views/settings/components/inputComponents/IconsInput.vue b/src/views/settings/components/inputComponents/IconsInput.vue
index f5278bbae7688ffda528ac0e6eadfb36270e2db2..e2f091656dd6566b9518870517dce483d9665cdd 100644
--- a/src/views/settings/components/inputComponents/IconsInput.vue
+++ b/src/views/settings/components/inputComponents/IconsInput.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="mascot-container">
+  <div :data-search="setting.key || setting.group" class="mascot-container">
     <div v-for="(icon, index) in data" :key="index" class="mascot">
       <div class="icons-container">
         <div class="icon-container">
diff --git a/src/views/settings/components/inputComponents/MascotsInput.vue b/src/views/settings/components/inputComponents/MascotsInput.vue
index 902ed22fb22cf89ee014b97adb2ebebfe41ef738..e9d94e512c80d478cc1e6a0f6183299ceff9d900 100644
--- a/src/views/settings/components/inputComponents/MascotsInput.vue
+++ b/src/views/settings/components/inputComponents/MascotsInput.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="mascot-container">
+  <div :data-search="setting.key || setting.group" class="mascot-container">
     <div v-for="mascot in data" :key="getId(mascot)" class="mascot">
       <el-form-item label="Name" label-width="85px" class="mascot-form-item">
         <div class="mascot-name-container">
diff --git a/src/views/settings/components/inputComponents/MultipleSelect.vue b/src/views/settings/components/inputComponents/MultipleSelect.vue
index ead60d694b07b71f9621e525b2f49947294992af..66b3aa7546babdc5d6868ec2c9da0b9c00722ae3 100644
--- a/src/views/settings/components/inputComponents/MultipleSelect.vue
+++ b/src/views/settings/components/inputComponents/MultipleSelect.vue
@@ -3,6 +3,7 @@
     <el-select
       v-if="setting.key === ':backends'"
       :value="data.value"
+      :data-search="setting.key || setting.group"
       multiple
       filterable
       allow-create
@@ -15,6 +16,7 @@
     <el-select
       v-if="setting.key === ':args'"
       :value="data[setting.key]"
+      :data-search="setting.key || setting.group"
       multiple
       filterable
       allow-create
diff --git a/src/views/settings/components/inputComponents/ProxyUrlInput.vue b/src/views/settings/components/inputComponents/ProxyUrlInput.vue
index 84956074ae49517645a63637913f218aaa05c7bc..c2ee2381d3cec829bf9e1f67091c81f6811c27a2 100644
--- a/src/views/settings/components/inputComponents/ProxyUrlInput.vue
+++ b/src/views/settings/components/inputComponents/ProxyUrlInput.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="proxy-url-input">
+  <div :data-search="setting.key || setting.group" class="proxy-url-input">
     <el-input
       :value="proxyUrlData.host"
       placeholder="host (e.g. localhost or 127.0.0.1)"
diff --git a/src/views/settings/components/inputComponents/PruneInput.vue b/src/views/settings/components/inputComponents/PruneInput.vue
index c851aa5b237f874caacf90da1c93a328559f9ba6..7c17415da64e359396cf55200f0a493f522c55d5 100644
--- a/src/views/settings/components/inputComponents/PruneInput.vue
+++ b/src/views/settings/components/inputComponents/PruneInput.vue
@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div :data-search="setting.key || setting.group">
     <el-radio-group v-model="prune" class="prune-options">
       <el-radio label=":disabled">Disabled</el-radio>
       <el-radio label=":maxlen">Limit-based</el-radio>
diff --git a/src/views/settings/components/inputComponents/RateLimitInput.vue b/src/views/settings/components/inputComponents/RateLimitInput.vue
index caddd15c1c15d680831402be2d5926e8d4f8ca43..431ae83b48d7efcc8e1c54aa07ba67787c8c35b4 100644
--- a/src/views/settings/components/inputComponents/RateLimitInput.vue
+++ b/src/views/settings/components/inputComponents/RateLimitInput.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="rate-limit-container">
+  <div :data-search="setting.key || setting.group" class="rate-limit-container">
     <div v-if="!rateLimitAuthUsers">
       <el-input
         :value="rateLimitAllUsers[0]"
diff --git a/src/views/settings/components/tabs.js b/src/views/settings/components/tabs.js
new file mode 100644
index 0000000000000000000000000000000000000000..4bfa205113d6cd26e56b04989ae13d83347b21c3
--- /dev/null
+++ b/src/views/settings/components/tabs.js
@@ -0,0 +1,82 @@
+export const tabs = {
+  'activity-pub': {
+    label: 'settings.activityPub',
+    settings: [':activitypub', ':user']
+  },
+  'authentication': {
+    label: 'settings.auth',
+    settings: [':auth', ':ldap', ':oauth2', 'Pleroma.Web.Auth.Authenticator']
+  },
+  'auto-linker': {
+    label: 'settings.autoLinker',
+    settings: [':opts']
+  },
+  'esshd': {
+    label: 'settings.esshd',
+    settings: [':esshd']
+  },
+  'captcha': {
+    label: 'settings.captcha',
+    settings: ['Pleroma.Captcha', 'Pleroma.Captcha.Kocaptcha']
+  },
+  'frontend': {
+    label: 'settings.frontend',
+    settings: [':assets', ':chat', ':emoji', ':frontend_configurations', ':markup', ':static_fe']
+  },
+  'gopher': {
+    label: 'settings.gopher',
+    settings: [':gopher']
+  },
+  'http': {
+    label: 'settings.http',
+    settings: [':cors_plug', ':http', ':http_security', ':http_signatures', ':web_cache_ttl']
+  },
+  'instance': {
+    label: 'settings.instance',
+    settings: [':admin_token', ':fetch_initial_posts', ':instance', ':manifest', 'Pleroma.User', 'Pleroma.ScheduledActivity', ':uri_schemes', ':feed', ':streamer']
+  },
+  'job-queue': {
+    label: 'settings.jobQueue',
+    settings: ['Pleroma.ActivityExpiration', 'Oban', ':workers']
+  },
+  'logger': {
+    label: 'settings.logger',
+    settings: [':console', ':ex_syslogger', ':quack', ':logger']
+  },
+  'mailer': {
+    label: 'settings.mailer',
+    settings: [':email_notifications', 'Pleroma.Emails.Mailer', 'Pleroma.Emails.UserEmail', ':swoosh', 'Pleroma.Emails.NewUsersDigestEmail']
+  },
+  'media-proxy': {
+    label: 'settings.mediaProxy',
+    settings: [':media_proxy']
+  },
+  'metadata': {
+    label: 'settings.metadata',
+    settings: ['Pleroma.Web.Metadata', ':rich_media']
+  },
+  'mrf': {
+    label: 'settings.mrf',
+    settings: [':mrf_simple', ':mrf_rejectnonpublic', ':mrf_hellthread', ':mrf_keyword', ':mrf_subchain', ':mrf_mention', ':mrf_normalize_markup', ':mrf_vocabulary', ':mrf_object_age', ':modules']
+  },
+  'rate-limiters': {
+    label: 'settings.rateLimiters',
+    settings: [':rate_limit']
+  },
+  'relays': {
+    label: 'settings.relays',
+    settings: []
+  },
+  'web-push': {
+    label: 'settings.webPush',
+    settings: [':vapid_details']
+  },
+  'upload': {
+    label: 'settings.upload',
+    settings: ['Pleroma.Upload.Filter.AnonymizeFilename', 'Pleroma.Upload.Filter.Mogrify', 'Pleroma.Uploaders.S3', 'Pleroma.Uploaders.Local', 'Pleroma.Upload']
+  },
+  'other': {
+    label: 'settings.other',
+    settings: [':mime', 'Pleroma.Plugs.RemoteIp']
+  }
+}
diff --git a/src/views/settings/index.vue b/src/views/settings/index.vue
index 3d0bbcdb9807a570be5b16f404d01ccb6dd3de21..048939a354590aeeefc4cf8ba16a489045563e5d 100644
--- a/src/views/settings/index.vue
+++ b/src/views/settings/index.vue
@@ -23,68 +23,26 @@
               </span>
             </el-button>
           </el-link>
+          <el-autocomplete
+            v-model="searchQuery"
+            :fetch-suggestions="querySearch"
+            :trigger-on-focus="false"
+            clearable
+            placeholder="Search"
+            prefix-icon="el-icon-search"
+            class="settings-search-input"
+            @select="handleSearchSelect"/>
         </div>
       </div>
       <el-tabs v-model="activeTab" tab-position="left">
-        <el-tab-pane :label="$t('settings.activityPub')" :disabled="configDisabled" name="activityPub" lazy>
-          <activity-pub/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.auth')" :disabled="configDisabled" name="auth" lazy>
-          <authentication/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.autoLinker')" :disabled="configDisabled" name="autoLinker" lazy>
-          <auto-linker/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.esshd')" :disabled="configDisabled" name="esshd" lazy>
-          <esshd/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.captcha')" :disabled="configDisabled" name="captcha" lazy>
-          <captcha/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.frontend')" :disabled="configDisabled" name="frontend" lazy>
-          <frontend/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.gopher')" :disabled="configDisabled" name="gopher" lazy>
-          <gopher/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.http')" :disabled="configDisabled" name="http" lazy>
-          <http/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.instance')" :disabled="configDisabled" name="instance">
-          <instance/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.jobQueue')" :disabled="configDisabled" name="jobQueue" lazy>
-          <job-queue/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.logger')" :disabled="configDisabled" name="logger" lazy>
-          <logger/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.mailer')" :disabled="configDisabled" name="mailer" lazy>
-          <mailer/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.mediaProxy')" :disabled="configDisabled" name="mediaProxy" lazy>
-          <media-proxy/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.metadata')" :disabled="configDisabled" name="metadata" lazy>
-          <metadata/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.mrf')" :disabled="configDisabled" name="mrf" lazy>
-          <mrf/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.rateLimiters')" :disabled="configDisabled" name="rateLimiters" lazy>
-          <rate-limiters/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.relays')" lazy name="relays">
-          <relays/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.webPush')" :disabled="configDisabled" name="webPush" lazy>
-          <web-push/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.upload')" :disabled="configDisabled" name="upload" lazy>
-          <upload/>
-        </el-tab-pane>
-        <el-tab-pane :label="$t('settings.other')" :disabled="configDisabled" name="other" lazy>
-          <other/>
+        <el-tab-pane
+          v-for="(value, componentName) in tabs"
+          :label="$t(value.label)"
+          :disabled="configDisabled"
+          :key="componentName"
+          :name="componentName"
+          lazy>
+          <component :is="componentName"/>
         </el-tab-pane>
       </el-tabs>
     </div>
@@ -119,6 +77,7 @@
           </el-button>
         </el-link>
       </div>
+      <div class="settings-search-input-container"/>
       <activity-pub v-if="activeTab === 'activityPub'"/>
       <authentication v-if="activeTab === 'auth'"/>
       <auto-linker v-if="activeTab === 'autoLinker'"/>
@@ -145,6 +104,7 @@
 
 <script>
 import i18n from '@/lang'
+import { tabs } from './components/tabs'
 import {
   ActivityPub,
   Authentication,
@@ -214,7 +174,8 @@ export default {
         { value: 'webPush', label: i18n.t('settings.webPush') },
         { value: 'upload', label: i18n.t('settings.upload') },
         { value: 'other', label: i18n.t('settings.other') }
-      ]
+      ],
+      searchQuery: ''
     }
   },
   computed: {
@@ -240,6 +201,12 @@ export default {
     },
     needReboot() {
       return this.$store.state.settings.needReboot
+    },
+    searchData() {
+      return this.$store.state.settings.searchData
+    },
+    tabs() {
+      return tabs
     }
   },
   mounted: function() {
@@ -256,6 +223,25 @@ export default {
         type: 'success',
         message: i18n.t('settings.restartSuccess')
       })
+    },
+    async handleSearchSelect(selectedValue) {
+      const tab = Object.keys(this.tabs).find(tab => {
+        return this.tabs[tab].settings.includes(selectedValue.group === ':pleroma' ? selectedValue.key : selectedValue.group)
+      })
+      await this.$store.dispatch('SetActiveTab', tab)
+      const selectedSetting = document.querySelector(`[data-search="${selectedValue.key}"]`)
+      if (selectedSetting) {
+        selectedSetting.scrollIntoView({ block: 'start', behavior: 'smooth' })
+      }
+    },
+    querySearch(queryString, cb) {
+      const results = this.searchData.filter(searchObj => searchObj.search.find(el => el.includes(queryString.toLowerCase())))
+        .map(searchObj => {
+          return searchObj.groupKey === ':opts'
+            ? { value: `${searchObj.label} in Auto Linker`, group: searchObj.groupKey, key: searchObj.key }
+            : { value: `${searchObj.label} in ${searchObj.groupLabel}`, group: searchObj.groupKey, key: searchObj.key }
+        })
+      cb(results)
     }
   }
 }
diff --git a/src/views/settings/styles/main.scss b/src/views/settings/styles/main.scss
index 8e6cb4cf4e63cc25cf63d30b356e420855869869..884ad08e025f2db04dd21e5eb79841c11314ceec 100644
--- a/src/views/settings/styles/main.scss
+++ b/src/views/settings/styles/main.scss
@@ -277,6 +277,10 @@
     padding: 10px;
     margin-right: 5px;
   }
+  .settings-search-input {
+    width: 350px;
+    margin-left: 5px;
+  }
   .single-input {
     margin-right: 10px
   }
@@ -406,6 +410,13 @@
     .limit-input {
       width: 45%;
     }
+    .nav-container {
+      display: flex;
+      height: 36px;
+      justify-content: space-between;
+      align-items: center;
+      margin: 15px;
+    }
     .proxy-url-input {
       flex-direction: column;
       align-items: flex-start;
@@ -446,12 +457,12 @@
     .settings-header-container {
       margin: 10px 15px 15px 15px;
     }
-    .nav-container {
-      display: flex;
-      height: 36px;
-      justify-content: space-between;
-      align-items: center;
-      margin: 15px;
+    .settings-search-input {
+      width: 100%;
+      margin-left: 0;
+    }
+    .settings-search-input-container {
+      margin: 0 15px 15px 15px;
     }
     .settings-menu {
       width: 163px;
@@ -530,7 +541,6 @@
       margin-right: 8px
     }
   }
-
   @media only screen and (max-width:801px) and (min-width: 481px) {
     .delete-setting-button {
       margin: 4px 0 0 10px;
@@ -575,5 +585,9 @@
     .settings-delete-button {
       float: right;
     }
+    .settings-search-input {
+      width: 250px;
+      margin: 0 0 15px 15px;
+    }
   }
 }
diff --git a/src/views/users/components/ModerationDropdown.vue b/src/views/users/components/ModerationDropdown.vue
index e4a974c131659bf2811edd2672291e3465f85dc9..fad336c3d2324a6a317a0bd5434477a3e9b973e5 100644
--- a/src/views/users/components/ModerationDropdown.vue
+++ b/src/views/users/components/ModerationDropdown.vue
@@ -172,7 +172,7 @@ export default {
 <style rel='stylesheet/scss' lang='scss'>
   .moderate-user-button {
     text-align: left;
-    width: 200px;
+    width: 350px;
     padding: 10px;
   }
   .moderate-user-button-container {
diff --git a/src/views/users/index.vue b/src/views/users/index.vue
index d6b12e68d167d0e1102b19b305d2ca1e8bfd6c56..85be0bee322489bc7048fd25b1e17ce9cc7d935e 100644
--- a/src/views/users/index.vue
+++ b/src/views/users/index.vue
@@ -6,7 +6,12 @@
     </h1>
     <div class="filter-container">
       <users-filter/>
-      <el-input :placeholder="$t('users.search')" v-model="search" class="search" @input="handleDebounceSearchInput"/>
+      <el-input
+        :placeholder="$t('users.search')"
+        v-model="search"
+        prefix-icon="el-icon-search"
+        class="search"
+        @input="handleDebounceSearchInput"/>
     </div>
     <div class="actions-container">
       <el-button class="actions-button" @click="createAccountDialogOpen = true">
diff --git a/test/views/invites/index.test.js b/test/views/invites/index.test.js
index c4a1b4efe5e36f603bc871b15615ff4facc23e2b..6789a3a87334283205afafb7039b798dbcdb3f9d 100644
--- a/test/views/invites/index.test.js
+++ b/test/views/invites/index.test.js
@@ -44,19 +44,18 @@ describe('Invite tokens', () => {
     })
     await flushPromises()
 
-    const dialog = wrapper.find('div.el-dialog__wrapper .create-new-token-dialog')
-    expect(dialog.isVisible()).toBe(false)
-
+    wrapper.setData({ createTokenDialogVisible: false })
     const openDialogButton = wrapper.find('button.create-invite-token')
-    const closeDialogButton = wrapper.find('div.el-dialog__footer button')
+    const closeDialogButton = wrapper.find('div.el-dialog__footer button.invites-close-dialog')
+    expect(wrapper.vm.createTokenDialogVisible).toBe(false)
 
     openDialogButton.trigger('click')
     await flushPromises()
-    expect(dialog.isVisible()).toBe(true)
+    expect(wrapper.vm.createTokenDialogVisible).toBe(true)
 
     closeDialogButton.trigger('click')
     await flushPromises()
-    expect(dialog.isVisible()).toBe(false)
+    expect(wrapper.vm.createTokenDialogVisible).toBe(false)
     done()
   })
 
diff --git a/test/views/reports/status.test.js b/test/views/reports/status.test.js
index 3551cf7393421e3c9385ca1ea905d11be0f4155a..08423403dc6762d90b8d00385551429f67acd2aa 100644
--- a/test/views/reports/status.test.js
+++ b/test/views/reports/status.test.js
@@ -33,7 +33,8 @@ describe('Status in reports', () => {
         status,
         page: 1,
         userId: '7',
-        godmode: false
+        godmode: false,
+        showCheckbox: false
       }
     })
     await flushPromises()
@@ -58,7 +59,8 @@ describe('Status in reports', () => {
         status,
         page: 1,
         userId: '7',
-        godmode: false
+        godmode: false,
+        showCheckbox: false
       }
     })
     await flushPromises()
@@ -83,7 +85,8 @@ describe('Status in reports', () => {
         status,
         page: 1,
         userId: '7',
-        godmode: false
+        godmode: false,
+        showCheckbox: false
       }
     })
     await flushPromises()
@@ -108,7 +111,8 @@ describe('Status in reports', () => {
         status,
         page: 1,
         userId: '7',
-        godmode: false
+        godmode: false,
+        showCheckbox: false
       }
     })
     await flushPromises()
@@ -133,7 +137,8 @@ describe('Status in reports', () => {
         status,
         page: 1,
         userId: '7',
-        godmode: false
+        godmode: false,
+        showCheckbox: false
       }
     })
     await flushPromises()
diff --git a/test/views/settings/formSearchObject.test.js b/test/views/settings/formSearchObject.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..dbabbc872fc38fffa29e362b03071a07e0e71dab
--- /dev/null
+++ b/test/views/settings/formSearchObject.test.js
@@ -0,0 +1,213 @@
+import { formSearchObject } from '@/store/modules/normalizers'
+import _ from 'lodash'
+
+describe('Form search object', () => {
+  it('forms search object for regular setting', () => {
+    const description = [{
+      description: "Upload general settings",
+      group: ":pleroma",
+      key: "Pleroma.Upload",
+      label: "Pleroma.Upload",
+      children: [
+        { description: "Module which will be used for uploads",
+          key: ":uploader",
+          label: "Uploader" },
+        { description: "List of filter modules for uploads",
+          key: ":filters",
+          label: "Filters" }
+      ]
+    }]
+    const expected = [
+      { label: "Pleroma.Upload",
+        key: "Pleroma.Upload",
+        groupKey: "Pleroma.Upload",
+        groupLabel: "Pleroma.Upload",
+        search: [
+          "pleroma.upload",
+          "pleroma.upload",
+          "upload general settings"
+        ]
+      },
+      { label: "Uploader",
+        key: ":uploader",
+        groupKey: "Pleroma.Upload",
+        groupLabel: "Pleroma.Upload",
+        search: [
+          ":uploader",
+          "uploader",
+          "module which will be used for uploads"
+        ]
+      },
+      { label: "Filters",
+        key: ":filters",
+        groupKey: "Pleroma.Upload",
+        groupLabel: "Pleroma.Upload",
+        search: [
+          ":filters",
+          "filters",
+          "list of filter modules for uploads"
+        ]
+      }
+    ]
+    expect(_.isEqual(formSearchObject(description), expected)).toBeTruthy()
+  })
+
+  it('forms search object for setting without key', () => {
+    const description = [{
+      description: "`Swoosh.Adapters.Local` adapter specific settings",
+      group: ":swoosh",
+      label: "Swoosh",
+      children: [
+        { description: "Run the preview server together as part of your app",
+          group: [":subgroup", "Swoosh.Adapters.Local"],
+          key: ":serve_mailbox",
+          label: "Serve mailbox"
+        }
+      ]
+    }]
+    const expected = [
+      { label: "Swoosh",
+        key: ":swoosh",
+        groupKey: ":swoosh",
+        groupLabel: "Swoosh",
+        search: ["swoosh", "`swoosh.adapters.local` adapter specific settings"]
+      },
+      { label: "Serve mailbox",
+        key: ":serve_mailbox",
+        groupKey: ":swoosh",
+        groupLabel: "Swoosh",
+        search: [
+          ":serve_mailbox",
+          "serve mailbox",
+          "run the preview server together as part of your app"
+        ]
+      }
+    ]
+    expect(_.isEqual(formSearchObject(description), expected)).toBeTruthy()
+  })
+
+  it('forms search object for setting without key and description', () => {
+    const description = [{
+      group: ":cors_plug",
+      label: "Cors plug",
+      children: [
+        { key: ":max_age",
+          label: "Max age" },
+        { key: ":methods",
+          label: "Methods" }
+      ]
+    }]
+    const expected = [
+      { label: "Cors plug",
+        key: ":cors_plug",
+        groupKey: ":cors_plug",
+        groupLabel: "Cors plug",
+        search: ["cors plug"]
+      },
+      { label: "Max age",
+        key: ":max_age",
+        groupKey: ":cors_plug",
+        groupLabel: "Cors plug",
+        search: [":max_age", "max age"]
+      },
+      { label: "Methods",
+        key: ":methods",
+        groupKey: ":cors_plug",
+        groupLabel: "Cors plug",
+        search: [":methods", "methods"]
+      }
+    ]
+    expect(_.isEqual(formSearchObject(description), expected)).toBeTruthy()
+  })
+
+  it('forms search object for setting without key in pleroma group', () => {
+    const description = [{
+      description: "Allows to set a token",
+      group: ":pleroma",
+      label: "Pleroma",
+      children: [
+        { description: "Token",
+          key: ":admin_token",
+          label: "Admin token" }
+      ]
+    }]
+    const expected = [{
+      label: "Admin token",
+      key: ":admin_token",
+      groupKey: ":pleroma",
+      groupLabel: "Pleroma",
+      search: [":admin_token", "admin token", "token"]
+    }]
+    expect(_.isEqual(formSearchObject(description), expected)).toBeTruthy()
+  })
+
+  it('forms search object for nested setting', () => {
+    const description = [{
+      description: "Media proxy",
+      group: ":pleroma",
+      key: ":media_proxy",
+      label: "Media proxy",
+      children: [
+        { description: "Options for Pleroma.ReverseProxy",
+        key: ":proxy_opts",
+        label: "Proxy opts",
+        children: [
+          { description: "HTTP options",
+            key: ":http",
+            label: "Http",
+            children: [
+              { description: "Adapter specific options",
+                key: ":adapter",
+                label: "Adapter",
+                children: [
+                  { description: "SSL options for HTTP adapter",
+                    key: ":ssl_options",
+                    label: "SSL Options"
+                  }
+                ]
+              }
+            ]
+          }
+        ]}
+      ]
+    }]
+    const expected = [
+      {
+        label: "Media proxy",
+        key: ":media_proxy",
+        groupKey: ":media_proxy",
+        groupLabel: "Media proxy",
+        search: [":media_proxy", "media proxy", "media proxy"]
+      },
+      {
+        label: "Proxy opts",
+        key: ":proxy_opts",
+        groupKey: ":media_proxy",
+        groupLabel: "Media proxy",
+        search: [":proxy_opts", "proxy opts", "options for pleroma.reverseproxy"]
+      },
+      {
+        label: "Http",
+        key: ":http",
+        groupKey: ":media_proxy",
+        groupLabel: "Media proxy",
+        search: [":http", "http", "http options"]
+      },
+      {
+        label: "Adapter",
+        key: ":adapter",
+        groupKey: ":media_proxy",
+        groupLabel: "Media proxy",
+        search: [":adapter", "adapter", "adapter specific options"]
+      },
+      {
+        label: "SSL Options",
+        key: ":ssl_options",
+        groupKey: ":media_proxy",
+        groupLabel: "Media proxy",
+        search: [":ssl_options", "ssl options", "ssl options for http adapter"]
+      }
+    ]
+    expect(_.isEqual(formSearchObject(description), expected)).toBeTruthy()
+  })
+})
diff --git a/test/views/settings/index.test.js b/test/views/settings/index.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e46b9e659c914aa77e30d2b1a30c621c1b303b3
--- /dev/null
+++ b/test/views/settings/index.test.js
@@ -0,0 +1,63 @@
+import Vuex from 'vuex'
+import { mount, createLocalVue, config } from '@vue/test-utils'
+import Element from 'element-ui'
+import Settings from '@/views/settings/index'
+import flushPromises from 'flush-promises'
+import app from '@/store/modules/app'
+import settings from '@/store/modules/settings'
+import getters from '@/store/getters'
+
+config.mocks["$t"] = () => {}
+
+const localVue = createLocalVue()
+localVue.use(Vuex)
+localVue.use(Element)
+
+describe('Settings search', () => {
+  let store
+  let actions
+
+  beforeEach(() => {
+    actions = { ...settings.actions, FetchSettings: jest.fn() }
+    store = new Vuex.Store({
+      modules: {
+        app,
+        settings: { ...settings, actions }
+      },
+      getters
+    })
+  })
+
+  it('shows search input', async (done) => {
+    const wrapper = mount(Settings, {
+      store,
+      localVue
+    })
+
+    await flushPromises()
+    const searchInput = wrapper.find('.settings-search-input')
+    expect(searchInput.exists()).toBe(true)
+    done()
+  })
+  it('changes tab when search value was selected', async (done) => {
+    const wrapper = mount(Settings, {
+      store,
+      localVue
+    })
+    wrapper.vm.handleSearchSelect({ group: 'Pleroma.Upload', key: 'Pleroma.Upload' })
+    expect(store.state.settings.activeTab).toBe('upload')
+
+    wrapper.vm.handleSearchSelect({ group: ':swoosh', key: ':serve_mailbox' })
+    expect(store.state.settings.activeTab).toBe('mailer')
+
+    wrapper.vm.handleSearchSelect({ group: ':pleroma', key: ':admin_token' })
+    expect(store.state.settings.activeTab).toBe('instance')
+
+    wrapper.vm.handleSearchSelect({ group: ':media_proxy', key: ':ssl_options' })
+    expect(store.state.settings.activeTab).toBe('media-proxy')
+
+    wrapper.vm.handleSearchSelect({ group: ':opts', key: ':opts' })
+    expect(store.state.settings.activeTab).toBe('auto-linker')
+    done()
+  })
+})
diff --git a/test/views/users/index.test.js b/test/views/users/index.test.js
index 63473aaf9261e123735050abcc0153dc6a517ca3..0000421498a91f885d07dfeb4067eaf2edb9ba55 100644
--- a/test/views/users/index.test.js
+++ b/test/views/users/index.test.js
@@ -239,21 +239,21 @@ describe('Users actions', () => {
     })
     await flushPromises()
 
-    const dialog = wrapper.find('.password-reset-token-dialog')
+    wrapper.setData({ resetPasswordDialogOpen: false })
     const closeDialogButton = wrapper.find('.password-reset-token-dialog button')
-    expect(dialog.isVisible()).toBe(false)
+    expect(wrapper.vm.resetPasswordDialogOpen).toBe(false)
     expect(store.state.users.passwordResetToken.token).toBe('')
 
     wrapper.find(htmlElement(1, 11)).trigger('click')
     await flushPromises()
 
-    expect(dialog.isVisible()).toBe(true)
+    expect(wrapper.vm.resetPasswordDialogOpen).toBe(true)
     expect(store.state.users.passwordResetToken.token).toBe('g05lxnBJQnL')
     expect(store.state.users.passwordResetToken.link).toBe('http://url/api/pleroma/password_reset/g05lxnBJQnL')
 
     closeDialogButton.trigger('click')
     await flushPromises()
-    expect(dialog.isVisible()).toBe(false)
+    expect(wrapper.vm.resetPasswordDialogOpen).toBe(false)
     done()
   })
 })
@@ -278,19 +278,18 @@ describe('Creates new account', () => {
     })
     await flushPromises()
 
-    const dialog = wrapper.find('div.el-dialog__wrapper')
-    expect(dialog.isVisible()).toBe(false)
-
+    wrapper.setData({ createAccountDialogOpen: false })
     const openDialogButton = wrapper.find('button.actions-button')
     const closeDialogButton = wrapper.find('div.el-dialog__footer button')
+    expect(wrapper.vm.createAccountDialogOpen).toBe(false)
 
     openDialogButton.trigger('click')
     await flushPromises()
-    expect(dialog.isVisible()).toBe(true)
+    expect(wrapper.vm.createAccountDialogOpen).toBe(true)
 
     closeDialogButton.trigger('click')
     await flushPromises()
-    expect(dialog.isVisible()).toBe(false)
+    expect(wrapper.vm.createAccountDialogOpen).toBe(false)
     done()
   })
 
diff --git a/yarn.lock b/yarn.lock
index 9a72fd1c2312b1a56abd645c9cbf1e96c6cf9d34..9f9b284d7310608a96199e85a2aa25658afaace9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1013,12 +1013,13 @@
     vue-template-es2015-compiler "^1.9.0"
 
 "@vue/test-utils@^1.0.0-beta.29":
-  version "1.0.0-beta.29"
-  resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz#c942cf25e891cf081b6a03332b4ae1ef430726f0"
-  integrity sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA==
+  version "1.0.0-beta.32"
+  resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.32.tgz#38c3947886236201a3f24b583c73598eb95ccc69"
+  integrity sha512-ywhe7PATMAk/ZGdsrcuQIliQusOyfe0OOHjKKCCERqgHh1g/kqPtmSMT5Jx4sErx53SYbNucr8QOK6/u5ianAw==
   dependencies:
     dom-event-types "^1.0.0"
-    lodash "^4.17.4"
+    lodash "^4.17.15"
+    pretty "^2.0.0"
 
 "@webassemblyjs/ast@1.8.5":
   version "1.8.5"
@@ -2496,6 +2497,11 @@ commander@^2.13.0, commander@^2.14.1, commander@^2.9.0:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
   integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
 
+commander@^2.19.0:
+  version "2.20.3"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+  integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
 commander@~2.13.0:
   version "2.13.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
@@ -2568,6 +2574,23 @@ concat-stream@^1.5.0, concat-stream@^1.6.0:
     readable-stream "^2.2.2"
     typedarray "^0.0.6"
 
+condense-newlines@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f"
+  integrity sha1-PemFVTE5R10yUCyDsC9gaE0kxV8=
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-whitespace "^0.3.0"
+    kind-of "^3.0.2"
+
+config-chain@^1.1.12:
+  version "1.1.12"
+  resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
+  integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+  dependencies:
+    ini "^1.3.4"
+    proto-list "~1.2.1"
+
 connect-history-api-fallback@^1.3.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
@@ -3431,6 +3454,16 @@ echarts@4.1.0:
   dependencies:
     zrender "4.0.4"
 
+editorconfig@^0.15.3:
+  version "0.15.3"
+  resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
+  integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
+  dependencies:
+    commander "^2.19.0"
+    lru-cache "^4.1.5"
+    semver "^5.6.0"
+    sigmund "^1.0.1"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -4399,7 +4432,7 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
   integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@@ -4411,6 +4444,18 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, gl
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
+glob@^7.1.3:
+  version "7.1.6"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+  integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
 global-modules@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
@@ -4934,16 +4979,21 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
-  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+inherits@2:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 
 inherits@2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
   integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
 
+inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
 ini@^1.3.4, ini@~1.3.0:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
@@ -5289,6 +5339,11 @@ is-utf8@^0.2.0:
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
   integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
 
+is-whitespace@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f"
+  integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38=
+
 is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@@ -5776,6 +5831,17 @@ js-base64@^2.1.8, js-base64@^2.1.9:
   resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
   integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
 
+js-beautify@^1.6.12:
+  version "1.10.3"
+  resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1"
+  integrity sha512-wfk/IAWobz1TfApSdivH5PJ0miIHgDoYb1ugSqHcODPmaYu46rYe5FVuIEkhjg8IQiv6rDNPyhsqbsohI/C2vQ==
+  dependencies:
+    config-chain "^1.1.12"
+    editorconfig "^0.15.3"
+    glob "^7.1.3"
+    mkdirp "~0.5.1"
+    nopt "~4.0.1"
+
 js-cookie@2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.0.tgz#1b2c279a6eece380a12168b92485265b35b1effb"
@@ -6218,6 +6284,11 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4,
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
   integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
 
+lodash@^4.17.15:
+  version "4.17.15"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+  integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
 log-symbols@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@@ -6274,7 +6345,7 @@ lower-case@^1.1.1:
   resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
   integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
 
-lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2:
+lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.5:
   version "4.1.5"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
   integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
@@ -6567,6 +6638,11 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
 
+minimist@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+  integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
 minimist@~0.0.1:
   version "0.0.10"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
@@ -6640,13 +6716,20 @@ mixin-object@^2.0.1:
     for-in "^0.1.3"
     is-extendable "^0.1.1"
 
-mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
+mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
   dependencies:
     minimist "0.0.8"
 
+mkdirp@~0.5.1:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c"
+  integrity sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==
+  dependencies:
+    minimist "^1.2.5"
+
 moment@^2.24.0:
   version "2.24.0"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
@@ -6919,6 +7002,14 @@ nopt@^4.0.1:
     abbrev "1"
     osenv "^0.1.4"
 
+nopt@~4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
+  integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
+  dependencies:
+    abbrev "1"
+    osenv "^0.1.4"
+
 normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -8022,6 +8113,15 @@ pretty-format@^24.3.0:
     ansi-regex "^4.0.0"
     ansi-styles "^3.2.0"
 
+pretty@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5"
+  integrity sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU=
+  dependencies:
+    condense-newlines "^0.2.1"
+    extend-shallow "^2.0.1"
+    js-beautify "^1.6.12"
+
 printj@~1.1.0, printj@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
@@ -8065,6 +8165,11 @@ prompts@^2.0.1:
     kleur "^3.0.2"
     sisteransi "^1.0.0"
 
+proto-list@~1.2.1:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+  integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
 proxy-addr@~2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
@@ -8792,7 +8897,7 @@ semver-compare@^1.0.0:
   resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
   integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1:
   version "5.6.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
   integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
@@ -8802,6 +8907,11 @@ semver@5.5.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
   integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
 
+semver@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
 semver@~5.3.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
@@ -8939,6 +9049,11 @@ showdown@1.8.6:
   dependencies:
     yargs "^10.0.3"
 
+sigmund@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
+  integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
+
 signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"