diff --git a/src/client/components/emoji-picker.vue b/src/client/components/emoji-picker.vue
index 270951962f..5d60f2eb51 100644
--- a/src/client/components/emoji-picker.vue
+++ b/src/client/components/emoji-picker.vue
@@ -1,7 +1,7 @@
 <template>
 <MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
-	<div class="omfetrab _popup">
-		<input ref="search" class="search" v-model.trim="q" :placeholder="$t('search')" @paste.stop="paste" @keyup.enter="done()" autofocus>
+	<div class="omfetrab _popup" :class="{ compact }">
+		<input ref="search" class="search" :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$t('search')" @paste.stop="paste" @keyup.enter="done()">
 		<div class="emojis">
 			<section class="result">
 				<div v-if="searchResultCustom.length > 0">
@@ -43,7 +43,7 @@
 				</section>
 
 				<section>
-					<header class="_acrylic"><Fa :icon="faHistory" fixed-width/> {{ $t('recentUsed') }}</header>
+					<header class="_acrylic"><Fa :icon="faClock" fixed-width/> {{ $t('recentUsed') }}</header>
 					<div>
 						<button v-for="emoji in $store.state.device.recentlyUsedEmojis"
 							class="_button"
@@ -94,7 +94,7 @@
 import { defineComponent, markRaw } from 'vue';
 import { emojilist } from '../../misc/emojilist';
 import { getStaticImageUrl } from '@/scripts/get-static-image-url';
