diff --git a/CHANGELOG.md b/CHANGELOG.md
index eea57a30f5..34a2f88a9c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,10 @@
 - ローカリゼーションの更新
 
 ### Client
+- ノート詳細ページを改修
+	- 読み込み時のパフォーマンスが向上しました
+	- リノート一覧、リアクション一覧がタブとして追加されました
+		- ノートのメニューからは当該項目は消えました
 - プロフィールにその人が作ったPlayの一覧出せるように
 - メニューのスイッチの動作を改善
 - 絵文字ピッカーの検索の表示件数を100件に増加
@@ -48,7 +52,6 @@
 - `$[rainbow ]`記法が、動きのあるMFMが無効になっていても使用できるようになりました
 - Playの操作を行うAPI TokenをAPIコンソールから発行できるように
 - リアクションの表示サイズをより大きくできるように
-- ノート詳細ページ読み込み時のパフォーマンスを改善
 - タイムラインでリスト/アンテナ選択時のパフォーマンスを改善
 - 「Moderation note」、「Add moderation note」をローカライズできるように
 - 新しい実績を追加
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 94d9657ac8..ac714258e2 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -1110,6 +1110,10 @@ export interface Locale {
     "pastAnnouncements": string;
     "youHaveUnreadAnnouncements": string;
     "useSecurityKey": string;
+    "replies": string;
+    "renotes": string;
+    "loadReplies": string;
+    "loadConversation": string;
     "_announcement": {
         "forExistingUsers": string;
         "forExistingUsersDescription": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 743814d339..d97b09f63c 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -15,7 +15,7 @@ gotIt: "わかった"
 cancel: "キャンセル"
 noThankYou: "やめておく"
 enterUsername: "ユーザー名を入力"
-renotedBy: "{user}がRenote"
+renotedBy: "{user}がリノート"
 noNotes: "ノートはありません"
 noNotifications: "通知はありません"
 instance: "サーバー"
@@ -45,10 +45,10 @@ pin: "ピン留め"
 unpin: "ピン留め解除"
 copyContent: "内容をコピー"
 copyLink: "リンクをコピー"
-copyLinkRenote: "Renoteのリンクをコピー"
+copyLinkRenote: "リノートのリンクをコピー"
 delete: "削除"
 deleteAndEdit: "削除して編集"
-deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、Renote、返信も全て削除されます。"
+deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、リノート、返信も全て削除されます。"
 addToList: "リストに追加"
 addToAntenna: "アンテナに追加"
 sendMessage: "メッセージを送信"
@@ -105,13 +105,13 @@ followRequests: "フォロー申請"
 unfollow: "フォロー解除"
 followRequestPending: "フォロー許可待ち"
 enterEmoji: "絵文字を入力"
-renote: "Renote"
-unrenote: "Renote解除"
-renoted: "Renoteしました。"
-cantRenote: "この投稿はRenoteできません。"
-cantReRenote: "RenoteをRenoteすることはできません。"
+renote: "リノート"
+unrenote: "リノート解除"
+renoted: "リノートしました。"
+cantRenote: "この投稿はリノートできません。"
+cantReRenote: "リノートをリノートすることはできません。"
 quote: "引用"
-inChannelRenote: "チャンネル内Renote"
+inChannelRenote: "チャンネル内リノート"
 inChannelQuote: "チャンネル内引用"
 pinnedNote: "ピン留めされたノート"
 pinned: "ピン留め"
@@ -657,7 +657,7 @@ behavior: "動作"
 sample: "サンプル"
 abuseReports: "通報"
 reportAbuse: "通報"
-reportAbuseRenote: "Renoteを通報"
+reportAbuseRenote: "リノートを通報"
 reportAbuseOf: "{name}を通報する"
 fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。"
 abuseReported: "内容が送信されました。ご報告ありがとうございました。"
@@ -691,9 +691,9 @@ manageAccessTokens: "アクセストークンの管理"
 accountInfo: "アカウント情報"
 notesCount: "ノートの数"
 repliesCount: "返信した数"
-renotesCount: "Renoteした数"
+renotesCount: "リノートした数"
 repliedCount: "返信された数"
-renotedCount: "Renoteされた数"
+renotedCount: "リノートされた数"
 followingCount: "フォロー数"
 followersCount: "フォロワー数"
 sentReactionsCount: "リアクションした数"
@@ -989,7 +989,7 @@ thisPostMayBeAnnoying: "この投稿は迷惑になる可能性があります
 thisPostMayBeAnnoyingHome: "ホームに投稿"
 thisPostMayBeAnnoyingCancel: "やめる"
 thisPostMayBeAnnoyingIgnore: "このまま投稿"
-collapseRenotes: "見たことのあるRenoteを省略して表示"
+collapseRenotes: "見たことのあるリノートを省略して表示"
 internalServerError: "サーバー内部エラー"
 internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。"
 copyErrorInfo: "エラー情報をコピー"
@@ -1037,7 +1037,7 @@ forceShowAds: "常に広告を表示する"
 addMemo: "メモを追加"
 editMemo: "メモを編集"
 reactionsList: "リアクション一覧"
-renotesList: "Renote一覧"
+renotesList: "リノート一覧"
 notificationDisplay: "通知の表示"
 leftTop: "左上"
 rightTop: "右上"
@@ -1107,6 +1107,10 @@ currentAnnouncements: "現在のお知らせ"
 pastAnnouncements: "過去のお知らせ"
 youHaveUnreadAnnouncements: "未読のお知らせがあります。"
 useSecurityKey: "ブラウザまたはデバイスの指示に従って、セキュリティキーまたはパスキーを使用してください。"
+replies: "返信"
+renotes: "リノート"
+loadReplies: "返信を見る"
+loadConversation: "会話を見る"
 
 _announcement:
   forExistingUsers: "既存ユーザーのみ"
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index bedacbce2a..fdf22c5995 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -86,9 +86,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</div>
 			<MkReactionsViewer :note="appearNote" :maxNumber="16">
 				<template #more>
-					<button class="_button" :class="$style.reactionDetailsButton" @click="showReactions">
-						{{ i18n.ts.more }}
-					</button>
+					<div :class="$style.reactionOmitted">{{ i18n.ts.more }}</div>
 				</template>
 			</MkReactionsViewer>
 			<footer :class="$style.footer">
@@ -457,7 +455,7 @@ function showRenoteMenu(viaKeyboard = false): void {
 	} else {
 		os.popupMenu([
 			getCopyNoteLinkMenu(note, i18n.ts.copyLinkRenote),
-			null, 
+			null,
 			getAbuseNoteMenu(note, i18n.ts.reportAbuseRenote),
 			$i.isModerator || $i.isAdmin ? getUnrenote() : undefined,
 		], renoteTime.value, {
@@ -488,12 +486,6 @@ function readPromo() {
 	});
 	isDeleted.value = true;
 }
-
-function showReactions(): void {
-	os.popup(defineAsyncComponent(() => import('@/components/MkReactedUsersDialog.vue')), {
-		noteId: appearNote.id,
-	}, {}, 'closed');
-}
 </script>
 
 <style lang="scss" module>
@@ -941,7 +933,7 @@ function showReactions(): void {
 	opacity: 0.7;
 }
 
-.reactionDetailsButton {
+.reactionOmitted {
 	display: inline-block;
 	height: 32px;
 	margin: 2px;
@@ -950,9 +942,5 @@ function showReactions(): void {
 	border-radius: 4px;
 	background: transparent;
 	opacity: .8;
-
-	&:hover {
-		background: var(--X5);
-	}
 }
 </style>
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index f7578dd390..086667127b 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -11,7 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 	v-hotkey="keymap"
 	:class="$style.root"
 >
-	<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
+	<div v-if="appearNote.reply.replyId">
+		<div v-if="!conversationLoaded" style="padding: 16px">
+			<MkButton style="margin: 0 auto;" primary rounded @click="loadConversation">{{ i18n.ts.loadConversation }}</MkButton>
+		</div>
+		<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
+	</div>
 	<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
 	<div v-if="isRenote" :class="$style.renote">
 		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
@@ -125,7 +130,43 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</button>
 		</footer>
 	</article>
-	<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
+	<div :class="$style.tabs">
+		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ti ti-arrow-back-up"></i> {{ i18n.ts.replies }}</button>
+		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ti ti-repeat"></i> {{ i18n.ts.renotes }}</button>
+		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'reactions' }]" @click="tab = 'reactions'"><i class="ti ti-icons"></i> {{ i18n.ts.reactions }}</button>
+	</div>
+	<div>
+		<div v-if="tab === 'replies'" :class="$style.tab_replies">
+			<div v-if="!repliesLoaded" style="padding: 16px">
+				<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
+			</div>
+			<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
+		</div>
+		<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
+			<MkPagination :pagination="renotesPagination">
+				<template #default="{ items }">
+					<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
+						<MkUserCardMini :user="item.user" :withChart="false"/>
+					</MkA>
+				</template>
+			</MkPagination>
+		</div>
+		<div v-else-if="tab === 'reactions'" :class="$style.tab_reactions">
+			<div :class="$style.reactionTabs">
+				<button v-for="reaction in Object.keys(appearNote.reactions)" :key="reaction" :class="[$style.reactionTab, { [$style.reactionTabActive]: reactionTabType === reaction }]" class="_button" @click="reactionTabType = reaction">
+					<MkReactionIcon :reaction="reaction"/>
+					<span style="margin-left: 4px;">{{ appearNote.reactions[reaction] }}</span>
+				</button>
+			</div>
+			<MkPagination :pagination="reactionsPagination">
+				<template #default="{ items }">
+					<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
+						<MkUserCardMini :user="item.user" :withChart="false"/>
+					</MkA>
+				</template>
+			</MkPagination>
+		</div>
+	</div>
 </div>
 <div v-else class="_panel" :class="$style.muted" @click="muted = false">
 	<I18n :src="i18n.ts.userSaysSomething" tag="small">
@@ -169,6 +210,10 @@ import { claimAchievement } from '@/scripts/achievements';
 import { MenuItem } from '@/types/menu';
 import MkRippleEffect from '@/components/MkRippleEffect.vue';
 import { showMovedDialog } from '@/scripts/show-moved-dialog';
+import MkUserCardMini from '@/components/MkUserCardMini.vue';
+import MkPagination, { Paging } from '@/components/MkPagination.vue';
+import MkReactionIcon from '@/components/MkReactionIcon.vue';
+import MkButton from '@/components/MkButton.vue';
 
 const props = defineProps<{
 	note: Misskey.entities.Note;
@@ -224,6 +269,26 @@ const keymap = {
 	's': () => showContent.value !== showContent.value,
 };
 
+let tab = $ref('replies');
+let reactionTabType = $ref(null);
+
+const renotesPagination = $computed(() => ({
+	endpoint: 'notes/renotes',
+	limit: 10,
+	params: {
+		noteId: appearNote.id,
+	},
+}));
+
+const reactionsPagination = $computed(() => ({
+	endpoint: 'notes/reactions',
+	limit: 10,
+	params: {
+		noteId: appearNote.id,
+		type: reactionTabType,
+	},
+}));
+
 useNoteCapture({
 	rootEl: el,
 	note: $$(appearNote),
@@ -426,14 +491,20 @@ function blur() {
 	el.value.blur();
 }
 
-os.api('notes/children', {
-	noteId: appearNote.id,
-	limit: 30,
-}).then(res => {
-	replies.value = res;
-});
+const repliesLoaded = ref(false);
+function loadReplies() {
+	repliesLoaded.value = true;
+	os.api('notes/children', {
+		noteId: appearNote.id,
+		limit: 30,
+	}).then(res => {
+		replies.value = res;
+	});
+}
 
-if (appearNote.replyId) {
+const conversationLoaded = ref(false);
+function loadConversation() {
+	conversationLoaded.value = true;
 	os.api('notes/conversation', {
 		noteId: appearNote.replyId,
 	}).then(res => {
@@ -640,10 +711,52 @@ if (appearNote.replyId) {
 	}
 }
 
-.reply {
+.reply:not(:first-child) {
 	border-top: solid 0.5px var(--divider);
 }
 
+.tabs {
+	border-top: solid 0.5px var(--divider);
+	border-bottom: solid 0.5px var(--divider);
+	display: flex;
+}
+
+.tab {
+	flex: 1;
+	padding: 12px 8px;
+	border-top: solid 2px transparent;
+	border-bottom: solid 2px transparent;
+}
+
+.tabActive {
+	border-bottom: solid 2px var(--accent);
+}
+
+.tab_renotes {
+	padding: 16px;
+}
+
+.tab_reactions {
+	padding: 16px;
+}
+
+.reactionTabs {
+	display: flex;
+	gap: 8px;
+	flex-wrap: wrap;
+	margin-bottom: 8px;
+}
+
+.reactionTab {
+	padding: 4px 6px;
+	border: solid 1px var(--divider);
+	border-radius: 6px;
+}
+
+.reactionTabActive {
+	border-color: var(--accent);
+}
+
 @container (max-width: 500px) {
 	.root {
 		font-size: 0.9em;
diff --git a/packages/frontend/src/components/MkReactedUsersDialog.vue b/packages/frontend/src/components/MkReactedUsersDialog.vue
deleted file mode 100644
index b5f3a634a3..0000000000
--- a/packages/frontend/src/components/MkReactedUsersDialog.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<!--
-SPDX-FileCopyrightText: syuilo and other misskey contributors
-SPDX-License-Identifier: AGPL-3.0-only
--->
-
-<template>
-<MkModalWindow
-	ref="dialog"
-	:width="400"
-	:height="450"
-	@close="dialog.close()"
-	@closed="emit('closed')"
->
-	<template #header>{{ i18n.ts.reactionsList }}</template>
-
-	<MkSpacer :marginMin="20" :marginMax="28">
-		<div v-if="note" class="_gaps">
-			<div v-if="reactions.length === 0" class="_fullinfo">
-				<img :src="infoImageUrl" class="_ghost"/>
-				<div>{{ i18n.ts.nothing }}</div>
-			</div>
-			<template v-else>
-				<div :class="$style.tabs">
-					<button v-for="reaction in reactions" :key="reaction" :class="[$style.tab, { [$style.tabActive]: tab === reaction }]" class="_button" @click="tab = reaction">
-						<MkReactionIcon :reaction="reaction"/>
-						<span style="margin-left: 4px;">{{ note.reactions[reaction] }}</span>
-					</button>
-				</div>
-				<MkA v-for="user in users" :key="user.id" :to="userPage(user)" @click="dialog.close()">
-					<MkUserCardMini :user="user" :withChart="false"/>
-				</MkA>
-			</template>
-		</div>
-		<div v-else>
-			<MkLoading/>
-		</div>
-	</MkSpacer>
-</MkModalWindow>
-</template>
-
-<script lang="ts" setup>
-import { onMounted, watch } from 'vue';
-import * as Misskey from 'misskey-js';
-import MkModalWindow from '@/components/MkModalWindow.vue';
-import MkReactionIcon from '@/components/MkReactionIcon.vue';
-import MkUserCardMini from '@/components/MkUserCardMini.vue';
-import { userPage } from '@/filters/user';
-import { i18n } from '@/i18n';
-import * as os from '@/os';
-import { infoImageUrl } from '@/instance';
-
-const emit = defineEmits<{
-	(ev: 'closed'): void,
-}>();
-
-const props = defineProps<{
-	noteId: Misskey.entities.Note['id'];
-}>();
-
-const dialog = $shallowRef<InstanceType<typeof MkModalWindow>>();
-
-let note = $ref<Misskey.entities.Note>();
-let tab = $ref<string>();
-let reactions = $ref<string[]>();
-let users = $ref();
-
-watch($$(tab), async () => {
-	const res = await os.api('notes/reactions', {
-		noteId: props.noteId,
-		type: tab,
-		limit: 30,
-	});
-
-	users = res.map(x => x.user);
-});
-
-onMounted(() => {
-	os.api('notes/show', {
-		noteId: props.noteId,
-	}).then((res) => {
-		reactions = Object.keys(res.reactions);
-		tab = reactions[0];
-		note = res;
-	});
-});
-</script>
-
-<style lang="scss" module>
-.tabs {
-	display: flex;
-	gap: 8px;
-	flex-wrap: wrap;
-}
-
-.tab {
-	padding: 4px 6px;
-	border: solid 1px var(--divider);
-	border-radius: 6px;
-}
-
-.tabActive {
-	border-color: var(--accent);
-}
-</style>
diff --git a/packages/frontend/src/components/MkRenotedUsersDialog.vue b/packages/frontend/src/components/MkRenotedUsersDialog.vue
deleted file mode 100644
index 5e6784bb9c..0000000000
--- a/packages/frontend/src/components/MkRenotedUsersDialog.vue
+++ /dev/null
@@ -1,71 +0,0 @@
-<!--
-SPDX-FileCopyrightText: syuilo and other misskey contributors
-SPDX-License-Identifier: AGPL-3.0-only
--->
-
-<template>
-<MkModalWindow
-	ref="dialog"
-	:width="400"
-	:height="450"
-	@close="dialog.close()"
-	@closed="emit('closed')"
->
-	<template #header>{{ i18n.ts.renotesList }}</template>
-
-	<MkSpacer :marginMin="20" :marginMax="28">
-		<div v-if="renotes" class="_gaps">
-			<div v-if="renotes.length === 0" class="_fullinfo">
-				<img :src="infoImageUrl" class="_ghost"/>
-				<div>{{ i18n.ts.nothing }}</div>
-			</div>
-			<template v-else>
-				<MkA v-for="user in users" :key="user.id" :to="userPage(user)" @click="dialog.close()">
-					<MkUserCardMini :user="user" :withChart="false"/>
-				</MkA>
-			</template>
-		</div>
-		<div v-else>
-			<MkLoading/>
-		</div>
-	</MkSpacer>
-</MkModalWindow>
-</template>
-
-<script lang="ts" setup>
-import { onMounted } from 'vue';
-import * as Misskey from 'misskey-js';
-import MkModalWindow from '@/components/MkModalWindow.vue';
-import MkUserCardMini from '@/components/MkUserCardMini.vue';
-import { userPage } from '@/filters/user';
-import { i18n } from '@/i18n';
-import * as os from '@/os';
-import { infoImageUrl } from '@/instance';
-
-const emit = defineEmits<{
-	(ev: 'closed'): void,
-}>();
-
-const props = defineProps<{
-	noteId: Misskey.entities.Note['id'];
-}>();
-
-const dialog = $shallowRef<InstanceType<typeof MkModalWindow>>();
-
-let note = $ref<Misskey.entities.Note>();
-let renotes = $ref();
-let users = $ref();
-
-onMounted(async () => {
-	const res = await os.api('notes/renotes', {
-		noteId: props.noteId,
-		limit: 30,
-	});
-
-	renotes = res;
-	users = res.map(x => x.user);
-});
-</script>
-
-<style lang="scss" module>
-</style>
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 5bda993fff..d9fae946d3 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -238,18 +238,6 @@ export function getNoteMenu(props: {
 		os.pageWindow(`/notes/${appearNote.id}`);
 	}
 
-	function showReactions(): void {
-		os.popup(defineAsyncComponent(() => import('@/components/MkReactedUsersDialog.vue')), {
-			noteId: appearNote.id,
-		}, {}, 'closed');
-	}
-
-	function showRenotes(): void {
-		os.popup(defineAsyncComponent(() => import('@/components/MkRenotedUsersDialog.vue')), {
-			noteId: appearNote.id,
-		}, {}, 'closed');
-	}
-
 	async function translate(): Promise<void> {
 		if (props.translation.value != null) return;
 		props.translating.value = true;
@@ -279,14 +267,6 @@ export function getNoteMenu(props: {
 				icon: 'ti ti-info-circle',
 				text: i18n.ts.details,
 				action: openDetail,
-			}, {
-				icon: 'ti ti-repeat',
-				text: i18n.ts.renotesList,
-				action: showRenotes,
-			}, {
-				icon: 'ti ti-icons',
-				text: i18n.ts.reactionsList,
-				action: showReactions,
 			}, {
 				icon: 'ti ti-copy',
 				text: i18n.ts.copyContent,