From c6d4c20982261b55b16dda59c3e657eb1feb0041 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:11:44 +0200
Subject: [PATCH 1/9] Made Select component to make using styled selects easier

---
 src/App.scss                                  | 34 +--------
 src/components/font_control/font_control.js   | 12 ++--
 src/components/font_control/font_control.vue  | 32 +++------
 .../interface_language_switcher.vue           | 41 ++++-------
 src/components/poll/poll_form.js              |  6 +-
 src/components/poll/poll_form.vue             | 51 +++++--------
 .../post_status_form/post_status_form.js      |  4 +-
 .../post_status_form/post_status_form.vue     | 31 +++-----
 src/components/select/select.vue              | 67 +++++++++++++++++
 .../settings_modal/tabs/filtering_tab.js      | 12 +---
 .../settings_modal/tabs/filtering_tab.vue     | 38 +++++-----
 .../settings_modal/tabs/general_tab.js        |  6 +-
 .../settings_modal/tabs/general_tab.vue       | 72 +++++++------------
 .../tabs/theme_tab/theme_tab.js               | 12 +---
 .../tabs/theme_tab/theme_tab.vue              | 70 +++++++-----------
 .../shadow_control/shadow_control.js          |  4 +-
 .../shadow_control/shadow_control.vue         | 32 +++------
 src/components/user_card/user_card.js         |  6 +-
 src/components/user_card/user_card.vue        | 27 +++----
 19 files changed, 240 insertions(+), 317 deletions(-)
 create mode 100644 src/components/select/select.vue

diff --git a/src/App.scss b/src/App.scss
index 90d083bb..77f2ea79 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -187,7 +187,7 @@ a {
   }
 }
 