-import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory, faUser, faChevronDown } from '@fortawesome/free-solid-svg-icons';
+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';
@@ -112,6 +112,9 @@ export default defineComponent({
 		overridePinned: {
 			required: false
 		},
+		compact: {
+			required: false
+		},
 	},
 
 	emits: ['done', 'closed'],
@@ -127,7 +130,7 @@ export default defineComponent({
 			q: null,
 			searchResultCustom: [],
 			searchResultUnicode: [],
-			faGlobe, faHistory, faChevronDown,
+			faGlobe, faClock, faChevronDown,
 			categories: [{
 				name: 'face',
 				icon: faLaugh,
@@ -311,9 +314,12 @@ export default defineComponent({
 	},
 
 	mounted() {
-		this.$refs.search.focus({
-			preventScroll: true
-		});
+		const isIos = navigator.userAgent.includes('WebKit') && !navigator.userAgent.includes('Chrome');
+		if (!isIos) {
+			this.$refs.search.focus({
+				preventScroll: true
+			});
+		}
 	},
 
 	methods: {
@@ -379,8 +385,19 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .omfetrab {
-	width: 350px;
+	$eachSize: 40px;
+	$pad: 8px;
+
+	display: flex;
+	flex-direction: column;
+	width: ($eachSize * 7) + ($pad * 2);
 	contain: content;
+	--height: 300px;
+
+	&.compact {
+		width: ($eachSize * 5) + ($pad * 2);
+		--height: 210px;
+	}
 
 	> .search {
 		width: 100%;
@@ -391,17 +408,27 @@ export default defineComponent({
 		border: none;
 		background: transparent;
 		color: var(--fg);
+
+		&:not(.filled) {
+			order: 1;
+			z-index: 2;
+			box-shadow: 0px -1px 0 0px var(--divider);
+		}
 	}
 
 	> .emojis {
-		$height: 300px;
-
-		height: $height;
+		height: var(--height);
 		overflow-y: auto;
 		overflow-x: hidden;
 
+		scrollbar-width: none;
+
+		&::-webkit-scrollbar {
+			display: none;
+		}
+
 		> .index {
-			min-height: $height;
+			min-height: var(--height);
 			position: relative;
 			border-bottom: solid 1px var(--divider);
 				
@@ -428,45 +455,33 @@ export default defineComponent({
 			}
 
 			> div {
-				display: grid;
-				grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
-				gap: 4px;
-				padding: 8px;
+				padding: $pad;
 
 				> button {
 					position: relative;
 					padding: 0;
-					width: 100%;
+					width: $eachSize;
+					height: $eachSize;
+					border-radius: 4px;
 
 					&:focus {
 						outline: solid 2px var(--focus);
 						z-index: 1;
 					}
 
-					&:before {
-						content: '';
-						display: block;
-						width: 1px;
-						height: 0;
-						padding-bottom: 100%;
+					&:hover {
+						background: rgba(0, 0, 0, 0.05);
 					}
 
-					&:hover {
-						> * {
-							transform: scale(1.2);
-							transition: transform 0s;
-						}
+					&:active {
+						background: var(--accent);
+						box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
 					}
 
 					> * {
-						position: absolute;
-						top: 0;
-						left: 0;
-						width: 100%;
-						height: 100%;
-						object-fit: contain;
-						font-size: 28px;
-						transition: transform 0.2s ease;
+						font-size: 24px;
+						height: 1.25em;
+						vertical-align: -.25em;
 						pointer-events: none;
 					}
 				}
@@ -474,6 +489,10 @@ export default defineComponent({
 
 			&.result {
 				border-bottom: solid 1px var(--divider);
+
+				&:empty {
+					display: none;
+				}
 			}
 
 			&.unicode {
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index 53972d9f6f..bf89cbf568 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -498,36 +498,20 @@ export default defineComponent({
 		react(viaKeyboard = false) {
 			pleaseLogin();
 			this.blur();
-			if (this.$store.state.device.useFullReactionPicker) {
-				os.popup(import('@/components/emoji-picker.vue'), {
-					src: this.$refs.reactButton,
-				}, {
-					done: reaction => {
-						if (reaction) {
-							os.api('notes/reactions/create', {
-								noteId: this.appearNote.id,
-								reaction: reaction
-							});
-						}
-						this.focus();
-					},
-				}, 'closed');
-			} else {
-				os.popup(import('@/components/reaction-picker.vue'), {
-					showFocus: viaKeyboard,
-					src: this.$refs.reactButton,
-				}, {
-					done: reaction => {
-						if (reaction) {
-							os.api('notes/reactions/create', {
-								noteId: this.appearNote.id,
-								reaction: reaction
-							});
-						}
-						this.focus();
-					},
-				}, 'closed');
-			}
+			os.popup(import('@/components/emoji-picker.vue'), {
+				src: this.$refs.reactButton,
+				compact: !this.$store.state.device.useFullReactionPicker
+			}, {
+				done: reaction => {
+					if (reaction) {
+						os.api('notes/reactions/create', {
+							noteId: this.appearNote.id,
+							reaction: reaction
+						});
+					}
+					this.focus();
+				},
+			}, 'closed');
 		},
 
 		reactDirectly(reaction) {
diff --git a/src/client/components/reaction-picker.vue b/src/client/components/reaction-picker.vue
deleted file mode 100644
index fca1e858bb..0000000000
--- a/src/client/components/reaction-picker.vue
+++ /dev/null
@@ -1,214 +0,0 @@
-<template>
-<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
-	<div class="rdfaahpb _popup" v-hotkey="keymap">
-		<div class="buttons" ref="buttons" :class="{ showFocus }">
-			<button class="_button" v-for="(reaction, i) in rs" :key="reaction" @click="react(reaction)" :tabindex="i + 1" :title="reaction" v-particle><XReactionIcon :reaction="reaction"/></button>
-		</div>
-		<input class="text" ref="text" v-model.trim="text" :placeholder="$t('enterEmoji')" @keyup.enter="reactText" @input="tryReactText">
-	</div>
-</MkModal>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import { emojiRegex } from '../../misc/emoji-regex';
-import XReactionIcon from '@/components/reaction-icon.vue';
-import MkModal from '@/components/ui/modal.vue';
-import { Autocomplete } from '@/scripts/autocomplete';
-
-export default defineComponent({
-	components: {
-		XReactionIcon,
-		MkModal,
-	},
-
-	props: {
-		reactions: {
-			required: false
-		},
-
-		showFocus: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-
-		src: {
-			required: false
-		},
-	},
-
-	emits: ['done', 'closed'],
-
-	data() {
-		return {
-			rs: this.reactions || this.$store.state.settings.reactions,
-			text: null,
-			focus: null
-		};
-	},
-
-	computed: {
-		keymap(): any {
-			return {
-				'esc': this.close,
-				'enter|space|plus': this.choose,
-				'up|k': this.focusUp,
-				'left|h|shift+tab': this.focusLeft,
-				'right|l|tab': this.focusRight,
-				'down|j': this.focusDown,
-				'1': () => this.react(this.rs[0]),
-				'2': () => this.react(this.rs[1]),
-				'3': () => this.react(this.rs[2]),
-				'4': () => this.react(this.rs[3]),
-				'5': () => this.react(this.rs[4]),
-				'6': () => this.react(this.rs[5]),
-				'7': () => this.react(this.rs[6]),
-				'8': () => this.react(this.rs[7]),
-				'9': () => this.react(this.rs[8]),
-				'0': () => this.react(this.rs[9]),
-			};
-		},
-	},
-
-	watch: {
-		focus(i) {
-			this.$refs.buttons.children[i].focus({
-				preventScroll: true
-			});
-		}
-	},
-
-	mounted() {
-		this.$nextTick(() => {
-			this.focus = 0;
-		});
-
-		// TODO: detach when unmount
-		new Autocomplete(this.$refs.text, this, { model: 'text' });
-	},
-
-	methods: {
-		close() {
-			this.$emit('done');
-			this.$refs.modal.close();
-		},
-	
-		react(reaction) {
-			this.$emit('done', reaction);
-			this.$refs.modal.close();
-		},
-
-		reactText() {
-			if (!this.text) return;
-			this.react(this.text);
-		},
-
-		tryReactText() {
-			if (!this.text) return;
-			if (!this.text.match(emojiRegex)) return;
-			this.reactText();
-		},
-
-		focusUp() {
-			this.focus = this.focus == 0 ? 9 : this.focus < 5 ? (this.focus + 4) : (this.focus - 5);
-		},
-
-		focusDown() {
-			this.focus = this.focus == 9 ? 0 : this.focus >= 5 ? (this.focus - 4) : (this.focus + 5);
-		},
-
-		focusRight() {
-			this.focus = this.focus == 9 ? 0 : (this.focus + 1);
-		},
-
-		focusLeft() {
-			this.focus = this.focus == 0 ? 9 : (this.focus - 1);
-		},
-
-		choose() {
-			this.$refs.buttons.children[this.focus].click();
-		},
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.rdfaahpb {
-	> .buttons {
-		padding: 6px 6px 0 6px;
-		width: 212px;
-		box-sizing: border-box;
-		text-align: center;
-
-		@media (max-width: 1025px) {
-			padding: 8px 8px 0 8px;
-			width: 256px;
-		}
-
-		&.showFocus {
-			> button:focus {
-				position: relative;
-				z-index: 1;
-
-				&:after {
-					content: "";
-					pointer-events: none;
-					position: absolute;
-					top: 0;
-					right: 0;
-					bottom: 0;
-					left: 0;
-					border: 2px solid var(--focus);
-					border-radius: 4px;
-				}
-			}
-		}
-
-		> button {
-			padding: 0;
-			width: 40px;
-			height: 40px;
-			font-size: 24px;
-			border-radius: 2px;
-
-			@media (max-width: 1025px) {
-				width: 48px;
-				height: 48px;
-				font-size: 26px;
-			}
-
-			> * {
-				height: 1em;
-			}
-
-			&: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);
-			}
-		}
-	}
-
-	> .text {
-		width: 208px;
-		padding: 8px;
-		margin: 0 0 6px 0;
-		box-sizing: border-box;
-		text-align: center;
-		font-size: 16px;
-		outline: none;
-		border: none;
-		background: transparent;
-		color: var(--fg);
-
-		@media (max-width: 1025px) {
-			width: 256px;
-			margin: 4px 0 8px 0;
-		}
-	}
-}
-</style>
diff --git a/src/client/pages/settings/reaction.vue b/src/client/pages/settings/reaction.vue
index 8033b7e11d..52b9f3260b 100644
--- a/src/client/pages/settings/reaction.vue
+++ b/src/client/pages/settings/reaction.vue
@@ -80,18 +80,11 @@ export default defineComponent({
 		},
 
 		preview(ev) {
-			if (this.$store.state.device.useFullReactionPicker) {
-				os.popup(import('@/components/emoji-picker.vue'), {
-					overridePinned: this.splited,
-					src: ev.currentTarget || ev.target,
-				}, {}, 'closed');
-			} else {
-				os.popup(import('@/components/reaction-picker.vue'), {
-					reactions: this.splited,
-					showFocus: false,
-					src: ev.currentTarget || ev.target,
-				}, {}, 'closed');
-			}
+			os.popup(import('@/components/emoji-picker.vue'), {
+				overridePinned: this.splited,
+				compact: !this.$store.state.device.useFullReactionPicker,
+				src: ev.currentTarget || ev.target,
+			}, {}, 'closed');
 		},
 
 		setDefault() {