diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp
index eefa4047a208ba862c05a8030d7dec30ee7ad529..c31638b0bf2e1fb98e3a9d18c1c6341187c56ad5 100644
--- a/indra/llui/llemojidictionary.cpp
+++ b/indra/llui/llemojidictionary.cpp
@@ -175,17 +175,26 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const
 	return result;
 }
 
-std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch)
+const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const
+{
+	const auto it = mShortCode2Descr.find(short_code);
+	return (mShortCode2Descr.end() != it) ? &it->second : nullptr;
+}
+
+std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) const
 {
 	const auto it = mEmoji2Descr.find(ch);
-	return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null;
+	return (mEmoji2Descr.end() != it) ? it->second.Name : LLStringUtil::null;
 }
 
 void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr)
 {
 	mEmojis.push_back(descr);
-	const LLEmojiDescriptor& back = mEmojis.back();
-	mEmoji2Descr.insert(std::make_pair(descr.Character, &back));
+	mEmoji2Descr.insert(std::make_pair(descr.Character, mEmojis.back()));
+	for (const std::string& shortCode : descr.ShortCodes)
+	{
+		mShortCode2Descr.insert(std::make_pair(shortCode, mEmojis.back()));
+	}
 }
 
 // ============================================================================
diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h
index 3fa55cd417264b5a70dcdf93c145506d099b7c34..0cde66371963cb988984cb2dce1baa55544f4433 100644
--- a/indra/llui/llemojidictionary.h
+++ b/indra/llui/llemojidictionary.h
@@ -58,14 +58,16 @@ class LLEmojiDictionary : public LLParamSingleton<LLEmojiDictionary>, public LLI
 public:
 	static void initClass();
 	LLWString   findMatchingEmojis(const std::string& needle) const;
-	std::string getNameFromEmoji(llwchar ch);
+	const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
+	std::string getNameFromEmoji(llwchar ch) const;
 
 private:
 	void addEmoji(LLEmojiDescriptor&& descr);
 
 private:
 	std::list<LLEmojiDescriptor> mEmojis;
-	std::map<llwchar, const LLEmojiDescriptor*> mEmoji2Descr;
+	std::map<llwchar, const LLEmojiDescriptor&> mEmoji2Descr;
+	std::map<std::string, const LLEmojiDescriptor&> mShortCode2Descr;
 };
 
 // ============================================================================
diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp
index 551f0331e791f006fc6835d4fc637a8367199bdf..32471e59a843704db7110cbd41b93f8aa39d6381 100644
--- a/indra/llui/llemojihelper.cpp
+++ b/indra/llui/llemojihelper.cpp
@@ -83,6 +83,14 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S
 
 void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> cb)
 {
+	// Commit immediately if the user already typed a full shortcode
+	if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code))
+	{
+		cb(LLWString(1, emojiDescrp->Character));
+		hideHelper();
+		return;
+	}
+
 	if (mHelperHandle.isDead())
 	{
 		LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER);
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 693dcb7b8da6425cb2fcc43c510d7becd062c351..b88c7ced40a5ef22e864b9c918992961585d0822 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -29,6 +29,7 @@
 
 #include "lltextbase.h"
 
+#include "llemojihelper.h"
 #include "lllocalcliprect.h"
 #include "llmenugl.h"
 #include "llscrollcontainer.h"