diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
index d5f35b553e32cadb8c7e8c2ac61d712f440770a6..380a0f4a01ef0b6f911b3b00e6a8c7bb982834e3 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
@@ -1,13 +1,16 @@
 <script>
 import {
   createPersonalNotes,
+  deletePersonalNotes,
   updatePersonalNotes,
 } from "./personal_notes.graphql";
 import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
 import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
+import DeleteDialog from "aleksis.core/components/generic/dialogs/DeleteDialog.vue";
 
 export default {
   name: "TextNote",
+  components: { DeleteDialog },
   mixins: [mutateMixin, personalNoteRelatedMixin],
   props: {
     value: {
@@ -21,43 +24,17 @@ export default {
         return this.value.note;
       },
       set(newValue) {
-        const input = (extras) => ({
-          input: [
-            {
-              note: newValue,
-              ...extras,
-            },
-          ],
-        });
-
-        const updater =
-          (replace) => (storedDocumentations, incomingPersonalNotes) => {
-            const note = incomingPersonalNotes[0];
-            const documentation = storedDocumentations.find(
-              (doc) => doc.id === this.documentation.id,
-            );
-            const participationStatus = documentation.participations.find(
-              (part) => part.id === this.participation.id,
-            );
-            if (replace) {
-              const index = participationStatus.notesWithNote.findIndex(
-                (n) => n.id === this.participation.id,
-              );
-              participationStatus.notesWithNote.splice(index, 1, note);
-            } else {
-              participationStatus.notesWithNote.push(note);
-
-              this.$emit("create");
-            }
-
-            return storedDocumentations;
-          };
-
+        if (!newValue) {
+          // this is a DELETE action, show the dialog, ...
+          this.showDeleteConfirm = true;
+          return;
+        }
         const create = !this.value.id;
 
         this.mutate(
           create ? createPersonalNotes : updatePersonalNotes,
-          input(
+          this.getInput(
+            newValue,
             create
               ? {
                   documentation: this.documentation.id,
@@ -68,11 +45,66 @@ export default {
                   id: this.value.id,
                 },
           ),
-          updater(!create),
+          this.getUpdater(create ? "create" : "update"),
         );
       },
     },
   },
+  methods: {
+    getInput(newValue, extras) {
+      return {
+        input: [
+          {
+            note: newValue,
+            ...extras,
+          },
+        ],
+      };
+    },
+    getUpdater(mode) {
+      return (storedDocumentations, incomingPersonalNotes) => {
+        const note = incomingPersonalNotes?.[0] || undefined;
+        const documentation = storedDocumentations.find(
+          (doc) => doc.id === this.documentation.id,
+        );
+        const participationStatus = documentation.participations.find(
+          (part) => part.id === this.participation.id,
+        );
+        switch (mode.toLowerCase()) {
+          case "update": case "delete": {
+            const updateIndex = participationStatus.notesWithNote.findIndex(
+              (n) => n.id === this.value.id,
+            );
+            if (mode === "update") {
+              participationStatus.notesWithNote.splice(updateIndex, 1, note);
+            } else {
+              participationStatus.notesWithNote.splice(updateIndex, 1);
+            }
+
+            break;
+          }
+
+          case "create":
+            participationStatus.notesWithNote.push(note);
+
+            this.$emit("create");
+            break;
+
+          default:
+            console.error("Invalid mode in getUpdater():", mode);
+            break;
+        }
+
+        return storedDocumentations;
+      };
+    },
+  },
+  data() {
+    return {
+      showDeleteConfirm: false,
+      deletePersonalNotes,
+    };
+  },
 };
 </script>
 
@@ -83,10 +115,38 @@ export default {
     outlined
     hide-details
     class="mb-4"
-    clearable
     :label="$t('alsijil.personal_notes.note')"
     :value="model"
     @change="model = $event"
     :loading="loading"
-  />
+  >
+    <template #append>
+      <v-slide-x-reverse-transition>
+        <v-btn v-if="!!model" icon @click="showDeleteConfirm = true">
+          <v-icon> $deleteContent </v-icon>
+        </v-btn>
+      </v-slide-x-reverse-transition>
+
+      <delete-dialog
+        v-model="showDeleteConfirm"
+        :gql-delete-mutation="deletePersonalNotes"
+        :affected-query="affectedQuery"
+        item-attribute="fullName"
+        :items="[value]"
+        :custom-update="getUpdater('delete')"
+      >
+        <template #title>
+          {{ $t("alsijil.personal_notes.confirm_delete") }}
+        </template>
+        <template #body>
+          {{
+            $t("alsijil.personal_notes.confirm_delete_explanation", {
+              note: value.note,
+              name: participation.person.fullName,
+            })
+          }}
+        </template>
+      </delete-dialog>
+    </template>
+  </v-textarea>
 </template>