diff --git a/src/client/components/emoji-picker-dialog.vue b/src/client/components/emoji-picker-dialog.vue
new file mode 100644
index 0000000000..177b5db44d
--- /dev/null
+++ b/src/client/components/emoji-picker-dialog.vue
@@ -0,0 +1,191 @@
+<template>
+<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
+	<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen"/>
+</MkModal>
+</template>
+
+<script lang="ts">
+import { defineComponent, markRaw } from 'vue';
+import MkModal from '@/components/ui/modal.vue';
+import MkEmojiPicker from '@/components/emoji-picker.vue';
+
+export default defineComponent({
+	components: {
+		MkModal,
+		MkEmojiPicker,
+	},
+
+	props: {
+		src: {
+			required: false
+		},
+		showPinned: {
+			required: false,
+			default: true
+		},
+		asReactionPicker: {
+			required: false
+		},
+	},
+
+	emits: ['done', 'closed'],
+
+	data() {
+		return {
+
+		};
+	},
+
+	methods: {
+		chosen(emoji: any) {
+			this.$emit('done', emoji);
+			this.$refs.modal.close();
+		},
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.omfetrab {
+	$pad: 8px;
+	--eachSize: 40px;
+
+	display: flex;
+	flex-direction: column;
+	contain: content;
+
+	&.big {
+		--eachSize: 44px;
+	}
+
+	&.w1 {
+		width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
+	}
+
+	&.w2 {
+		width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
+	}
+
+	&.w3 {
+		width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
+	}
+
+	&.h1 {
+		--height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
+	}
+
+	&.h2 {
+		--height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
+	}
+
+	&.h3 {
+		--height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
+	}
+
+	> .search {
+		width: 100%;
+		padding: 12px;
+		box-sizing: border-box;
+		font-size: 1em;
+		outline: none;
+		border: none;
+		background: transparent;
+		color: var(--fg);
+
+		&:not(.filled) {
+			order: 1;
+			z-index: 2;
+			box-shadow: 0px -1px 0 0px var(--divider);
+		}
+	}
+
+	> .emojis {
+		height: var(--height);
+		overflow-y: auto;
+		overflow-x: hidden;
+
+		scrollbar-width: none;
+
+		&::-webkit-scrollbar {
+			display: none;
+		}
+
+		> .index {
+			min-height: var(--height);
+			position: relative;
+			border-bottom: solid 1px var(--divider);
+				
+			> .arrow {
+				position: absolute;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				padding: 16px 0;
+				text-align: center;
+				opacity: 0.5;
+				pointer-events: none;
+			}
+		}
+
+		section {
+			> header {
+				position: sticky;
+				top: 0;
+				left: 0;
+				z-index: 1;
+				padding: 8px;
+				font-size: 12px;
+			}
+
+			> div {
+				padding: $pad;
+
+				> button {
+					position: relative;
+					padding: 0;
+					width: var(--eachSize);
+					height: var(--eachSize);
+					border-radius: 4px;
+
+					&:focus {
+						outline: solid 2px var(--focus);
+						z-index: 1;
+					}
+
+					&:hover {
+						background: rgba(0, 0, 0, 0.05);
+					}
+
+					&:active {
+						background: var(--accent);
+						box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
+					}
+
+					> * {
+						font-size: 24px;
+						height: 1.25em;
+						vertical-align: -.25em;
+						pointer-events: none;
+					}
+				}
+			}
+
+			&.result {
+				border-bottom: solid 1px var(--divider);
+
+				&:empty {
+					display: none;
+				}
+			}
+
+			&.unicode {
+				min-height: 384px;
+			}
+
+			&.custom {
+				min-height: 64px;
+			}
+		}
+	}
+}
+</style>
diff --git a/src/client/components/emoji-picker-window.vue b/src/client/components/emoji-picker-window.vue
new file mode 100644
index 0000000000..fb6a5a9072
--- /dev/null
+++ b/src/client/components/emoji-picker-window.vue
@@ -0,0 +1,197 @@
+<template>
+<MkWindow ref="window"
+	:initial-width="null"
+	:initial-height="null"
+	:can-resize="false"
+	:mini="true"
+	:front="true"
+	@closed="$emit('closed')"
+>
+	<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen"/>
+</MkWindow>
+</template>
+
+<script lang="ts">
+import { defineComponent, markRaw } from 'vue';
+import MkWindow from '@/components/ui/window.vue';
+import MkEmojiPicker from '@/components/emoji-picker.vue';
+
+export default defineComponent({
+	components: {
+		MkWindow,
+		MkEmojiPicker,
+	},
+
+	props: {
+		src: {
+			required: false
+		},
+		showPinned: {
+			required: false,
+			default: true
+		},
+		asReactionPicker: {
+			required: false
+		},
+	},
+
+	emits: ['chosen', 'closed'],
+
+	data() {
+		return {
+
+		};
+	},
+
+	methods: {
+		chosen(emoji: any) {
+			this.$emit('chosen', emoji);
+		},
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.omfetrab {
+	$pad: 8px;
+	--eachSize: 40px;
+
+	display: flex;
+	flex-direction: column;
+	contain: content;
+
+	&.big {
+		--eachSize: 44px;
+	}
+
+	&.w1 {
+		width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
+	}
+
+	&.w2 {
+		width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
+	}
+
+	&.w3 {
+		width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
+	}
+
+	&.h1 {
+		--height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
+	}
+
+	&.h2 {
+		--height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
+	}
+
+	&.h3 {
+		--height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
+	}
+
+	> .search {
+		width: 100%;
+		padding: 12px;
+		box-sizing: border-box;
+		font-size: 1em;
+		outline: none;
+		border: none;
+		background: transparent;
+		color: var(--fg);
+
+		&:not(.filled) {
+			order: 1;
+			z-index: 2;
+			box-shadow: 0px -1px 0 0px var(--divider);
+		}
+	}
+
+	> .emojis {
+		height: var(--height);
+		overflow-y: auto;
+		overflow-x: hidden;
+
+		scrollbar-width: none;
+
+		&::-webkit-scrollbar {
+			display: none;
+		}
+
+		> .index {
+			min-height: var(--height);
+			position: relative;
+			border-bottom: solid 1px var(--divider);
+				
+			> .arrow {
+				position: absolute;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				padding: 16px 0;
+				text-align: center;
+				opacity: 0.5;
+				pointer-events: none;
+			}
+		}
+
+		section {
+			> header {
+				position: sticky;
+				top: 0;
+				left: 0;
+				z-index: 1;
+				padding: 8px;
+				font-size: 12px;
+			}
+
+			> div {
+				padding: $pad;
+
+				> button {
+					position: relative;
+					padding: 0;
+					width: var(--eachSize);
+					height: var(--eachSize);
+					border-radius: 4px;
+
+					&:focus {
+						outline: solid 2px var(--focus);
+						z-index: 1;
+					}
+
+					&:hover {
+						background: rgba(0, 0, 0, 0.05);
+					}
+
+					&:active {
+						background: var(--accent);
+						box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
+					}
+
+					> * {
+						font-size: 24px;
+						height: 1.25em;
+						vertical-align: -.25em;
+						pointer-events: none;
+					}
+				}
+			}
+
+			&.result {
+				border-bottom: solid 1px var(--divider);
+
+				&:empty {
+					display: none;
+				}
+			}
+
+			&.unicode {
+				min-height: 384px;
+			}
+
+			&.custom {
+				min-height: 64px;
+			}
+		}
+	}
+}
+</style>
diff --git a/src/client/components/emoji-picker.vue b/src/client/components/emoji-picker.vue
index 9a261ef83f..93530e16c8 100644
--- a/src/client/components/emoji-picker.vue
+++ b/src/client/components/emoji-picker.vue
@@ -1,93 +1,91 @@
 <template>
-<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
-	<div class="omfetrab _popup" :class="['w' + width, 'h' + height, { big }]">
-		<input ref="search" class="search" :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
-		<div class="emojis" ref="emojis">
-			<section class="result">
-				<div v-if="searchResultCustom.length > 0">
-					<button v-for="emoji in searchResultCustom"
+<div class="omfetrab _popup" :class="['w' + width, 'h' + height, { big }]">
+	<input ref="search" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
+	<div class="emojis" ref="emojis">
+		<section class="result">
+			<div v-if="searchResultCustom.length > 0">
+				<button v-for="emoji in searchResultCustom"
+					class="_button"
+					:title="emoji.name"
+					@click="chosen(emoji, $event)"
+					:key="emoji"
+					tabindex="0"
+				>
+					<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>
+					<img v-else :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
+				</button>
+			</div>
+			<div v-if="searchResultUnicode.length > 0">
+				<button v-for="emoji in searchResultUnicode"
+					class="_button"
+					:title="emoji.name"
+					@click="chosen(emoji, $event)"
+					:key="emoji.name"
+					tabindex="0"
+				>
+					<MkEmoji :emoji="emoji.char"/>
+				</button>
+			</div>
+		</section>
+
+		<div class="index">
+			<section v-if="showPinned">
+				<div>
+					<button v-for="emoji in pinned"
+						class="_button"
+						@click="chosen(emoji, $event)"
+						tabindex="0"
+					>
+						<MkEmoji :emoji="emoji" :normal="true"/>
+					</button>
+				</div>
+			</section>
+
+			<section>
+				<header class="_acrylic"><Fa :icon="faClock" fixed-width/> {{ $ts.recentUsed }}</header>
+				<div>
+					<button v-for="emoji in $store.state.recentlyUsedEmojis"
 						class="_button"
-						:title="emoji.name"
 						@click="chosen(emoji, $event)"
 						:key="emoji"
-						tabindex="0"
 					>
-						<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>
-						<img v-else :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
-					</button>
-				</div>
-				<div v-if="searchResultUnicode.length > 0">
-					<button v-for="emoji in searchResultUnicode"
-						class="_button"
-						:title="emoji.name"
-						@click="chosen(emoji, $event)"
-						:key="emoji.name"
-						tabindex="0"
-					>
-						<MkEmoji :emoji="emoji.char"/>
+						<MkEmoji :emoji="emoji" :normal="true"/>
 					</button>
 				</div>
 			</section>
 
-			<div class="index">
-				<section v-if="showPinned">
-					<div>
-						<button v-for="emoji in pinned"
-							class="_button"
-							@click="chosen(emoji, $event)"
-							tabindex="0"
-						>
-							<MkEmoji :emoji="emoji" :normal="true"/>
-						</button>
-					</div>
-				</section>
-
-				<section>
-					<header class="_acrylic"><Fa :icon="faClock" fixed-width/> {{ $ts.recentUsed }}</header>
-					<div>
-						<button v-for="emoji in $store.state.recentlyUsedEmojis"
-							class="_button"
-							@click="chosen(emoji, $event)"
-							:key="emoji"
-						>
-							<MkEmoji :emoji="emoji" :normal="true"/>
-						</button>
-					</div>
-				</section>
-
-				<div class="arrow"><Fa :icon="faChevronDown"/></div>
-			</div>
-
-			<section v-for="category in customEmojiCategories" :key="'custom:' + category" class="custom">
-				<header class="_acrylic" v-appear="() => visibleCategories[category] = true">{{ category || $ts.other }}</header>
-				<div v-if="visibleCategories[category]">
-					<button v-for="emoji in customEmojis.filter(e => e.category === category)"
-						class="_button"
-						:title="emoji.name"
-						@click="chosen(emoji, $event)"
-						:key="emoji.name"
-					>
-						<img :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
-					</button>
-				</div>
-			</section>
-
-			<section v-for="category in categories" :key="category.name" class="unicode">
-				<header class="_acrylic" v-appear="() => category.isActive = true"><Fa :icon="category.icon" fixed-width/> {{ category.name }}</header>
-				<div v-if="category.isActive">
-					<button v-for="emoji in emojilist.filter(e => e.category === category.name)"
-						class="_button"
-						:title="emoji.name"
-						@click="chosen(emoji, $event)"
-						:key="emoji.name"
-					>
-						<MkEmoji :emoji="emoji.char"/>
-					</button>
-				</div>
-			</section>
+			<div class="arrow"><Fa :icon="faChevronDown"/></div>
 		</div>
+
+		<section v-for="category in customEmojiCategories" :key="'custom:' + category" class="custom">
+			<header class="_acrylic" v-appear="() => visibleCategories[category] = true">{{ category || $ts.other }}</header>
+			<div v-if="visibleCategories[category]">
+				<button v-for="emoji in customEmojis.filter(e => e.category === category)"
+					class="_button"
+					:title="emoji.name"
+					@click="chosen(emoji, $event)"
+					:key="emoji.name"
+				>
+					<img :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
+				</button>
+			</div>
+		</section>
+
+		<section v-for="category in categories" :key="category.name" class="unicode">
+			<header class="_acrylic" v-appear="() => category.isActive = true"><Fa :icon="category.icon" fixed-width/> {{ category.name }}</header>
+			<div v-if="category.isActive">
+				<button v-for="emoji in emojilist.filter(e => e.category === category.name)"
+					class="_button"
+					:title="emoji.name"
+					@click="chosen(emoji, $event)"
+					:key="emoji.name"
+				>
+					<MkEmoji :emoji="emoji.char"/>
+				</button>
+			</div>
+		</section>
 	</div>
-</MkModal>
+</div>
 </template>
 
 <script lang="ts">
@@ -96,7 +94,6 @@ import { emojilist } from '../../misc/emojilist';
 import { getStaticImageUrl } from '@/scripts/get-static-image-url';
 import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faClock, faUser, faChevronDown } from '@fortawesome/free-solid-svg-icons';
 import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons';
-import MkModal from '@/components/ui/modal.vue';
 import Particle from '@/components/particle.vue';
 import * as os from '@/os';
 import { isDeviceTouch } from '@/scripts/is-device-touch';
@@ -104,14 +101,7 @@ import { isMobile } from '@/scripts/is-mobile';
 import { emojiCategories } from '@/instance';
 
 export default defineComponent({
-	components: {
-		MkModal,
-	},
-
 	props: {
-		src: {
-			required: false
-		},
 		showPinned: {
 			required: false,
 			default: true
@@ -121,7 +111,7 @@ export default defineComponent({
 		},
 	},
 
-	emits: ['done', 'closed'],
+	emits: ['chosen'],
 
 	data() {
 		return {
@@ -345,8 +335,7 @@ export default defineComponent({
 			}
 
 			const key = this.getKey(emoji);
-			this.$emit('done', key);
-			this.$refs.modal.close();
+			this.$emit('chosen', key);
 
 			// 最近使った絵文字更新
 			if (!this.pinned.includes(key)) {
diff --git a/src/client/components/note-detailed.vue b/src/client/components/note-detailed.vue
index 83157f7d59..e1927133ae 100644
--- a/src/client/components/note-detailed.vue
+++ b/src/client/components/note-detailed.vue
@@ -523,7 +523,7 @@ export default defineComponent({
 		react(viaKeyboard = false) {
 			pleaseLogin();
 			this.blur();
-			os.popup(import('@/components/emoji-picker.vue'), {
+			os.popup(import('@/components/emoji-picker-dialog.vue'), {
 				src: this.$refs.reactButton,
 				asReactionPicker: true
 			}, {
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index 377e5991b2..6af0668e2e 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -498,7 +498,7 @@ export default defineComponent({
 		react(viaKeyboard = false) {
 			pleaseLogin();
 			this.blur();
-			os.popup(import('@/components/emoji-picker.vue'), {
+			os.popup(import('@/components/emoji-picker-dialog.vue'), {
 				src: this.$refs.reactButton,
 				asReactionPicker: true
 			}, {
diff --git a/src/client/components/post-form.vue b/src/client/components/post-form.vue
index 7849095ba8..9b5adf9cc1 100644
--- a/src/client/components/post-form.vue
+++ b/src/client/components/post-form.vue
@@ -606,9 +606,7 @@ export default defineComponent({
 		},
 
 		async insertEmoji(ev) {
-			os.pickEmoji(ev.currentTarget || ev.target).then(emoji => {
-				insertTextAtCursor(this.$refs.text, emoji);
-			});
+			os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
 		},
 
 		showActions(ev) {
diff --git a/src/client/components/ui/window.vue b/src/client/components/ui/window.vue
index d8852b9ffd..4d3b048c11 100644
--- a/src/client/components/ui/window.vue
+++ b/src/client/components/ui/window.vue
@@ -1,8 +1,8 @@
 <template>
 <transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')">
-	<div class="ebkgocck" v-if="showing">
+	<div class="ebkgocck" :class="{ front }" v-if="showing">
 		<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
-			<div class="header" @contextmenu.prevent.stop="onContextmenu">
+			<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu">
 				<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
 				<button v-else class="_button" @click="close()"><Fa :icon="faTimes"/></button>
 
@@ -92,6 +92,16 @@ export default defineComponent({
 			required: false,
 			default: false,
 		},
+		mini: {
+			type: Boolean,
+			required: false,
+			default: false,
+		},
+		front: {
+			type: Boolean,
+			required: false,
+			default: false,
+		},
 		contextmenu: {
 			type: Array,
 			required: false,
@@ -387,6 +397,10 @@ export default defineComponent({
 	left: 0;
 	z-index: 5000;
 
+	&.front {
+		z-index: 11000; // front指定の時は、mk-modalのよりも大きくなければならない
+	}
+
 	> .body {
 		overflow: hidden; // overflow: clip; をSafariが対応したら消す
 		overflow: clip;
@@ -397,17 +411,22 @@ export default defineComponent({
     height: 100%;
 
 		> .header {
-			$height: 50px;
+			--height: 50px;
+
+			&.mini {
+				--height: 38px;
+			}
+
 			display: flex;
 			position: relative;
 			z-index: 1;
 			flex-shrink: 0;
 			user-select: none;
-			height: $height;
+			height: var(--height);
 
 			> ::v-deep(button) {
-				height: $height;
-				width: $height;
+				height: var(--height);
+				width: var(--height);
 
 				&:hover {
 					color: var(--fgHighlighted);
@@ -417,7 +436,7 @@ export default defineComponent({
 			> .title {
 				flex: 1;
 				position: relative;
-				line-height: $height;
+				line-height: var(--height);
 				white-space: nowrap;
 				overflow: hidden; // overflow: clip; をSafariが対応したら消す
 				overflow: clip;
diff --git a/src/client/os.ts b/src/client/os.ts
index 59ee3617e1..fe4054e272 100644
--- a/src/client/os.ts
+++ b/src/client/os.ts
@@ -1,5 +1,8 @@
+// TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する
+
 import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
 import { EventEmitter } from 'eventemitter3';
+import insertTextAtCursor from 'insert-text-at-cursor';
 import * as Sentry from '@sentry/browser';
 import Stream from '@/scripts/stream';
 import { apiUrl, debug } from '@/config';
@@ -289,7 +292,7 @@ export async function selectDriveFolder(multiple: boolean) {
 
 export async function pickEmoji(src?: HTMLElement, opts) {
 	return new Promise((resolve, reject) => {
-		popup(import('@/components/emoji-picker.vue'), {
+		popup(import('@/components/emoji-picker-dialog.vue'), {
 			src,
 			...opts
 		}, {
@@ -300,6 +303,63 @@ export async function pickEmoji(src?: HTMLElement, opts) {
 	});
 }
 
+type AwaitType<T> =
+	T extends Promise<infer U> ? U :
+	T extends (...args: Array<any>) => Promise<infer V> ? V :
+	T;
+let openingEmojiPicker: AwaitType<ReturnType<typeof popup>> | null = null;
+let activeTextarea: HTMLTextAreaElement | HTMLInputElement | null = null;
+export async function openEmojiPicker(src?: HTMLElement, opts, initialTextarea: typeof activeTextarea) {
+	if (openingEmojiPicker) return;
+
+	activeTextarea = initialTextarea;
+
+	const textareas = document.querySelectorAll('textarea, input');
+	for (const textarea of Array.from(textareas)) {
+		textarea.addEventListener('focus', () => {
+			activeTextarea = textarea;
+		});
+	}
+
+	const observer = new MutationObserver(records => {
+		for (const record of records) {
+			for (const node of Array.from(record.addedNodes)) {
+				if (node instanceof HTMLElement) {
+					const textareas = node.querySelectorAll('textarea, input');
+					for (const textarea of Array.from(textareas)) {
+						if (textarea.dataset.preventEmojiInsert != null) return;
+						if (document.activeElement === textarea) activeTextarea = textarea;
+						textarea.addEventListener('focus', () => {
+							activeTextarea = textarea;
+						});
+					}
+				}
+			}
+		}
+	});
+
+	observer.observe(document.body, {
+		childList: true,
+		subtree: true,
+		attributes: false,
+		characterData: false,
+	});
+
+	openingEmojiPicker = await popup(import('@/components/emoji-picker-window.vue'), {
+		src,
+		...opts
+	}, {
+		chosen: emoji => {
+			insertTextAtCursor(activeTextarea, emoji);
+		},
+		closed: () => {
+			openingEmojiPicker!.dispose();
+			openingEmojiPicker = null;
+			observer.disconnect();
+		}
+	});
+}
+
 export function modalMenu(items: any[], src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) {
 	return new Promise((resolve, reject) => {
 		let dispose;
diff --git a/src/client/pages/messaging/messaging-room.form.vue b/src/client/pages/messaging/messaging-room.form.vue
index 258300dc52..5e675a3f12 100644
--- a/src/client/pages/messaging/messaging-room.form.vue
+++ b/src/client/pages/messaging/messaging-room.form.vue
@@ -223,9 +223,7 @@ export default defineComponent({
 		},
 
 		async insertEmoji(ev) {
-			os.pickEmoji(ev.currentTarget || ev.target).then(emoji => {
-				insertTextAtCursor(this.$refs.text, emoji);
-			});
+			os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
 		}
 	}
 });
diff --git a/src/client/pages/settings/reaction.vue b/src/client/pages/settings/reaction.vue
index 798ffb33d1..4488e50051 100644
--- a/src/client/pages/settings/reaction.vue
+++ b/src/client/pages/settings/reaction.vue
@@ -105,7 +105,7 @@ export default defineComponent({
 		},
 
 		preview(ev) {
-			os.popup(import('@/components/emoji-picker.vue'), {
+			os.popup(import('@/components/emoji-picker-dialog.vue'), {
 				asReactionPicker: true,
 				src: ev.currentTarget || ev.target,
 			}, {}, 'closed');
diff --git a/src/client/style.scss b/src/client/style.scss
index 3ebb5fabd1..aa2face04e 100644
--- a/src/client/style.scss
+++ b/src/client/style.scss
@@ -391,8 +391,8 @@ hr {
 
 ._acrylic {
 	background: var(--acrylicPanel);
-	-webkit-backdrop-filter: blur(10px);
-	backdrop-filter: blur(10px);
+	-webkit-backdrop-filter: blur(15px);
+	backdrop-filter: blur(15px);
 }
 
 ._vMargin {
diff --git a/src/client/ui/chat/note.vue b/src/client/ui/chat/note.vue
index 3c5c1acfdc..d80978e182 100644
--- a/src/client/ui/chat/note.vue
+++ b/src/client/ui/chat/note.vue
@@ -504,7 +504,7 @@ export default defineComponent({
 			pleaseLogin();
 			this.operating = true;
 			this.blur();
-			const { dispose } = await os.popup(import('@/components/emoji-picker.vue'), {
+			const { dispose } = await os.popup(import('@/components/emoji-picker-dialog.vue'), {
 				src: this.$refs.reactButton,
 				asReactionPicker: true
 			}, {
diff --git a/src/client/ui/chat/post-form.vue b/src/client/ui/chat/post-form.vue
index b0a31b097d..9388989d5d 100644
--- a/src/client/ui/chat/post-form.vue
+++ b/src/client/ui/chat/post-form.vue
@@ -593,9 +593,7 @@ export default defineComponent({
 		},
 
 		async insertEmoji(ev) {
-			os.pickEmoji(ev.currentTarget || ev.target).then(emoji => {
-				insertTextAtCursor(this.$refs.text, emoji);
-			});
+			os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
 		},
 
 		showActions(ev) {