diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index d830e0e47..e910fbab0 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -5,7 +5,7 @@
 	ref="el"
 	v-hotkey="keymap"
 	:class="$style.root"
-	:tabindex="!isDeleted ? '-1' : null"
+	:tabindex="!isDeleted ? '-1' : undefined"
 >
 	<MkNoteSub v-if="appearNote.reply && !renoteCollapsed" :note="appearNote.reply" :class="$style.replyTo"/>
 	<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
@@ -77,7 +77,13 @@
 				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
 			</div>
 			<footer :class="$style.footer">
-				<MkReactionsViewer :note="appearNote"/>
+				<MkReactionsViewer :note="appearNote" :max-number="16">
+					<template v-slot:more>
+						<button class="_button" :class="$style.reactionDetailsButton" @click="showReactions">
+							{{ i18n.ts.more }}
+						</button>
+					</template>
+				</MkReactionsViewer>
 				<button :class="$style.footerButton" class="_button" @click="reply()">
 					<i class="ti ti-arrow-back-up"></i>
 					<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ appearNote.repliesCount }}</p>
@@ -120,7 +126,7 @@
 </template>
 
 <script lang="ts" setup>
-import { computed, inject, onMounted, onUnmounted, reactive, ref, shallowRef, Ref } from 'vue';
+import { computed, inject, onMounted, onUnmounted, reactive, ref, shallowRef, Ref, defineAsyncComponent } from 'vue';
 import * as mfm from 'mfm-js';
 import * as misskey from 'misskey-js';
 import MkNoteSub from '@/components/MkNoteSub.vue';
@@ -196,7 +202,7 @@ const isLong = (appearNote.cw == null && appearNote.text != null && (
 const collapsed = ref(appearNote.cw == null && isLong);
 const isDeleted = ref(false);
 const muted = ref(checkWordMute(appearNote, $i, defaultStore.state.mutedWords));
-const translation = ref(null);
+const translation = ref<any>(null);
 const translating = ref(false);
 const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.user.instance);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibility) || appearNote.userId === $i.id);
@@ -361,6 +367,12 @@ function readPromo() {
 	});
 	isDeleted.value = true;
 }
+
+function showReactions(): void {
+	os.popup(defineAsyncComponent(() => import('@/components/MkReactedUsersDialog.vue')), {
+		noteId: appearNote.id,
+	}, {}, 'closed');
+}
 </script>
 
 <style lang="scss" module>
@@ -697,4 +709,19 @@ function readPromo() {
 	text-align: center;
 	opacity: 0.7;
 }
+
+.reactionDetailsButton {
+	display: inline-block;
+	height: 32px;
+	margin: 2px;
+	padding: 0 6px;
+	border: dashed 1px var(--divider);
+	border-radius: 4px;
+	background: transparent;
+	opacity: .8;
+
+	&:hover {
+		background: var(--X5);
+	}
+}
 </style>
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index 83fdf0f98..4abd2562d 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -107,7 +107,7 @@ useTooltip(buttonEl, async (showing) => {
 	border-radius: 4px;
 
 	&.canToggle {
-		background: rgba(0, 0, 0, 0.05);
+		background: var(--buttonBg);
 
 		&:hover {
 			background: rgba(0, 0, 0, 0.1);
diff --git a/packages/frontend/src/components/MkReactionsViewer.vue b/packages/frontend/src/components/MkReactionsViewer.vue
index 5981471c6..cdd6f528e 100644
--- a/packages/frontend/src/components/MkReactionsViewer.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.vue
@@ -7,23 +7,60 @@
 	:move-class="$store.state.animation ? $style.transition_x_move : ''"
 	tag="div" :class="$style.root"
 >
-	<XReaction v-for="(count, reaction) in note.reactions" :key="reaction" :reaction="reaction" :count="count" :is-initial="initialReactions.has(reaction)" :note="note"/>
+	<XReaction v-for="[reaction, count] in reactions" :key="reaction" :reaction="reaction" :count="count" :is-initial="initialReactions.has(reaction)" :note="note"/>
+	<slot v-if="hasMoreReactions" name="more" />
 </TransitionGroup>
 </template>
 
 <script lang="ts" setup>
-import { computed } from 'vue';
 import * as misskey from 'misskey-js';
-import { $i } from '@/account';
 import XReaction from '@/components/MkReactionsViewer.reaction.vue';
+import { watch } from 'vue';
 
-const props = defineProps<{
-	note: misskey.entities.Note;
-}>();
+const props = withDefaults(defineProps<{
+    note: misskey.entities.Note;
+    maxNumber?: number;
+}>(), {
+    maxNumber: Infinity,
+});
 
 const initialReactions = new Set(Object.keys(props.note.reactions));
 
-const isMe = computed(() => $i && $i.id === props.note.userId);
+let reactions = $ref<[string, number][]>([]);
+let hasMoreReactions = $ref(false);
+
+if (props.note.myReaction && !Object.keys(reactions).includes(props.note.myReaction)) {
+	reactions[props.note.myReaction] = props.note.reactions[props.note.myReaction];
+}
+
+watch([() => props.note.reactions, () => props.maxNumber], ([newSource, maxNumber]) => {
+	let newReactions: [string, number][] = [];
+	hasMoreReactions = Object.keys(newSource).length > maxNumber;
+
+	for (let i = 0; i < reactions.length; i++) {
+		const reaction = reactions[i][0];
+		if (reaction in newSource && newSource[reaction] !== 0) {
+			reactions[i][1] = newSource[reaction];
+			newReactions.push(reactions[i]);
+		}
+	}
+
+	const newReactionsNames = newReactions.map(([x]) => x);
+	newReactions = [
+		...newReactions,
+		...Object.entries(newSource)
+			.sort(([, a], [, b]) => b - a)
+			.filter(([y], i) => i < maxNumber && !newReactionsNames.includes(y)),
+	]
+
+	newReactions = newReactions.slice(0, props.maxNumber);
+
+	if (props.note.myReaction && !newReactions.map(([x]) => x).includes(props.note.myReaction)) {
+		newReactions.push([props.note.myReaction, newSource[props.note.myReaction]]);
+	}
+
+	reactions = newReactions;
+}, { immediate: true, deep: true });
 </script>
 
 <style lang="scss" module>