diff --git a/app/assets/javascripts/admin/addon/components/emoji-value-list.js b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
new file mode 100644
index 00000000000..e7096a71dad
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
@@ -0,0 +1,168 @@
+import Component from "@ember/component";
+import I18n from "I18n";
+import discourseComputed from "discourse-common/utils/decorators";
+import { emojiUrlFor } from "discourse/lib/text";
+import { action, set, setProperties } from "@ember/object";
+import { later, schedule } from "@ember/runloop";
+
+export default Component.extend({
+  classNameBindings: [":value-list", ":emoji-list"],
+  values: null,
+  validationMessage: null,
+  emojiPickerIsActive: false,
+  isEditorFocused: false,
+
+  @discourseComputed("values")
+  collection(values) {
+    values = values || "";
+
+    return values
+      .split("|")
+      .filter(Boolean)
+      .map((value) => {
+        return {
+          isEditable: true,
+          isEditing: false,
+          value,
+          emojiUrl: emojiUrlFor(value),
+        };
+      });
+  },
+
+  @action
+  closeEmojiPicker() {
+    this.collection.setEach("isEditing", false);
+    this.set("emojiPickerIsActive", false);
+    this.set("isEditorFocused", false);
+  },
+
+  @action
+  emojiSelected(code) {
+    if (!this._validateInput(code)) {
+      return;
+    }
+
+    const item = this.collection.findBy("isEditing");
+    if (item) {
+      setProperties(item, {
+        value: code,
+        emojiUrl: emojiUrlFor(code),
+        isEditing: false,
+      });
+
+      this._saveValues();
+    } else {
+      const newCollectionValue = {
+        value: code,
+        emojiUrl: emojiUrlFor(code),
+        isEditable: true,
+        isEditing: false,
+      };
+      this.collection.addObject(newCollectionValue);
+      this._saveValues();
+    }
+
+    this.set("emojiPickerIsActive", false);
+    this.set("isEditorFocused", false);
+  },
+
+  @discourseComputed("collection")
+  showUpDownButtons(collection) {
+    return collection.length - 1 ? true : false;
+  },
+
+  _splitValues(values) {
+    if (values && values.length) {
+      const emojiList = [];
+      const emojis = values.split("|").filter(Boolean);
+      emojis.forEach((emojiName) => {
+        const emoji = {
+          isEditable: true,
+          isEditing: false,
+        };
+        emoji.value = emojiName;
+        emoji.emojiUrl = emojiUrlFor(emojiName);
+
+        emojiList.push(emoji);
+      });
+
+      return emojiList;
+    } else {
+      return [];
+    }
+  },
+
+  @action
+  editValue(index) {
+    this.closeEmojiPicker();
+    schedule("afterRender", () => {
+      if (parseInt(index, 10) >= 0) {
+        const item = this.collection[index];
+        if (item.isEditable) {
+          set(item, "isEditing", true);
+        }
+      }
+
+      this.set("isEditorFocused", true);
+      later(() => {
+        if (this.element && !this.isDestroying && !this.isDestroyed) {
+          this.set("emojiPickerIsActive", true);
+        }
+      }, 100);
+    });
+  },
+
+  @action
+  removeValue(value) {
+    this._removeValue(value);
+  },
+
+  @action
+  shift(operation, index) {
+    let futureIndex = index + operation;
+
+    if (futureIndex > this.collection.length - 1) {
+      futureIndex = 0;
+    } else if (futureIndex < 0) {
+      futureIndex = this.collection.length - 1;
+    }
+
+    const shiftedEmoji = this.collection[index];
+    this.collection.removeAt(index);
+    this.collection.insertAt(futureIndex, shiftedEmoji);
+
+    this._saveValues();
+  },
+
+  _validateInput(input) {
+    this.set("validationMessage", null);
+
+    if (!emojiUrlFor(input)) {
+      this.set(
+        "validationMessage",
+        I18n.t("admin.site_settings.emoji_list.invalid_input")
+      );
+      return false;
+    }
+
+    return true;
+  },
+
+  _removeValue(value) {
+    this.collection.removeObject(value);
+    this._saveValues();
+  },
+
+  _replaceValue(index, newValue) {
+    const item = this.collection[index];
+    if (item.value === newValue) {
+      return;
+    }
+    set(item, "value", newValue);
+    this._saveValues();
+  },
+
+  _saveValues() {
+    this.set("values", this.collection.mapBy("value").join("|"));
+  },
+});
diff --git a/app/assets/javascripts/admin/addon/mixins/setting-component.js b/app/assets/javascripts/admin/addon/mixins/setting-component.js
index d96bd40c22b..fc6c6c24d5f 100644
--- a/app/assets/javascripts/admin/addon/mixins/setting-component.js
+++ b/app/assets/javascripts/admin/addon/mixins/setting-component.js
@@ -27,6 +27,7 @@ const CUSTOM_TYPES = [
   "tag_list",
   "color",
   "simple_list",
+  "emoji_list",
 ];
 
 const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"];
