diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
index 0edbba1e9..3ada6e408 100644
--- a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
+++ b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
@@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "lang/lang_keys.h"
 #include "main/main_session.h"
 #include "settings/settings_common.h"
+#include "ui/chat/chats_filter_tag.h"
 #include "ui/effects/animation_value_f.h"
 #include "ui/effects/animations.h"
 #include "ui/effects/panel_animation.h"
@@ -544,31 +545,18 @@ void EditFilterBox(
 				colors->width(),
 				h);
 		}, preview->lifetime());
-		const auto previewColor = preview->lifetime().make_state<QColor>();
+		const auto previewTag = preview->lifetime().make_state<QImage>();
 		const auto previewAlpha = preview->lifetime().make_state<float64>(1);
 		preview->paintRequest() | rpl::start_with_next([=] {
 			auto p = QPainter(preview);
-			p.fillRect(preview->rect(), Qt::transparent);
-			const auto &font = st::dialogRowFilterTagFont;
-			const auto text = name->getLastText().toUpper();
-			p.setFont(font);
 			p.setOpacity(*previewAlpha);
-			const auto roundedWidth = font->width(text) + font->spacew * 3;
+			const auto size = previewTag->size() / style::DevicePixelRatio();
 			const auto rect = QRect(
-				preview->width() - roundedWidth - st::boxRowPadding.right(),
-				(st::normalFont->height - font->height) / 2,
-				roundedWidth,
-				font->height);
-			const auto pen = QPen(*previewColor);
-			p.setPen(Qt::NoPen);
-			p.setBrush(anim::with_alpha(pen.color(), .15));
-			{
-				auto hq = PainterHighQualityEnabler(p);
-				const auto radius = font->height / 3.;
-				p.drawRoundedRect(rect, radius, radius);
-			}
-			p.setPen(pen);
-			p.drawText(rect, text, style::al_center);
+				preview->width() - size.width() - st::boxRowPadding.right(),
+				(st::normalFont->height - size.height()) / 2,
+				size.width(),
+				size.height());
+			p.drawImage(rect.topLeft(), *previewTag);
 			if (p.opacity() < 1) {
 				p.setOpacity(1. - p.opacity());
 				p.setFont(st::normalFont);
@@ -580,10 +568,6 @@ void EditFilterBox(
 			}
 		}, preview->lifetime());
 
