diff --git a/aleksis/core/frontend/components/calendar/CalendarControlBar.vue b/aleksis/core/frontend/components/calendar/CalendarControlBar.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c3f9c45c424aa73c0178ea15882e4e6783a73e43
--- /dev/null
+++ b/aleksis/core/frontend/components/calendar/CalendarControlBar.vue
@@ -0,0 +1,21 @@
+<script>
+export default {
+  name: "CalendarControlBar",
+  emits: ["prev", "next", "today"],
+};
+</script>
+
+<template>
+  <div class="d-flex justify-center">
+    <v-btn icon class="mx-2" @click="$emit('prev')">
+      <v-icon>mdi-chevron-left</v-icon>
+    </v-btn>
+    <v-btn outlined text class="mx-2" @click="$emit('today')">
+      <v-icon left>mdi-calendar-today-outline</v-icon>
+      {{ $t("calendar.today") }}
+    </v-btn>
+    <v-btn icon class="mx-2" @click="$emit('next')">
+      <v-icon>mdi-chevron-right</v-icon>
+    </v-btn>
+  </div>
+</template>
diff --git a/aleksis/core/frontend/components/calendar/CalendarOverview.vue b/aleksis/core/frontend/components/calendar/CalendarOverview.vue
index 89f4ff78d0a1d89671daee8f89ee5b28aaa491f5..7153b8e1e8dce599fc00527d28bc327a713e4ed4 100644
--- a/aleksis/core/frontend/components/calendar/CalendarOverview.vue
+++ b/aleksis/core/frontend/components/calendar/CalendarOverview.vue
@@ -14,28 +14,21 @@
         {{ $refs.calendar.title }}
       </h1>
       <v-row align="stretch">
-        <v-col
-          cols="12"
-          sm="4"
-          lg="3"
-          xl="2"
-          align-self="center"
-          class="d-flex justify-center"
-        >
-          <v-btn icon class="mx-2" @click="$refs.calendar.prev()">
-            <v-icon>mdi-chevron-left</v-icon>
-          </v-btn>
-          <v-btn outlined text class="mx-2" @click="calendarFocus = ''">
-            <v-icon left>mdi-calendar-today-outline</v-icon>
-            {{ $t("calendar.today") }}
-          </v-btn>
-          <v-btn icon class="mx-2" @click="$refs.calendar.next()">
-            <v-icon>mdi-chevron-right</v-icon>
-          </v-btn>
+        <!-- Control bar with prev, next and today buttons -->
+        <v-col cols="12" sm="4" lg="3" xl="2" align-self="center">
+          <calendar-control-bar
+            @prev="$refs.calendar.prev()"
+            @next="$refs.calendar.next()"
+            @today="calendarFocus = new Date()"
+          />
         </v-col>
+
+        <!-- Calendar title with current calendar time range -->
         <v-col v-if="$vuetify.breakpoint.lgAndUp" align-self="center">
           <h1 class="mx-2" v-if="$refs.calendar">{{ $refs.calendar.title }}</h1>
         </v-col>
+
+        <!-- Button menu for selecting currently active calendars (only tablets/mobile) -->
         <v-col
           v-if="$vuetify.breakpoint.mdAndDown"
           cols="12"
@@ -54,7 +47,10 @@
             />
           </button-menu>
         </v-col>
+
         <v-spacer v-if="$vuetify.breakpoint.lgAndUp" />
+
+        <!-- Calendar type select (month, week, day) -->
         <v-col
           cols="12"
           sm="4"
@@ -62,30 +58,20 @@
           align-self="center"
           :align="$vuetify.breakpoint.smAndUp ? 'right' : 'center'"
         >
-          <v-btn-toggle dense v-model="currentCalendarType" class="mx-2">
-            <v-btn
-              v-for="calendarType in availableCalendarTypes"
-              :value="calendarType.type"
-              :key="calendarType.type"
-            >
-              <v-icon v-if="$vuetify.breakpoint.smAndDown">{{
-                "mdi-" + calendarType.icon
-              }}</v-icon>
-              <span class="hidden-sm-and-down">{{
-                nameForMenu(calendarType)
-              }}</span>
-            </v-btn>
-          </v-btn-toggle>
+          <calendar-type-select v-model="currentCalendarType" />
         </v-col>
       </v-row>
       <v-row>
         <v-col v-if="$vuetify.breakpoint.lgAndUp" lg="3" xl="2">
