diff --git a/packages/client/src/components/MkUrlPreviewPopup.vue b/packages/client/src/components/MkUrlPreviewPopup.vue
index 2f0ffaa388..f343c6d8a6 100644
--- a/packages/client/src/components/MkUrlPreviewPopup.vue
+++ b/packages/client/src/components/MkUrlPreviewPopup.vue
@@ -1,52 +1,37 @@
 <template>
 <div class="fgmtyycl" :style="{ zIndex, top: top + 'px', left: left + 'px' }">
-	<transition :name="$store.state.animation ? 'zoom' : ''" @after-leave="$emit('closed')">
+	<transition :name="$store.state.animation ? 'zoom' : ''" @after-leave="emit('closed')">
 		<MkUrlPreview v-if="showing" class="_popup _shadow" :url="url"/>
 	</transition>
 </div>
 </template>
 
-<script lang="ts">
-import { defineComponent } from 'vue';
+<script lang="ts" setup>
+import { onMounted } from 'vue';
 import MkUrlPreview from '@/components/MkUrlPreview.vue';
 import * as os from '@/os';
 
-export default defineComponent({
-	components: {
-		MkUrlPreview,
-	},
+const props = defineProps<{
+	showing: boolean;
+	url: string;
+	source: HTMLElement;
+}>();
 
-	props: {
-		url: {
-			type: String,
-			required: true,
-		},
-		source: {
-			required: true,
-		},
-		showing: {
-			type: Boolean,
-			required: true,
-		},
-	},
+const emit = defineEmits<{
+	(ev: 'closed'): void;
+}>();
 
-	data() {
-		return {
-			u: null,
-			top: 0,
-			left: 0,
-			zIndex: os.claimZIndex('middle'),
-		};
-	},
+const zIndex = os.claimZIndex('middle');
+let top = $ref(0);
+let left = $ref(0);
 
-	mounted() {
-		const rect = this.source.getBoundingClientRect();
-		const x = Math.max((rect.left + (this.source.offsetWidth / 2)) - (300 / 2), 6) + window.pageXOffset;
-		const y = rect.top + this.source.offsetHeight + window.pageYOffset;
+onMounted(() => {
+	const rect = props.source.getBoundingClientRect();
+	const x = Math.max((rect.left + (props.source.offsetWidth / 2)) - (300 / 2), 6) + window.pageXOffset;
+	const y = rect.top + props.source.offsetHeight + window.pageYOffset;
 
-		this.top = y;
-		this.left = x;
-	},
+	top = y;
+	left = x;
 });
 </script>