-input, textarea, .select, .input {
+input, textarea, .input {
 
   &.unstyled {
     border-radius: 0;
@@ -217,11 +217,7 @@ input, textarea, .select, .input {
   hyphens: none;
   padding: 8px .5em;
 
-  &.select {
-    padding: 0;
-  }
-
-  &:disabled, &[disabled=disabled] {
+  &:disabled, &[disabled=disabled], &.disabled {
     cursor: not-allowed;
     opacity: 0.5;
   }
@@ -239,25 +235,6 @@ input, textarea, .select, .input {
     pointer-events: none;
   }
 
-  select {
-    -webkit-appearance: none;
-    -moz-appearance: none;
-    appearance: none;
-    background: transparent;
-    border: none;
-    color: $fallback--text;
-    color: var(--inputText, --text, $fallback--text);
-    margin: 0;
-    padding: 0 2em 0 .2em;
-    font-family: sans-serif;
-    font-family: var(--inputFont, sans-serif);
-    font-size: 14px;
-    width: 100%;
-    z-index: 1;
-    height: 28px;
-    line-height: 16px;
-  }
-
   &[type=range] {
     background: none;
     border: none;
@@ -809,13 +786,6 @@ nav {
   }
 }
 
-.select-multiple {
-  display: flex;
-  .option-list {
-    margin: 0;
-    padding-left: .5em;
-  }
-}
 .setting-list,
 .option-list{
   list-style-type: none;
diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js
index 6274780b..137ef9c0 100644
--- a/src/components/font_control/font_control.js
+++ b/src/components/font_control/font_control.js
@@ -1,14 +1,10 @@
 import { set } from 'vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
+import Select from '../select/select.vue'
 
 export default {
+  components: {
+    Select
+  },
   props: [
     'name', 'label', 'value', 'fallback', 'options', 'no-inherit'
   ],
diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue
index dd117ec0..996ff92c 100644
--- a/src/components/font_control/font_control.vue
+++ b/src/components/font_control/font_control.vue
@@ -22,30 +22,20 @@
       class="opt-l"
       :for="name + '-o'"
     />
-    <label
-      :for="name + '-font-switcher'"
-      class="select"
+    <Select
+      :id="name + '-font-switcher'"
+      v-model="preset"
       :disabled="!present"
+      class="font-switcher"
     >
-      <select
-        :id="name + '-font-switcher'"
-        v-model="preset"
-        :disabled="!present"
-        class="font-switcher"
+      <option
+        v-for="option in availableOptions"
+        :key="option"
+        :value="option"
       >
-        <option
-          v-for="option in availableOptions"
-          :key="option"
-          :value="option"
-        >
-          {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
-        </option>
-      </select>
-      <FAIcon
-        class="select-down-icon"
-        icon="chevron-down"
-      />
-    </label>
+        {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
+      </option>
+    </Select>
     <input
       v-if="isCustom"
       :id="name"
diff --git a/src/components/interface_language_switcher/interface_language_switcher.vue b/src/components/interface_language_switcher/interface_language_switcher.vue
index dc3bd408..cf307a24 100644
--- a/src/components/interface_language_switcher/interface_language_switcher.vue
+++ b/src/components/interface_language_switcher/interface_language_switcher.vue
@@ -3,27 +3,18 @@
     <label for="interface-language-switcher">
       {{ $t('settings.interfaceLanguage') }}
     </label>
-    <label
-      for="interface-language-switcher"
-      class="select"
+    <Select
+      id="interface-language-switcher"
+      v-model="language"
     >
-      <select
-        id="interface-language-switcher"
-        v-model="language"
+      <option
+        v-for="lang in languages"
+        :key="lang.code"
+        :value="lang.code"
       >
-        <option
-          v-for="lang in languages"
-          :key="lang.code"
-          :value="lang.code"
-        >
-          {{ lang.name }}
-        </option>
-      </select>
-      <FAIcon
-        class="select-down-icon"
-        icon="chevron-down"
-      />
-    </label>
+        {{ lang.name }}
+      </option>
+    </Select>
   </div>
 </template>
 
@@ -32,16 +23,12 @@ import languagesObject from '../../i18n/messages'
 import localeService from '../../services/locale/locale.service.js'
 import ISO6391 from 'iso-639-1'
 import _ from 'lodash'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
+import Select from '../select/select.vue'
 
 export default {
+  components: {
+    Select
+  },
   computed: {
     languages () {
       return _.map(languagesObject.languages, (code) => ({ code: code, name: this.getLanguageName(code) })).sort((a, b) => a.name.localeCompare(b.name))
diff --git a/src/components/poll/poll_form.js b/src/components/poll/poll_form.js
index 1f8df3f9..e30645c3 100644
--- a/src/components/poll/poll_form.js
+++ b/src/components/poll/poll_form.js
@@ -1,19 +1,21 @@
 import * as DateUtils from 'src/services/date_utils/date_utils.js'
 import { uniq } from 'lodash'
 import { library } from '@fortawesome/fontawesome-svg-core'
+import Select from '../select/select.vue'
 import {
   faTimes,
-  faChevronDown,
   faPlus
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
   faTimes,
-  faChevronDown,
   faPlus
 )
 
 export default {
+  components: {
+    Select
+  },
   name: 'PollForm',
   props: ['visible'],
   data: () => ({
diff --git a/src/components/poll/poll_form.vue b/src/components/poll/poll_form.vue
index c4403210..f10d1550 100644
--- a/src/components/poll/poll_form.vue
+++ b/src/components/poll/poll_form.vue
@@ -46,23 +46,13 @@
         class="poll-type"
         :title="$t('polls.type')"
       >
-        <label
-          for="poll-type-selector"
-          class="select"
+        <Select
+          v-model="pollType"
+          @change="updatePollToParent"
         >
-          <select
-            v-model="pollType"
-            class="select"
-            @change="updatePollToParent"
-          >
-            <option value="single">{{ $t('polls.single_choice') }}</option>
-            <option value="multiple">{{ $t('polls.multiple_choices') }}</option>
-          </select>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+          <option value="single">{{ $t('polls.single_choice') }}</option>
+          <option value="multiple">{{ $t('polls.multiple_choices') }}</option>
+        </Select>
       </div>
       <div
         class="poll-expiry"
@@ -76,24 +66,19 @@
           :max="maxExpirationInCurrentUnit"
           @change="expiryAmountChange"
         >
-        <label class="expiry-unit select">
-          <select
-            v-model="expiryUnit"
-            @change="expiryAmountChange"
+        <Select
+          v-model="expiryUnit"
+          class="expiry-unit"
+          @change="expiryAmountChange"
+        >
+          <option
+            v-for="unit in expiryUnits"
+            :key="unit"
+            :value="unit"
           >
-            <option
-              v-for="unit in expiryUnits"
-              :key="unit"
-              :value="unit"
-            >
-              {{ $t(`time.${unit}_short`, ['']) }}
-            </option>
-          </select>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+            {{ $t(`time.${unit}_short`, ['']) }}
+          </option>
+        </Select>
       </div>
     </div>
   </div>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index e540654b..5342894f 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -11,10 +11,10 @@ import { reject, map, uniqBy, debounce } from 'lodash'
 import suggestor from '../emoji_input/suggestor.js'
 import { mapGetters, mapState } from 'vuex'
 import Checkbox from '../checkbox/checkbox.vue'
+import Select from '../select/select.vue'
 
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
-  faChevronDown,
   faSmileBeam,
   faPollH,
   faUpload,
@@ -24,7 +24,6 @@ import {
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
-  faChevronDown,
   faSmileBeam,
   faPollH,
   faUpload,
@@ -84,6 +83,7 @@ const PostStatusForm = {
     PollForm,
     ScopeSelector,
     Checkbox,
+    Select,
     Attachment,
     StatusContent
   },
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 73f6a4f1..cc4f6251 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -189,28 +189,19 @@
             v-if="postFormats.length > 1"
             class="text-format"
           >
-            <label
-              for="post-content-type"
-              class="select"
+            <Select
+              id="post-content-type"
+              v-model="newStatus.contentType"
+              class="form-control"
             >
-              <select
-                id="post-content-type"
-                v-model="newStatus.contentType"
-                class="form-control"
+              <option
+                v-for="postFormat in postFormats"
+                :key="postFormat"
+                :value="postFormat"
               >
-                <option
-                  v-for="postFormat in postFormats"
-                  :key="postFormat"
-                  :value="postFormat"
-                >
-                  {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+                {{ $t(`post_status.content_type["${postFormat}"]`) }}
+              </option>
+            </Select>
           </div>
           <div
             v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'"
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
new file mode 100644
index 00000000..a27a2541
--- /dev/null
+++ b/src/components/select/select.vue
@@ -0,0 +1,67 @@
+
+<template>
+  <label
+    class="Select input"
+    :class="{ disabled }"
+  >
+    <select
+      :disabled="disabled"
+      :value="value"
+      @change="$emit('change', $event.target.value)"
+    >
+      <slot />
+    </select>
+    <FAIcon
+      class="select-down-icon"
+      icon="chevron-down"
+    />
+  </label>
+</template>
+
+<script>
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faChevronDown
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faChevronDown
+)
+export default {
+  model: {
+    prop: 'value',
+    event: 'change'
+  },
+  props: [
+    'value',
+    'disabled'
+  ]
+}
+</script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.Select {
+  padding: 0;
+
+  select {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    background: transparent;
+    border: none;
+    color: $fallback--text;
+    color: var(--inputText, --text, $fallback--text);
+    margin: 0;
+    padding: 0 2em 0 .2em;
+    font-family: sans-serif;
+    font-family: var(--inputFont, sans-serif);
+    font-size: 14px;
+    width: 100%;
+    z-index: 1;
+    height: 28px;
+    line-height: 16px;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 6e95f7af..89199d85 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -1,15 +1,8 @@
 import { filter, trim } from 'lodash'
 import BooleanSetting from '../helpers/boolean_setting.vue'
+import Select from '../../select/select.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
 
 const FilteringTab = {
   data () {
@@ -18,7 +11,8 @@ const FilteringTab = {
     }
   },
   components: {
-    BooleanSetting
+    BooleanSetting,
+    Select
   },
   computed: {
     ...SharedComputedObject(),
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 402c2a4a..4023fbe2 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -38,26 +38,17 @@
       </div>
       <div>
         {{ $t('settings.replies_in_timeline') }}
-        <label
-          for="replyVisibility"
-          class="select"
+        <Select
+          id="replyVisibility"
+          v-model="replyVisibility"
         >
-          <select
-            id="replyVisibility"
-            v-model="replyVisibility"
-          >
-            <option
-              value="all"
-              selected
-            >{{ $t('settings.reply_visibility_all') }}</option>
-            <option value="following">{{ $t('settings.reply_visibility_following') }}</option>
-            <option value="self">{{ $t('settings.reply_visibility_self') }}</option>
-          </select>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+          <option
+            value="all"
+            selected
+          >{{ $t('settings.reply_visibility_all') }}</option>
+          <option value="following">{{ $t('settings.reply_visibility_following') }}</option>
+          <option value="self">{{ $t('settings.reply_visibility_self') }}</option>
+        </Select>
       </div>
       <div>
         <BooleanSetting path="hidePostStats">
@@ -88,3 +79,12 @@
   </div>
 </template>
 <script src="./filtering_tab.js"></script>
+<style lang="scss">
+.select-multiple {
+  display: flex;
+  .option-list {
+    margin: 0;
+    padding-left: .5em;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 2db523be..03648d0b 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -1,15 +1,14 @@
 import BooleanSetting from '../helpers/boolean_setting.vue'
+import Select from '../../select/select.vue'
 import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
-  faChevronDown,
   faGlobe
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
-  faChevronDown,
   faGlobe
 )
 
@@ -27,7 +26,8 @@ const GeneralTab = {
   },
   components: {
     BooleanSetting,
-    InterfaceLanguageSwitcher
+    InterfaceLanguageSwitcher,
+    Select
   },
   computed: {
     postFormats () {
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 9228c78e..a0413cfa 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -87,59 +87,41 @@
         <li>
           <div>
             {{ $t('settings.subject_line_behavior') }}
-            <label
-              for="subjectLineBehavior"
-              class="select"
+            <Select
+              id="subjectLineBehavior"
+              v-model="subjectLineBehavior"
             >
-              <select
-                id="subjectLineBehavior"
-                v-model="subjectLineBehavior"
-              >
-                <option value="email">
-                  {{ $t('settings.subject_line_email') }}
-                  {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-                <option value="masto">
-                  {{ $t('settings.subject_line_mastodon') }}
-                  {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-                <option value="noop">
-                  {{ $t('settings.subject_line_noop') }}
-                  {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+              <option value="email">
+                {{ $t('settings.subject_line_email') }}
+                {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+              <option value="masto">
+                {{ $t('settings.subject_line_mastodon') }}
+                {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+              <option value="noop">
+                {{ $t('settings.subject_line_noop') }}
+                {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+            </Select>
           </div>
         </li>
         <li v-if="postFormats.length > 0">
           <div>
             {{ $t('settings.post_status_content_type') }}
-            <label
-              for="postContentType"
-              class="select"
+            <Select
+              id="postContentType"
+              v-model="postContentType"
             >
-              <select
-                id="postContentType"
-                v-model="postContentType"
+              <option
+                v-for="postFormat in postFormats"
+                :key="postFormat"
+                :value="postFormat"
               >
-                <option
-                  v-for="postFormat in postFormats"
-                  :key="postFormat"
-                  :value="postFormat"
-                >
-                  {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                  {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+                {{ $t(`post_status.content_type["${postFormat}"]`) }}
+                {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
+              </option>
+            </Select>
           </div>
         </li>
         <li>
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index 6cf75fe7..73068e19 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -33,16 +33,9 @@ import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
 import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
 import ExportImport from 'src/components/export_import/export_import.vue'
 import Checkbox from 'src/components/checkbox/checkbox.vue'
+import Select from 'src/components/select/select.vue'
 
 import Preview from './preview.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
 
 // List of color values used in v1
 const v1OnlyNames = [
@@ -384,7 +377,8 @@ export default {
     TabSwitcher,
     Preview,
     ExportImport,
-    Checkbox
+    Checkbox,
+    Select
   },
   methods: {
     loadTheme (
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index b8add42f..2b4b8ba0 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -59,32 +59,23 @@
           <template slot="before">
             <div class="presets">
               {{ $t('settings.presets') }}
-              <label
-                for="preset-switcher"
-                class="select"
+              <Select
+                id="preset-switcher"
+                v-model="selected"
+                class="preset-switcher"
               >
-                <select
-                  id="preset-switcher"
-                  v-model="selected"
-                  class="preset-switcher"
+                <option
+                  v-for="style in availableStyles"
+                  :key="style.name"
+                  :value="style"
+                  :style="{
+                    backgroundColor: style[1] || (style.theme || style.source).colors.bg,
+                    color: style[3] || (style.theme || style.source).colors.text
+                  }"
                 >
-                  <option
-                    v-for="style in availableStyles"
-                    :key="style.name"
-                    :value="style"
-                    :style="{
-                      backgroundColor: style[1] || (style.theme || style.source).colors.bg,
-                      color: style[3] || (style.theme || style.source).colors.text
-                    }"
-                  >
-                    {{ style[0] || style.name }}
-                  </option>
-                </select>
-                <FAIcon
-                  class="select-down-icon"
-                  icon="chevron-down"
-                />
-              </label>
+                  {{ style[0] || style.name }}
+                </option>
+              </Select>
             </div>
           </template>
         </ExportImport>
@@ -902,28 +893,19 @@
           <div class="tab-header shadow-selector">
             <div class="select-container">
               {{ $t('settings.style.shadows.component') }}
-              <label
-                for="shadow-switcher"
-                class="select"
+              <Select
+                id="shadow-switcher"
+                v-model="shadowSelected"
+                class="shadow-switcher"
               >
-                <select
-                  id="shadow-switcher"
-                  v-model="shadowSelected"
-                  class="shadow-switcher"
+                <option
+                  v-for="shadow in shadowsAvailable"
+                  :key="shadow"
+                  :value="shadow"
                 >
-                  <option
-                    v-for="shadow in shadowsAvailable"
-                    :key="shadow"
-                    :value="shadow"
-                  >
-                    {{ $t('settings.style.shadows.components.' + shadow) }}
-                  </option>
-                </select>
-                <FAIcon
-                  class="select-down-icon"
-                  icon="chevron-down"
-                />
-              </label>
+                  {{ $t('settings.style.shadows.components.' + shadow) }}
+                </option>
+              </Select>
             </div>
             <div class="override">
               <label
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index 800c39d5..2d5d6eb1 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -1,5 +1,6 @@
 import ColorInput from '../color_input/color_input.vue'
 import OpacityInput from '../opacity_input/opacity_input.vue'
+import Select from '../select/select.vue'
 import { getCssShadow } from '../../services/style_setter/style_setter.js'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
@@ -45,7 +46,8 @@ export default {
   },
   components: {
     ColorInput,
-    OpacityInput
+    OpacityInput,
+    Select
   },
   methods: {
     add () {
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 37d491f0..6b5acbdb 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -59,30 +59,20 @@
         :disabled="usingFallback"
         class="id-control style-control"
       >
-        <label
-          for="shadow-switcher"
-          class="select"
+        <Select
+          id="shadow-switcher"
+          v-model="selectedId"
+          class="shadow-switcher"
           :disabled="!ready || usingFallback"
         >
-          <select
-            id="shadow-switcher"
-            v-model="selectedId"
-            class="shadow-switcher"
-            :disabled="!ready || usingFallback"
+          <option
+            v-for="(shadow, index) in cValue"
+            :key="index"
+            :value="index"
           >
-            <option
-              v-for="(shadow, index) in cValue"
-              :key="index"
-              :value="index"
-            >
-              {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
-            </option>
-          </select>
-          <FAIcon
-            icon="chevron-down"
-            class="select-down-icon"
-          />
-        </label>
+            {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
+          </option>
+        </Select>
         <button
           class="btn button-default"
           :disabled="!ready || !present"
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 3a8efafc..d9fb64d1 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -4,13 +4,13 @@ import ProgressButton from '../progress_button/progress_button.vue'
 import FollowButton from '../follow_button/follow_button.vue'
 import ModerationTools from '../moderation_tools/moderation_tools.vue'
 import AccountActions from '../account_actions/account_actions.vue'
+import Select from '../select/select.vue'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
 import { mapGetters } from 'vuex'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
   faBell,
   faRss,
-  faChevronDown,
   faSearchPlus,
   faExternalLinkAlt
 } from '@fortawesome/free-solid-svg-icons'
@@ -18,7 +18,6 @@ import {
 library.add(
   faRss,
   faBell,
-  faChevronDown,
   faSearchPlus,
   faExternalLinkAlt
 )
@@ -118,7 +117,8 @@ export default {
     ModerationTools,
     AccountActions,
     ProgressButton,
-    FollowButton
+    FollowButton,
+    Select
   },
   methods: {
     muteUser () {
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 4b7ee7d5..c5b73fde 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -132,25 +132,16 @@
               class="userHighlightCl"
               type="color"
             >
-            <label
-              for="theme_tab"
-              class="userHighlightSel select"
+            <Select
+              :id="'userHighlightSel'+user.id"
+              v-model="userHighlightType"
+              class="userHighlightSel"
             >
-              <select
-                :id="'userHighlightSel'+user.id"
-                v-model="userHighlightType"
-                class="userHighlightSel"
-              >
-                <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option>
-                <option value="solid">{{ $t('user_card.highlight.solid') }}</option>
-                <option value="striped">{{ $t('user_card.highlight.striped') }}</option>
-                <option value="side">{{ $t('user_card.highlight.side') }}</option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+              <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option>
+              <option value="solid">{{ $t('user_card.highlight.solid') }}</option>
+              <option value="striped">{{ $t('user_card.highlight.striped') }}</option>
+              <option value="side">{{ $t('user_card.highlight.side') }}</option>
+            </Select>
           </div>
         </div>
         <div

From 5d3bf43fdc83efb0294229df63201877032a85ff Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:19:11 +0200
Subject: [PATCH 2/9] ghost styles for poll form

---
 src/components/poll/poll_form.vue | 14 ++------------
 src/components/select/select.js   | 21 +++++++++++++++++++++
 src/components/select/select.vue  | 31 ++++++++++---------------------
 3 files changed, 33 insertions(+), 33 deletions(-)
 create mode 100644 src/components/select/select.js

diff --git a/src/components/poll/poll_form.vue b/src/components/poll/poll_form.vue
index f10d1550..f2459e45 100644
--- a/src/components/poll/poll_form.vue
+++ b/src/components/poll/poll_form.vue
@@ -47,6 +47,7 @@
         :title="$t('polls.type')"
       >
         <Select
+          kind="ghost"
           v-model="pollType"
           @change="updatePollToParent"
         >
@@ -68,6 +69,7 @@
         >
         <Select
           v-model="expiryUnit"
+          kind="ghost"
           class="expiry-unit"
           @change="expiryAmountChange"
         >
@@ -132,12 +134,6 @@
   .poll-type {
     margin-right: 0.75em;
     flex: 1 1 60%;
-    .select {
-      border: none;
-      box-shadow: none;
-      background-color: transparent;
-      padding-right: 0.75em;
-    }
   }
 
   .poll-expiry {
@@ -147,12 +143,6 @@
       width: 3em;
       text-align: right;
     }
-
-    .expiry-unit {
-      border: none;
-      box-shadow: none;
-      background-color: transparent;
-    }
   }
 }
 </style>
diff --git a/src/components/select/select.js b/src/components/select/select.js
new file mode 100644
index 00000000..49535d07
--- /dev/null
+++ b/src/components/select/select.js
@@ -0,0 +1,21 @@
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faChevronDown
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faChevronDown
+)
+
+export default {
+  model: {
+    prop: 'value',
+    event: 'change'
+  },
+  props: [
+    'value',
+    'disabled',
+    'unstyled',
+    'kind'
+  ]
+}
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
index a27a2541..55474e1a 100644
--- a/src/components/select/select.vue
+++ b/src/components/select/select.vue
@@ -2,7 +2,7 @@
 <template>
   <label
     class="Select input"
-    :class="{ disabled }"
+    :class="[ kindClass, { disabled } ]"
   >
     <select
       :disabled="disabled"
@@ -18,26 +18,7 @@
   </label>
 </template>
 
-<script>
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
-export default {
-  model: {
-    prop: 'value',
-    event: 'change'
-  },
-  props: [
-    'value',
-    'disabled'
-  ]
-}
-</script>
+<script src="./select.js"> </script>
 
 <style lang="scss">
 @import '../../_variables.scss';
@@ -45,6 +26,14 @@ export default {
 .Select {
   padding: 0;
 
+  /* Overriding input styles, probably should make proper Input component? */
+  &.-kind_ghost {
+    border: none;
+    box-shadow: none;
+    background-color: transparent;
+    padding-right: 0.75em;
+  }
+
   select {
     -webkit-appearance: none;
     -moz-appearance: none;

From 3870a30aeaeb9ed89e69610f2fc4ca6838fb1558 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:31:15 +0200
Subject: [PATCH 3/9] cleanup, fixes

---
 src/App.scss                                  | 13 ----------
 src/components/font_control/font_control.vue  |  3 ++-
 src/components/poll/poll_form.vue             |  9 +++++--
 src/components/select/select.vue              | 24 ++++++++++++-------
 .../shadow_control/shadow_control.vue         | 14 +++++------
 src/components/user_card/user_card.vue        | 10 ++------
 6 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/src/App.scss b/src/App.scss
index 77f2ea79..a537baed 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -222,19 +222,6 @@ input, textarea, .input {
     opacity: 0.5;
   }
 
-  .select-down-icon {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    right: 5px;
-    height: 100%;
-    color: $fallback--text;
-    color: var(--inputText, $fallback--text);
-    line-height: 28px;
-    z-index: 0;
-    pointer-events: none;
-  }
-
   &[type=range] {
     background: none;
     border: none;
diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue
index 996ff92c..29605084 100644
--- a/src/components/font_control/font_control.vue
+++ b/src/components/font_control/font_control.vue
@@ -55,7 +55,8 @@
     min-width: 10em;
   }
   &.custom {
-    .select {
+    /* TODO Should make proper joiners... */
+    .font-switcher {
       border-top-right-radius: 0;
       border-bottom-right-radius: 0;
     }
diff --git a/src/components/poll/poll_form.vue b/src/components/poll/poll_form.vue
index f2459e45..ecbfdf41 100644
--- a/src/components/poll/poll_form.vue
+++ b/src/components/poll/poll_form.vue
@@ -47,7 +47,8 @@
         :title="$t('polls.type')"
       >
         <Select
-          kind="ghost"
+          class="poll-type-select"
+          unstyled="true"
           v-model="pollType"
           @change="updatePollToParent"
         >
@@ -69,7 +70,7 @@
         >
         <Select
           v-model="expiryUnit"
-          kind="ghost"
+          unstyled="true"
           class="expiry-unit"
           @change="expiryAmountChange"
         >
@@ -134,6 +135,10 @@
   .poll-type {
     margin-right: 0.75em;
     flex: 1 1 60%;
+
+    .poll-type-select {
+      padding-right: 0.75em;
+    }
   }
 
   .poll-expiry {
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
index 55474e1a..5ade1fa6 100644
--- a/src/components/select/select.vue
+++ b/src/components/select/select.vue
@@ -2,7 +2,7 @@
 <template>
   <label
     class="Select input"
-    :class="[ kindClass, { disabled } ]"
+    :class="{ disabled, unstyled }"
   >
     <select
       :disabled="disabled"
@@ -26,14 +26,6 @@
 .Select {
   padding: 0;
 
-  /* Overriding input styles, probably should make proper Input component? */
-  &.-kind_ghost {
-    border: none;
-    box-shadow: none;
-    background-color: transparent;
-    padding-right: 0.75em;
-  }
-
   select {
     -webkit-appearance: none;
     -moz-appearance: none;
@@ -52,5 +44,19 @@
     height: 28px;
     line-height: 16px;
   }
+
+  .select-down-icon {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 5px;
+    height: 100%;
+    color: $fallback--text;
+    color: var(--inputText, $fallback--text);
+    line-height: 28px;
+    z-index: 0;
+    pointer-events: none;
+  }
+
 }
 </style>
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 6b5acbdb..511e07f3 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -306,20 +306,20 @@
 
     .id-control {
       align-items: stretch;
-      .select, .btn {
+
+      .shadow-switcher {
+        flex: 1;
+      }
+
+      .shadow-switcher, .btn {
         min-width: 1px;
         margin-right: 5px;
       }
+
       .btn {
         padding: 0 .4em;
         margin: 0 .1em;
       }
-      .select {
-        flex: 1;
-        select {
-          align-self: initial;
-        }
-      }
     }
   }
 }
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index c5b73fde..75c08f47 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -532,15 +532,11 @@
         flex: 1 0 auto;
       }
 
-      .userHighlightSel,
-      .userHighlightSel.select {
+      .userHighlightSel {
         padding-top: 0;
         padding-bottom: 0;
         flex: 1 0 auto;
       }
-      .userHighlightSel.select svg {
-        line-height: 22px;
-      }
 
       .userHighlightText {
         width: 70px;
@@ -549,9 +545,7 @@
 
       .userHighlightCl,
       .userHighlightText,
-      .userHighlightSel,
-      .userHighlightSel.select {
-        height: 22px;
+      .userHighlightSel {
         vertical-align: top;
         margin-right: .5em;
         margin-bottom: .25em;

From 1f0ac68fcd3f382eedf69d1f5fdcffdc16c3885e Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:55:14 +0200
Subject: [PATCH 4/9] implement ChoiceSetting for settings modal similar to
 BooleanSetting

---
 .../settings_modal/helpers/choice_setting.js  | 34 ++++++++++++++
 .../settings_modal/helpers/choice_setting.vue | 29 ++++++++++++
 .../settings_modal/tabs/filtering_tab.js      | 11 +++--
 .../settings_modal/tabs/filtering_tab.vue     | 17 ++-----
 .../settings_modal/tabs/general_tab.js        | 18 ++++++--
 .../settings_modal/tabs/general_tab.vue       | 46 +++++--------------
 6 files changed, 103 insertions(+), 52 deletions(-)
 create mode 100644 src/components/settings_modal/helpers/choice_setting.js
 create mode 100644 src/components/settings_modal/helpers/choice_setting.vue

diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
new file mode 100644
index 00000000..042e8106
--- /dev/null
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -0,0 +1,34 @@
+import { get, set } from 'lodash'
+import Select from 'src/components/select/select.vue'
+import ModifiedIndicator from './modified_indicator.vue'
+export default {
+  components: {
+    Select,
+    ModifiedIndicator
+  },
+  props: [
+    'path',
+    'disabled',
+    'options'
+  ],
+  computed: {
+    pathDefault () {
+      const [firstSegment, ...rest] = this.path.split('.')
+      return [firstSegment + 'DefaultValue', ...rest].join('.')
+    },
+    state () {
+      return get(this.$parent, this.path)
+    },
+    defaultState () {
+      return get(this.$parent, this.pathDefault)
+    },
+    isChanged () {
+      return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault)
+    }
+  },
+  methods: {
+    update (e) {
+      set(this.$parent, this.path, e)
+    }
+  }
+}
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
new file mode 100644
index 00000000..1a8275b4
--- /dev/null
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -0,0 +1,29 @@
+<template>
+  <label
+    class="ChoiceSetting"
+  >
+    <slot />
+    <Select
+      :value="state"
+      :disabled="disabled"
+      @change="update"
+    >
+      <option
+        v-for="option in options"
+        :key="option.key"
+        :value="option.value"
+      >
+        {{ option.label }}
+        {{ option.value === defaultValue ? $t('settings.instance_default_simple') : '' }}
+      </option>
+    </Select>
+    <ModifiedIndicator :changed="isChanged" />
+  </label>
+</template>
+
+<script src="./choice_setting.js"></script>
+
+<style lang="scss">
+.ChoiceSetting {
+}
+</style>
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 89199d85..4eaf4217 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -1,18 +1,23 @@
 import { filter, trim } from 'lodash'
 import BooleanSetting from '../helpers/boolean_setting.vue'
-import Select from '../../select/select.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
 
 const FilteringTab = {
   data () {
     return {
-      muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n')
+      muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n'),
+      replyVisibilityOptions: ['all', 'following', 'self'].map(mode => ({
+        key: mode,
+        value: mode,
+        label: this.$t(`settings.reply_visibility_${mode}`)
+      }))
     }
   },
   components: {
     BooleanSetting,
-    Select
+    ChoiceSetting
   },
   computed: {
     ...SharedComputedObject(),
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 4023fbe2..fb5fc375 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -36,20 +36,13 @@
           </li>
         </ul>
       </div>
-      <div>
-        {{ $t('settings.replies_in_timeline') }}
-        <Select
+      <ChoiceSetting
           id="replyVisibility"
-          v-model="replyVisibility"
+          path="replyVisibility"
+          :options="replyVisibilityOptions"
         >
-          <option
-            value="all"
-            selected
-          >{{ $t('settings.reply_visibility_all') }}</option>
-          <option value="following">{{ $t('settings.reply_visibility_following') }}</option>
-          <option value="self">{{ $t('settings.reply_visibility_self') }}</option>
-        </Select>
-      </div>
+        {{ $t('settings.replies_in_timeline') }}
+      </ChoiceSetting>
       <div>
         <BooleanSetting path="hidePostStats">
           {{ $t('settings.hide_post_stats') }}
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 03648d0b..07fccf57 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -1,5 +1,5 @@
 import BooleanSetting from '../helpers/boolean_setting.vue'
-import Select from '../../select/select.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
 import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
@@ -15,6 +15,11 @@ library.add(
 const GeneralTab = {
   data () {
     return {
+      subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
+        key: mode,
+        value: mode,
+        label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
+      })),
       loopSilentAvailable:
       // Firefox
       Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
@@ -26,13 +31,20 @@ const GeneralTab = {
   },
   components: {
     BooleanSetting,
-    InterfaceLanguageSwitcher,
-    Select
+    ChoiceSetting,
+    InterfaceLanguageSwitcher
   },
   computed: {
     postFormats () {
       return this.$store.state.instance.postFormats || []
     },
+    postContentOptions () {
+      return this.postFormats.map(format => ({
+        key: format,
+        value: format,
+        label: this.$t(`post_status.content_type["${format}"]`)
+      }))
+    },
     instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
     instanceWallpaperUsed () {
       return this.$store.state.instance.background &&
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index a0413cfa..7fb82c06 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -85,44 +85,22 @@
           </BooleanSetting>
         </li>
         <li>
-          <div>
+          <ChoiceSetting
+            id="subjectLineBehavior"
+            path="subjectLineBehavior"
+            :options="subjectLineOptions"
+          >
             {{ $t('settings.subject_line_behavior') }}
-            <Select
-              id="subjectLineBehavior"
-              v-model="subjectLineBehavior"
-            >
-              <option value="email">
-                {{ $t('settings.subject_line_email') }}
-                {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-              <option value="masto">
-                {{ $t('settings.subject_line_mastodon') }}
-                {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-              <option value="noop">
-                {{ $t('settings.subject_line_noop') }}
-                {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-            </Select>
-          </div>
+          </ChoiceSetting>
         </li>
         <li v-if="postFormats.length > 0">
-          <div>
+          <ChoiceSetting
+            id="postContentType"
+            path="postContentType"
+            :options="postContentOptions"
+          >
             {{ $t('settings.post_status_content_type') }}
-            <Select
-              id="postContentType"
-              v-model="postContentType"
-            >
-              <option
-                v-for="postFormat in postFormats"
-                :key="postFormat"
-                :value="postFormat"
-              >
-                {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
-              </option>
-            </Select>
-          </div>
+          </ChoiceSetting>
         </li>
         <li>
           <BooleanSetting path="minimalScopesMode">

From 8e88d8110b0e52023c7f78777bda1951a1bc8d8b Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 17:00:58 +0200
Subject: [PATCH 5/9] fix for filtering tab

---
 .../settings_modal/settings_modal_content.scss      | 13 ++++++++++++-
 .../settings_modal/tabs/filtering_tab.vue           |  9 ---------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/components/settings_modal/settings_modal_content.scss b/src/components/settings_modal/settings_modal_content.scss
index f066234c..81ab434b 100644
--- a/src/components/settings_modal/settings_modal_content.scss
+++ b/src/components/settings_modal/settings_modal_content.scss
@@ -7,13 +7,24 @@
     margin: 1em 1em 1.4em;
     padding-bottom: 1.4em;
 
-    > div {
+    > div,
+    > label {
+      display: block;
       margin-bottom: .5em;
       &:last-child {
         margin-bottom: 0;
       }
     }
 
+    .select-multiple {
+      display: flex;
+
+      .option-list {
+        margin: 0;
+        padding-left: .5em;
+      }
+    }
+
     &:last-child {
       border-bottom: none;
       padding-bottom: 0;
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index fb5fc375..dbd8d9af 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -72,12 +72,3 @@
   </div>
 </template>
 <script src="./filtering_tab.js"></script>
-<style lang="scss">
-.select-multiple {
-  display: flex;
-  .option-list {
-    margin: 0;
-    padding-left: .5em;
-  }
-}
-</style>

From 2da37f15ab6a7e0c6088a6e5a0b2c2885f1cb85a Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 17:04:31 +0200
Subject: [PATCH 6/9] Cleanup boolean/choice setting

---
 .../helpers/boolean_setting.vue               | 38 +------------------
 .../settings_modal/helpers/choice_setting.vue |  2 +-
 2 files changed, 2 insertions(+), 38 deletions(-)

diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 146ad6c1..c3ee6583 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -18,40 +18,4 @@
   </label>
 </template>
 
-<script>
-import { get, set } from 'lodash'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-import ModifiedIndicator from './modified_indicator.vue'
-export default {
-  components: {
-    Checkbox,
-    ModifiedIndicator
-  },
-  props: [
-    'path',
-    'disabled'
-  ],
-  computed: {
-    pathDefault () {
-      const [firstSegment, ...rest] = this.path.split('.')
-      return [firstSegment + 'DefaultValue', ...rest].join('.')
-    },
-    state () {
-      return get(this.$parent, this.path)
-    },
-    isChanged () {
-      return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault)
-    }
-  },
-  methods: {
-    update (e) {
-      set(this.$parent, this.path, e)
-    }
-  }
-}
-</script>
-
-<style lang="scss">
-.BooleanSetting {
-}
-</style>
+<script src="./boolean_setting.js"></script>
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 1a8275b4..fa17661b 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -14,7 +14,7 @@
         :value="option.value"
       >
         {{ option.label }}
-        {{ option.value === defaultValue ? $t('settings.instance_default_simple') : '' }}
+        {{ option.value === defaultState ? $t('settings.instance_default_simple') : '' }}
       </option>
     </Select>
     <ModifiedIndicator :changed="isChanged" />

From 0c77a3e1d6956c14b68078ff766c5ccfb6b086a4 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 7 Apr 2021 20:47:59 +0300
Subject: [PATCH 7/9] remove extra chevron post-merge

---
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index 570cd11b..548dc852 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -72,10 +72,6 @@
                   {{ style[0] || style.name }}
                 </option>
               </Select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
             </label>
           </div>
           <div class="export-import">

From 1afda1ac6d037e477e500870fe4e05c3c1f773cb Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 7 Apr 2021 20:53:58 +0300
Subject: [PATCH 8/9] lost file

---
 .../settings_modal/helpers/boolean_setting.js | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 src/components/settings_modal/helpers/boolean_setting.js

diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
new file mode 100644
index 00000000..1dda49f2
--- /dev/null
+++ b/src/components/settings_modal/helpers/boolean_setting.js
@@ -0,0 +1,30 @@
+import { get, set } from 'lodash'
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import ModifiedIndicator from './modified_indicator.vue'
+export default {
+  components: {
+    Checkbox,
+    ModifiedIndicator
+  },
+  props: [
+    'path',
+    'disabled'
+  ],
+  computed: {
+    pathDefault () {
+      const [firstSegment, ...rest] = this.path.split('.')
+      return [firstSegment + 'DefaultValue', ...rest].join('.')
+    },
+    state () {
+      return get(this.$parent, this.path)
+    },
+    isChanged () {
+      return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault)
+    }
+  },
+  methods: {
+    update (e) {
+      set(this.$parent, this.path, e)
+    }
+  }
+}

From c03965646027bc8ce2d4c083ea3fd0423233fa18 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 31 May 2021 14:02:36 +0300
Subject: [PATCH 9/9] fix warnings

---
 src/components/poll/poll_form.vue                | 10 +++++++---
 .../settings_modal/tabs/filtering_tab.vue        |  8 ++++----
 src/components/user_card/user_card.vue           | 16 ++++++++++++----
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/components/poll/poll_form.vue b/src/components/poll/poll_form.vue
index ecbfdf41..3620075a 100644
--- a/src/components/poll/poll_form.vue
+++ b/src/components/poll/poll_form.vue
@@ -47,13 +47,17 @@
         :title="$t('polls.type')"
       >
         <Select
+          v-model="pollType"
           class="poll-type-select"
           unstyled="true"
-          v-model="pollType"
           @change="updatePollToParent"
         >
-          <option value="single">{{ $t('polls.single_choice') }}</option>
-          <option value="multiple">{{ $t('polls.multiple_choices') }}</option>
+          <option value="single">
+            {{ $t('polls.single_choice') }}
+          </option>
+          <option value="multiple">
+            {{ $t('polls.multiple_choices') }}
+          </option>
         </Select>
       </div>
       <div
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index dbd8d9af..6fc9ceaa 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -37,10 +37,10 @@
         </ul>
       </div>
       <ChoiceSetting
-          id="replyVisibility"
-          path="replyVisibility"
-          :options="replyVisibilityOptions"
-        >
+        id="replyVisibility"
+        path="replyVisibility"
+        :options="replyVisibilityOptions"
+      >
         {{ $t('settings.replies_in_timeline') }}
       </ChoiceSetting>
       <div>
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 75c08f47..53b55c01 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -137,10 +137,18 @@
               v-model="userHighlightType"
               class="userHighlightSel"
             >
-              <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option>
-              <option value="solid">{{ $t('user_card.highlight.solid') }}</option>
-              <option value="striped">{{ $t('user_card.highlight.striped') }}</option>
-              <option value="side">{{ $t('user_card.highlight.side') }}</option>
+              <option value="disabled">
+                {{ $t('user_card.highlight.disabled') }}
+              </option>
+              <option value="solid">
+                {{ $t('user_card.highlight.solid') }}
+              </option>
+              <option value="striped">
+                {{ $t('user_card.highlight.striped') }}
+              </option>
+              <option value="side">
+                {{ $t('user_card.highlight.side') }}
+              </option>
             </Select>
           </div>
         </div>