diff --git a/lib/classes/ActionMenu.php b/lib/classes/ActionMenu.php
index 6fc016a2e7c2946b7fcd08b5c7e17ff6f1ef1c1d..aa6c5240e47f8ed5a72f3689fe7ada1b828639e0 100644
--- a/lib/classes/ActionMenu.php
+++ b/lib/classes/ActionMenu.php
@@ -96,6 +96,18 @@ class ActionMenu
         return $result;
     }
 
+    /**
+     * Returns the number of action menu items (not counting separators).
+     *
+     * @return int count
+     */
+    protected function countActions(): int
+    {
+        return count(array_filter($this->actions, function($action) {
+            return $action['type'] !== 'separator';
+        }));
+    }
+
     /**
      * Adds a link to the list of actions.
      *
@@ -213,6 +225,23 @@ class ActionMenu
         return $this;
     }
 
+    /**
+     * Adds a separator line to the list of actions.
+     *
+     * @return ActionMenu instance to allow chaining
+     */
+    public function addSeparator(): ActionMenu
+    {
+        if ($this->checkCondition()) {
+            $this->actions[] = [
+                'type'   => 'separator',
+                'index'  => ''
+            ];
+        }
+
+        return $this;
+    }
+
     /**
      * Adds a css classs to the root element in html.
      *
@@ -251,7 +280,7 @@ class ActionMenu
      */
     public function render()
     {
-        if (count($this->actions) === 0) {
+        if ($this->countActions() === 0) {
             return '';
         }
 
@@ -342,7 +371,7 @@ class ActionMenu
         $rendering_mode = $this->rendering_mode;
 
         if ($rendering_mode === null) {
-            $rendering_mode = count($this->actions) <= Config::get()->ACTION_MENU_THRESHOLD
+            $rendering_mode = $this->countActions() <= Config::get()->ACTION_MENU_THRESHOLD
                             ? self::RENDERING_MODE_ICONS
                             : self::RENDERING_MODE_MENU;
         }
diff --git a/resources/assets/stylesheets/scss/actionmenu.scss b/resources/assets/stylesheets/scss/actionmenu.scss
index 588f50c039132c21bbda0d1f2dedbd018da3c936..56b1317c41243a4253b079dcda3ffd279b7a0fcb 100644
--- a/resources/assets/stylesheets/scss/actionmenu.scss
+++ b/resources/assets/stylesheets/scss/actionmenu.scss
@@ -141,6 +141,12 @@ $action-menu-shadow: 1px 1px 1px $dark-gray-color-60;
                 color: $active-color;
             }
         }
+
+        > hr {
+            border-style: none;
+            border-top: thin solid var(--dark-gray-color-45);
+            margin: 4px 0;
+        }
     }
 
     &.is-open {
diff --git a/resources/vue/components/StudipActionMenu.vue b/resources/vue/components/StudipActionMenu.vue
index d67f6a230f47e9076dd3a1f0d69569140fdcc77f..014a1cacefc1857f4381e6bd5da019c9041039f6 100644
--- a/resources/vue/components/StudipActionMenu.vue
+++ b/resources/vue/components/StudipActionMenu.vue
@@ -11,10 +11,10 @@
             </div>
             <ul class="action-menu-list">
                 <li v-for="item in navigationItems" :key="item.id" class="action-menu-item">
-                    <a v-if="item.type === 'link'" v-bind="linkAttributes(item)" v-on="linkEvents(item)">
+                    <hr v-if="item.type === 'separator'">
+                    <a v-else-if="item.type === 'link'" v-bind="linkAttributes(item)" v-on="linkEvents(item)">
                         <studip-icon v-if="item.icon !== false" :shape="item.icon.shape" :role="item.icon.role"></studip-icon>
                         <span v-else class="action-menu-no-icon"></span>
-
                         {{ item.label }}
                     </a>
                     <label v-else-if="item.icon" class="undecorated" v-bind="linkAttributes(item)" v-on="linkEvents(item)">
@@ -33,7 +33,8 @@
     </div>
     <div v-else>
         <a v-for="item in navigationItems" :key="item.id" v-bind="linkAttributes(item)" v-on="linkEvents(item)">
-            <studip-icon :title="item.label" :shape="item.icon.shape" :role="item.icon.role" :size="20"></studip-icon>
+            <span v-if="item.type === 'separator'" class="quiet">|</span>
+            <studip-icon v-else :title="item.label" :shape="item.icon.shape" :role="item.icon.role" :size="20"></studip-icon>
         </a>
     </div>
 </template>
@@ -119,7 +120,7 @@ export default {
             if (collapseAt === true) {
                 return true;
             }
-            return Number.parseInt(collapseAt) <= this.items.length;
+            return Number.parseInt(collapseAt) <= this.items.filter((item) => item.type !== 'separator').length;
         },
         title () {
             return this.context ? this.$gettextInterpolate(this.$gettext('Aktionsmenü für %{context}'), {context: this.context}) : this.$gettext('Aktionsmenü');
diff --git a/templates/shared/action-menu-single.php b/templates/shared/action-menu-single.php
index a34a01e69dcefe5643f96cc8037a88c10a8e26a5..455bc44a6ba3f48dca69876895b033de2c324991 100644
--- a/templates/shared/action-menu-single.php
+++ b/templates/shared/action-menu-single.php
@@ -30,5 +30,7 @@
         <? endif ?>
     <? elseif ($action['type'] === 'multi-person-search'): ?>
         <?= $action['object']->render(false) ?>
+    <? elseif ($action['type'] === 'separator'): ?>
+        <span class="quiet">|</span>
     <? endif ?>
 <? endforeach ?>
diff --git a/templates/shared/action-menu.php b/templates/shared/action-menu.php
index c781f3338596474fd14a50b270f4ec188954b235..4f3b5f10ff9e09ba635bc12b5f6df2e723eb351e 100644
--- a/templates/shared/action-menu.php
+++ b/templates/shared/action-menu.php
@@ -48,6 +48,8 @@
                 <? endif ?>
             <? elseif ($action['type'] === 'multi-person-search'): ?>
                 <?= $action['object']->render() ?>
+            <? elseif ($action['type'] === 'separator'): ?>
+                <hr>
             <? endif ?>
             </li>
         <? endforeach ?>