diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 3111768189a054584ce6e21ddd05d77c792b61fa..358da897d08da06349c88b500766998e40b13519 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -766,7 +766,7 @@ middle: "中"
 low: "低"
 emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
 ratio: "比率"
-notePreview: "ノートをプレビュー"
+previewNoteText: "本文をプレビュー"
 customCss: "カスタムCSS"
 customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
 global: "グローバル"
diff --git a/src/client/components/note-preview.vue b/src/client/components/note-preview.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a474a013414512f2ae5a05dea47b6fc447b6fb3c
--- /dev/null
+++ b/src/client/components/note-preview.vue
@@ -0,0 +1,98 @@
+<template>
+<div class="fefdfafb" v-size="{ min: [350, 500] }">
+	<MkAvatar class="avatar" :user="$i"/>
+	<div class="main">
+		<div class="header">
+			<MkUserName :user="$i"/>
+		</div>
+		<div class="body">
+			<div class="content">
+				<Mfm :text="text" :author="$i" :i="$i"/>
+			</div>
+		</div>
+	</div>
+</div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+
+export default defineComponent({
+	components: {
+	},
+
+	props: {
+		text: {
+			type: String,
+			required: true
+		}
+	},
+});
+</script>
+
+<style lang="scss" scoped>
+.fefdfafb {
+	display: flex;
+	margin: 0;
+	padding: 0;
+	overflow: clip;
+	font-size: 0.95em;
+
+	&.min-width_350px {
+		> .avatar {
+			margin: 0 10px 0 0;
+			width: 44px;
+			height: 44px;
+		}
+	}
+
+	&.min-width_500px {
+		> .avatar {
+			margin: 0 12px 0 0;
+			width: 48px;
+			height: 48px;
+		}
+	}
+
+	> .avatar {
+		flex-shrink: 0;
+		display: block;
+		margin: 0 10px 0 0;
+		width: 40px;
+		height: 40px;
+		border-radius: 8px;
+	}
+
+	> .main {
+		flex: 1;
+		min-width: 0;
+
+		> .header {
+			margin-bottom: 2px;
+		}
+
+		> .body {
+
+			> .cw {
+				cursor: default;
+				display: block;
+				margin: 0;
+				padding: 0;
+				overflow-wrap: break-word;
+
+				> .text {
+					margin-right: 8px;
+				}
+			}
+
+			> .content {
+				> .text {
+					cursor: default;
+					margin: 0;
+					padding: 0;
+				}
+			}
+		}
+	}
+}
+</style>
diff --git a/src/client/components/post-form.vue b/src/client/components/post-form.vue
index 3b8db21099c6482b875b15d5d11cb250655bfb27..7b4c5db46be55dd4bb9f43be466e743024a3e78c 100644
--- a/src/client/components/post-form.vue
+++ b/src/client/components/post-form.vue
@@ -17,7 +17,7 @@
 				<span v-if="visibility === 'followers'"><i class="fas fa-unlock"></i></span>
 				<span v-if="visibility === 'specified'"><i class="fas fa-envelope"></i></span>
 			</button>
-			<button class="_button preview" @click="showPreview = !showPreview" :class="{ active: showPreview }" v-tooltip="$ts.notePreview"><i class="fas fa-file-code"></i></button>
+			<button class="_button preview" @click="showPreview = !showPreview" :class="{ active: showPreview }" v-tooltip="$ts.previewNoteText"><i class="fas fa-file-code"></i></button>
 			<button class="submit _buttonPrimary" :disabled="!canPost" @click="post" data-cy-open-post-form-submit>{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button>
 		</div>
 	</header>
@@ -41,7 +41,7 @@
 		<input v-show="withHashtags" ref="hashtags" class="hashtags" v-model="hashtags" :placeholder="$ts.hashtags" list="hashtags">
 		<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
 		<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/>
-		<XNoteSimple class="preview" v-if="showPreview" :note="draftedNote"/>
+		<XNotePreview class="preview" v-if="showPreview" :text="text"/>
 		<footer>
 			<button class="_button" @click="chooseFileFrom" v-tooltip="$ts.attachFile"><i class="fas fa-photo-video"></i></button>
 			<button class="_button" @click="togglePoll" :class="{ active: poll }" v-tooltip="$ts.poll"><i class="fas fa-poll-h"></i></button>
@@ -64,6 +64,7 @@ import insertTextAtCursor from 'insert-text-at-cursor';
 import { length } from 'stringz';
 import { toASCII } from 'punycode/';
 import XNoteSimple from './note-simple.vue';
+import XNotePreview from './note-preview.vue';
 import * as mfm from 'mfm-js';
 import { host, url } from '@client/config';
 import { erase, unique } from '../../prelude/array';
@@ -83,6 +84,7 @@ import { defaultStore } from '@client/store';
 export default defineComponent({
 	components: {
 		XNoteSimple,
+		XNotePreview,
 		XPostFormAttaches: defineAsyncComponent(() => import('./post-form-attaches.vue')),
 		XPollEditor: defineAsyncComponent(() => import('./poll-editor.vue')),
 		MkInfo,
@@ -223,18 +225,6 @@ export default defineComponent({
 			return this.$instance ? this.$instance.maxNoteTextLength : 1000;
 		},
 
-		draftedNote(): object {
-			return {
-				user: this.$i,
-				createdAt: new Date(),
-				visibility: this.visibility,
-				localOnly: this.localOnly,
-				cw: this.useCw ? this.cw : null,
-				text: this.text,
-				files: this.files,
-				poll: this.poll,
-			};
-		}
 		withHashtags: defaultStore.makeGetterSetter('postFormWithHashtags'),
 		hashtags: defaultStore.makeGetterSetter('postFormHashtags'),
 	},