+          <!-- Mini date picker -->
           <v-date-picker
             no-title
             v-model="calendarFocus"
             :style="{ margin: '0px -8px' }"
             :first-day-of-week="1"
           ></v-date-picker>
+
+          <!-- Calendar select (only desktop) -->
           <v-list flat subheader>
             <v-subheader>
               {{ $t("calendar.my_calendars") }}
@@ -102,6 +88,8 @@
             </v-btn>
           </v-list>
         </v-col>
+
+        <!-- Actual calendar -->
         <v-col lg="9" xl="10">
           <v-sheet height="600">
             <v-expand-transition>
@@ -160,10 +148,14 @@ import {
 
 import gqlCalendarOverview from "./calendarOverview.graphql";
 import gqlSetCalendarStatus from "./setCalendarStatus.graphql";
+import CalendarControlBar from "./CalendarControlBar.vue";
+import CalendarTypeSelect from "./CalendarTypeSelect.vue";
 
 export default {
   name: "CalendarOverview",
   components: {
+    CalendarTypeSelect,
+    CalendarControlBar,
     ButtonMenu,
     CalendarSelect,
   },
@@ -178,23 +170,6 @@ export default {
       selectedEvent: {},
       selectedElement: null,
       selectedOpen: false,
-      availableCalendarTypes: [
-        {
-          type: "month",
-          translationKey: "calendar.month",
-          icon: "calendar-month-outline",
-        },
-        {
-          type: "week",
-          translationKey: "calendar.week",
-          icon: "calendar-week-outline",
-        },
-        {
-          type: "day",
-          translationKey: "calendar.day",
-          icon: "calendar-today-outline",
-        },
-      ],
       fetchedDateRange: { start: null, end: null },
     };
   },
@@ -228,9 +203,6 @@ export default {
     },
   },
   methods: {
-    nameForMenu: function (item) {
-      return this.$t(item.translationKey);
-    },
     viewDay({ date }) {
       this.calendarFocus = date;
       this.currentCalendarType = "day";
diff --git a/aleksis/core/frontend/components/calendar/CalendarTypeSelect.vue b/aleksis/core/frontend/components/calendar/CalendarTypeSelect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1868b314a1af1106fe30b54571f629f2a577995f
--- /dev/null
+++ b/aleksis/core/frontend/components/calendar/CalendarTypeSelect.vue
@@ -0,0 +1,61 @@
+<script>
+export default {
+  name: "CalendarTypeSelect",
+  props: {
+    value: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      innerValue: this.value,
+      availableCalendarTypes: [
+        {
+          type: "month",
+          translationKey: "calendar.month",
+          icon: "calendar-month-outline",
+        },
+        {
+          type: "week",
+          translationKey: "calendar.week",
+          icon: "calendar-week-outline",
+        },
+        {
+          type: "day",
+          translationKey: "calendar.day",
+          icon: "calendar-today-outline",
+        },
+      ],
+    };
+  },
+  watch: {
+    value(val) {
+      this.innerValue = val;
+    },
+    innerValue(val) {
+      this.$emit("input", val);
+    },
+  },
+  methods: {
+    nameForMenu(item) {
+      return this.$t(item.translationKey);
+    },
+  },
+};
+</script>
+
+<template>
+  <v-btn-toggle dense v-model="innerValue" class="mx-2">
+    <v-btn
+      v-for="calendarType in availableCalendarTypes"
+      :value="calendarType.type"
+      :key="calendarType.type"
+    >
+      <v-icon v-if="$vuetify.breakpoint.smAndDown">{{
+        "mdi-" + calendarType.icon
+      }}</v-icon>
+      <span class="hidden-sm-and-down">{{ nameForMenu(calendarType) }}</span>
+    </v-btn>
+  </v-btn-toggle>
+</template>