-		name->changes() | rpl::start_with_next([=] {
-			preview->update();
-		}, preview->lifetime());
-
 		const auto side = st::userpicBuilderEmojiAccentColorSize;
 		const auto line = colors->add(
 			Ui::CreateSkipWidget(colors, side),
@@ -594,6 +578,13 @@ void EditFilterBox(
 		const auto palette = [](int i) {
 			return Ui::EmptyUserpic::UserpicColor(i).color2;
 		};
+		name->changes() | rpl::start_with_next([=] {
+			*previewTag = Ui::ChatsFilterTag(
+				name->getLastText().toUpper(),
+				palette(state->colorIndex.current())->c,
+				false);
+			preview->update();
+		}, preview->lifetime());
 		for (auto i = 0; i < kColorsCount; ++i) {
 			const auto button = Ui::CreateChild<UserpicBuilder::CircleButton>(
 				line);
@@ -605,7 +596,10 @@ void EditFilterBox(
 			const auto color = palette(i);
 			button->setBrush(color);
 			if (progress == 1) {
-				*previewColor = color->c;
+				*previewTag = Ui::ChatsFilterTag(
+					name->getLastText().toUpper(),
+					color->c,
+					false);
 				if (i == kNoTag) {
 					*previewAlpha = 0.;
 				}
@@ -628,7 +622,10 @@ void EditFilterBox(
 							buttons[was]->setSelectedProgress(1. - progress);
 						}
 						buttons[now]->setSelectedProgress(progress);
-						*previewColor = anim::color(c1, c2, progress);
+						*previewTag = Ui::ChatsFilterTag(
+							name->getLastText().toUpper(),
+							anim::color(c1, c2, progress),
+							false);
 						*previewAlpha = anim::interpolateF(a1, a2, progress);
 						preview->update();
 					}, 0., 1., st::universalDuration);
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
index d5572a026..6fa18f356 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
@@ -63,6 +63,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "window/window_controller.h"
 #include "window/window_session_controller.h"
 #include "window/window_peer_menu.h"
+#include "ui/chat/chats_filter_tag.h"
 #include "ui/effects/ripple_animation.h"
 #include "ui/effects/loading_element.h"
 #include "ui/widgets/multi_select.h"
@@ -315,6 +316,9 @@ InnerWidget::InnerWidget(
 		session().settings().archiveCollapsedChanges() | rpl::map_to(false),
 		session().data().chatsFilters().changed() | rpl::map_to(true)
 	) | rpl::start_with_next([=](bool refreshHeight) {
+		if (refreshHeight) {
+			_chatsFilterTags.clear();
+		}
 		if (refreshHeight && _filterId) {
 			// Height of the main list will be refreshed in other way.
 			_shownList->updateHeights(_narrowRatio);
@@ -4274,34 +4278,12 @@ QImage *InnerWidget::cacheChatsFilterTag(
 	if (roundedText.isEmpty() || colorIndex < 0) {
 		return nullptr;
 	}
-	const auto &roundedFont = st::dialogRowFilterTagFont;
-	const auto roundedWidth = roundedFont->width(roundedText)
-		+ roundedFont->spacew * 3;
-	const auto rect = QRect(0, 0, roundedWidth, roundedFont->height);
-	auto cache = QImage(
-		rect.size() * style::DevicePixelRatio(),
-		QImage::Format_ARGB32_Premultiplied);
-	cache.setDevicePixelRatio(style::DevicePixelRatio());
-	cache.fill(Qt::transparent);
-	{
-		auto p = QPainter(&cache);
-		const auto pen = QPen(active
-			? st::dialogsBgActive
-			: Ui::EmptyUserpic::UserpicColor(colorIndex).color2);
-		p.setPen(Qt::NoPen);
-		p.setBrush(active
-			? st::dialogsTextFgActive->c
-			: anim::with_alpha(pen.color(), .15));
-		{
-			auto hq = PainterHighQualityEnabler(p);
-			const auto radius = roundedFont->height / 3.;
-			p.drawRoundedRect(rect, radius, radius);
-		}
-		p.setPen(pen);
-		p.setFont(roundedFont);
-		p.drawText(rect, roundedText, style::al_center);
-	}
-	return &_chatsFilterTags.emplace(key, std::move(cache)).first->second;
+	return &_chatsFilterTags.emplace(
+		key,
+		Ui::ChatsFilterTag(
+			std::move(roundedText),
+			Ui::EmptyUserpic::UserpicColor(colorIndex).color2->c,
+			active)).first->second;
 }
 
 bool InnerWidget::chooseHashtag() {
diff --git a/Telegram/SourceFiles/ui/chat/chats_filter_tag.cpp b/Telegram/SourceFiles/ui/chat/chats_filter_tag.cpp
new file mode 100644
index 000000000..3e799aa02
--- /dev/null
+++ b/Telegram/SourceFiles/ui/chat/chats_filter_tag.cpp
@@ -0,0 +1,91 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#include "ui/chat/chats_filter_tag.h"
+
+#include "ui/emoji_config.h"
+#include "ui/painter.h"
+#include "styles/style_dialogs.h"
+
+namespace Ui {
+
+QImage ChatsFilterTag(QString roundedText, QColor color, bool active) {
+	const auto &roundedFont = st::dialogRowFilterTagFont;
+	const auto additionalWidth = roundedFont->spacew * 3;
+	struct EmojiReplacement final {
+		QPixmap pixmap;
+		int from = -1;
+		int length = 0;
+		float64 x = -1;
+	};
+	auto emojiReplacements = std::vector<EmojiReplacement>();
+	auto ch = roundedText.constData();
+	const auto end = ch + roundedText.size();
+	while (ch != end) {
+		auto emojiLength = 0;
+		if (const auto emoji = Ui::Emoji::Find(ch, end, &emojiLength)) {
+			const auto factor = style::DevicePixelRatio();
+			emojiReplacements.emplace_back(
+				Ui::Emoji::SinglePixmap(
+					emoji,
+					st::normalFont->height * factor).scaledToHeight(
+						roundedFont->ascent * factor,
+						Qt::SmoothTransformation),
+				ch - roundedText.constData(),
+				emojiLength);
+			ch += emojiLength;
+		} else {
+			ch++;
+		}
+	}
+	if (!emojiReplacements.empty()) {
+		auto addedChars = 0;
+		for (auto &e : emojiReplacements) {
+			const auto pixmapWidth = e.pixmap.width()
+				/ style::DevicePixelRatio();
+			const auto spaces = 1 + pixmapWidth / roundedFont->spacew;
+			const auto placeholder = QString(spaces, ' ');
+			const auto from = e.from + addedChars;
+			e.x = roundedFont->width(roundedText.mid(0, from))
+				+ additionalWidth / 2.
+				+ (roundedFont->width(placeholder) - pixmapWidth) / 2.;
+			roundedText.replace(from, e.length, placeholder);
+			addedChars += spaces - e.length;
+		}
+	}
+	const auto roundedWidth = roundedFont->width(roundedText)
+		+ additionalWidth;
+	const auto rect = QRect(0, 0, roundedWidth, roundedFont->height);
+	auto cache = QImage(
+		rect.size() * style::DevicePixelRatio(),
+		QImage::Format_ARGB32_Premultiplied);
+	cache.setDevicePixelRatio(style::DevicePixelRatio());
+	cache.fill(Qt::transparent);
+	{
+		auto p = QPainter(&cache);
+		const auto pen = QPen(active ? st::dialogsBgActive->c : color);
+		p.setPen(Qt::NoPen);
+		p.setBrush(active
+			? st::dialogsTextFgActive->c
+			: anim::with_alpha(pen.color(), .15));
+		{
+			auto hq = PainterHighQualityEnabler(p);
+			const auto radius = roundedFont->height / 3.;
+			p.drawRoundedRect(rect, radius, radius);
+		}
+		p.setPen(pen);
+		p.setFont(roundedFont);
+		p.drawText(rect, roundedText, style::al_center);
+		for (const auto &e : emojiReplacements) {
+			const auto h = e.pixmap.height() / style::DevicePixelRatio();
+			p.drawPixmap(QPointF(e.x, (rect.height() - h) / 2), e.pixmap);
+		}
+	}
+	return cache;
+}
+
+} // namespace Ui
diff --git a/Telegram/SourceFiles/ui/chat/chats_filter_tag.h b/Telegram/SourceFiles/ui/chat/chats_filter_tag.h
new file mode 100644
index 000000000..aa07bf4c5
--- /dev/null
+++ b/Telegram/SourceFiles/ui/chat/chats_filter_tag.h
@@ -0,0 +1,14 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#pragma once
+
+namespace Ui {
+
+[[nodiscard]] QImage ChatsFilterTag(QString text, QColor color, bool active);
+
+} // namespace Ui
diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake
index fa35b57d9..5b281f1cf 100644
--- a/Telegram/cmake/td_ui.cmake
+++ b/Telegram/cmake/td_ui.cmake
@@ -334,6 +334,8 @@ PRIVATE
     ui/chat/chat_style_radius.h
     ui/chat/chat_theme.cpp
     ui/chat/chat_theme.h
+    ui/chat/chats_filter_tag.cpp
+    ui/chat/chats_filter_tag.h
     ui/chat/continuous_scroll.cpp
     ui/chat/continuous_scroll.h
     ui/chat/forward_options_box.cpp