diff --git a/app/assets/javascripts/admin/addon/templates/components/emoji-value-list.hbs b/app/assets/javascripts/admin/addon/templates/components/emoji-value-list.hbs
new file mode 100644
index 00000000000..aeed56f4586
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/templates/components/emoji-value-list.hbs
@@ -0,0 +1,53 @@
+{{#if collection}}
+  <ul class="values emoji-value-list">
+    {{#each collection as |data index|}}
+      <li class="value" data-index={{index}}>
+        {{#if data.isEditable}}
+          {{d-button
+            action=(action "removeValue")
+            actionParam=data
+            icon="times"
+            class="remove-value-btn btn-small"
+          }}
+        {{/if}}
+
+        <div class="value-input emoji-details {{if data.isEditable "can-edit"}} {{if data.isEditing "d-editor-textarea-wrapper"}}" {{on "click" (fn this.editValue index)}} role="button">
+          <img height="15px" width="15px" src={{data.emojiUrl}} class="emoji-list-emoji">
+          <span class="emoji-name">{{data.value}}</span>
+        </div>
+
+        {{#if showUpDownButtons}}
+          {{d-button
+            action=(action "shift" -1 index)
+            icon="arrow-up"
+            class="shift-up-value-btn btn-small"
+          }}
+          {{d-button
+            action=(action "shift" 1 index)
+            icon="arrow-down"
+            class="shift-down-value-btn btn-small"
+          }}
+        {{/if}}
+      </li>
+    {{/each}}
+  </ul>
+{{/if}}
+
+<div class="value">
+  {{d-button
+    action=(action "editValue")
+    actionParam=data
+    icon="emoji-icon"
+    class="add-emoji-button d-editor-textarea-wrapper"
+    label="admin.site_settings.emoji_list.add_emoji_button.label"
+  }}
+</div>
+
+{{emoji-picker
+  isActive=emojiPickerIsActive
+  isEditorFocused=isEditorFocused
+  emojiSelected=(action "emojiSelected")
+  onEmojiPickerClose=(action "closeEmojiPicker")
+}}
+
+{{setting-validation-message message=validationMessage}}
diff --git a/app/assets/javascripts/admin/addon/templates/components/site-settings/emoji-list.hbs b/app/assets/javascripts/admin/addon/templates/components/site-settings/emoji-list.hbs
new file mode 100644
index 00000000000..50d1d18898b
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/templates/components/site-settings/emoji-list.hbs
@@ -0,0 +1,3 @@
+{{emoji-value-list setting=setting values=value}}
+<div class="desc">{{html-safe setting.description}}</div>
+{{setting-validation-message message=validationMessage}}
diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss
index a65d7ff0add..e920bb76c90 100644
--- a/app/assets/stylesheets/common/admin/admin_base.scss
+++ b/app/assets/stylesheets/common/admin/admin_base.scss
@@ -884,6 +884,47 @@ table#user-badges {
   }
 }
 
+.emoji-value-list {
+  margin-left: 0;
+
+  .emoji-details {
+    display: flex;
+    align-items: center;
+    min-height: 30px;
+    padding: $input-padding;
+    line-height: 1;
+    color: var(--primary);
+    border: 1px solid var(--primary-low);
+
+    .emoji-name {
+      margin-left: 0.5em;
+    }
+
+    &:not(.can-edit) {
+      pointer-events: none;
+      background-color: var(--primary-very-low);
+    }
+  }
+
+  .value-input {
+    flex-direction: row;
+  }
+}
+
+.value .add-emoji-button {
+  display: block;
+  background-color: var(--primary-low);
+  border: none;
+}
+
+.value .add-value-btn,
+.shift-up-value-btn,
+.shift-down-value-btn {
+  @include value-btn;
+  margin-right: 0 !important;
+  margin-left: 0.25em;
+}
+
 .secret-value-list {
   .value {
     flex-flow: row wrap;
diff --git a/app/assets/stylesheets/desktop.scss b/app/assets/stylesheets/desktop.scss
index dfae3eca774..d302363926b 100644
--- a/app/assets/stylesheets/desktop.scss
+++ b/app/assets/stylesheets/desktop.scss
@@ -4,3 +4,6 @@
 
 // Import all component-specific files
 @import "desktop/components/_index";
+
+// Import all admin-specific files
+@import "desktop/admin/_index";
diff --git a/app/assets/stylesheets/desktop/admin/_index.scss b/app/assets/stylesheets/desktop/admin/_index.scss
new file mode 100644
index 00000000000..b45777ec742
--- /dev/null
+++ b/app/assets/stylesheets/desktop/admin/_index.scss
@@ -0,0 +1 @@
+@import "admin_base";
diff --git a/app/assets/stylesheets/desktop/admin/admin_base.scss b/app/assets/stylesheets/desktop/admin/admin_base.scss
new file mode 100644
index 00000000000..c014649b9e0
--- /dev/null
+++ b/app/assets/stylesheets/desktop/admin/admin_base.scss
@@ -0,0 +1,15 @@
+.emoji-value-list {
+  .value {
+    .shift-up-value-btn,
+    .shift-down-value-btn {
+      display: none;
+    }
+
+    &:hover {
+      .shift-up-value-btn,
+      .shift-down-value-btn {
+        display: block;
+      }
+    }
+  }
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 31de720fd34..9201bb510bb 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -5010,6 +5010,10 @@ en:
         reset: "reset"
         none: "none"
       site_settings:
+        emoji_list:
+          invalid_input: "Emoji list should only contain valid emoji names, eg: hugs"
+          add_emoji_button:
+            label: "Add Emoji"
         title: "Settings"
         no_results: "No results found."
         more_than_30_results: "There are more than 30 results. Please refine your search or select a category."
diff --git a/lib/site_settings/type_supervisor.rb b/lib/site_settings/type_supervisor.rb
index f5bb727d356..ee78697ebf2 100644
--- a/lib/site_settings/type_supervisor.rb
+++ b/lib/site_settings/type_supervisor.rb
@@ -35,7 +35,8 @@ class SiteSettings::TypeSupervisor
       group_list: 20,
       tag_list: 21,
       color: 22,
-      simple_list: 23
+      simple_list: 23,
+      emoji_list: 24
     )
   end
 
diff --git a/lib/svg_sprite/svg_sprite.rb b/lib/svg_sprite/svg_sprite.rb
index 61aa7c3df30..9a2d18b9831 100644
--- a/lib/svg_sprite/svg_sprite.rb
+++ b/lib/svg_sprite/svg_sprite.rb
@@ -66,6 +66,7 @@ module SvgSprite
     "download",
     "ellipsis-h",
     "ellipsis-v",
+    "emoji-icon",
     "envelope",
     "envelope-square",
     "exchange-alt",
diff --git a/spec/components/site_settings/type_supervisor_spec.rb b/spec/components/site_settings/type_supervisor_spec.rb
index 86fd7267ed2..36c6f82a197 100644
--- a/spec/components/site_settings/type_supervisor_spec.rb
+++ b/spec/components/site_settings/type_supervisor_spec.rb
@@ -91,6 +91,9 @@ describe SiteSettings::TypeSupervisor do
       it "'simple_list' should be at the right position" do
         expect(SiteSettings::TypeSupervisor.types[:simple_list]).to eq(23)
       end
+      it "'emoji_list' should be at the right position" do
+        expect(SiteSettings::TypeSupervisor.types[:emoji_list]).to eq(24)
+      end
     end
   end
 
diff --git a/vendor/assets/svg-icons/emoji.svg b/vendor/assets/svg-icons/emoji.svg
new file mode 100644
index 00000000000..9b715176936
--- /dev/null
+++ b/vendor/assets/svg-icons/emoji.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
+  <symbol overflow="visible" viewBox="0 0 216.3 152.3" id="emoji-icon">
+    <path d="M121.1 70.7c1.9 2 5.1 2.1 7.2.2l.2-.2 31.2-32.2c9.1-9.4 8.6-24.9-1.6-33.5-8.8-7.5-22-6.2-30.1 2.2l-3.2 3.3-3.2-3.3c-8.1-8.4-21.3-9.7-30.1-2.2-10.1 8.6-10.7 24.2-1.6 33.5l31.2 32.2zM53.5 45.3C23.9 45.3 0 69.2 0 98.8s23.9 53.5 53.5 53.5 53.5-24 53.5-53.5-23.9-53.5-53.5-53.5zm18.8 24.6c5.5 0 9.9 4.4 9.9 9.9s-4.4 9.9-9.9 9.9-9.9-4.4-9.9-9.9c-.1-5.5 4.4-9.9 9.9-9.9zm-38.2 0c5.5 0 9.9 4.4 9.9 9.9s-4.4 9.9-9.9 9.9-9.9-4.4-9.9-9.9 4.4-9.9 9.9-9.9zm52.4 45.4c-8.2 9.8-20.2 15.5-33.1 15.5s-24.9-5.6-33.1-15.5c-3.9-4.7 3.2-10.6 7.1-5.9 6.5 7.7 15.9 12.2 26 12.2s19.5-4.4 26-12.2c3.8-4.7 10.9 1.2 7.1 5.9zm129.8-22.5c0-6.4-6.3-9.5-13.3-9.5h-24c1.5-6 10.3-13.8 10.3-22.8 0-15.5-10.1-17.2-15.2-17.2-4.3 0-6.2 8.3-7.2 12.2-1.1 4.6-2.2 9.3-5.4 12.4-6.7 6.8-10.3 15.3-18.4 23.5-.7-1.8-2.6-3.1-4.7-3.1h-10.7c-2.8 0-5.1 2.2-5.1 4.9V142c0 2.7 2.3 4.9 5.1 4.9h10.7c2.8 0 5.1-2.2 5.1-4.9v-.9c.3.1.6.2.9.2 3.3.1 7.8 1.9 11.1 3.4 6.7 3 15.1 6.7 25.3 6.7h.6c9 0 19.7-.1 24-6.3 1.8-2.5 2.7-4.4.5-9.9 5-3 7-10 1-15 8-5 8-13 1-17 6.1-1.9 8.5-6.6 8.4-10.4z"></path>
+  </symbol>
+</svg>