Vue Timeline Employee Shift Slots
Get started with this exampleUsage
theme: 'ios' You can turn auto theming on and let it decide based on the platform.
Usage
themeVariant: 'light' You can turn auto dark mode on based on system settings.
Usage
clickToCreate: true,
// click to create is on dragToCreate: true,
// drag to create is on dragToMove: true,
// reordering is on dragToResize: true,
// resizing is on eventDelete: true
// deleting is on Fine-tune drag & drop with these options, which are false by default.
Usage
locale: localeEn Selecting the locale loads the localized settings and the translated UI text.
Employee Shift Slots
Use the slot template for setting up a custom time slot header. Customize how the time slots look and what they show. Utilize properties passed in the slots array.
Demo

Code
View code on GitHub
<script setup>
import { formatDate, MbscEventcalendar, setOptions } from '@mobiscroll/vue'
import { ref } from 'vue'
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
})
const staff = ref([
{
id: 1,
name: 'Ryan',
color: '#e20000',
title: 'Cloud System Engineer',
img: 'https://img.mobiscroll.com/demos/m1.png'
},
{
id: 2,
name: 'Kate',
color: '#60e81a',
title: 'Help Desk Specialist',
img: 'https://img.mobiscroll.com/demos/f1.png'
},
{
id: 3,
name: 'John',
color: '#3ba7ff',
title: 'Application Developer',
img: 'https://img.mobiscroll.com/demos/m2.png'
}
])
const shifts = ref([
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 2,
slot: 1
},
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 3,
slot: 1
},
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 6,
slot: 1
},
{
start: '2026-11-08T07:00',
end: '2026-11-08T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-08T07:00',
end: '2026-11-08T13:00',
title: '07:00 - 13:00',
resource: 2,
slot: 1
},
{
start: '2026-11-08T12:00',
end: '2026-11-08T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
},
{
start: '2026-11-09T07:00',
end: '2026-11-09T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-09T07:00',
end: '2026-11-09T13:00',
title: '07:00 - 13:00',
resource: 3,
slot: 1
},
{
start: '2026-11-09T12:00',
end: '2026-11-09T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-10T12:00',
end: '2026-11-10T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-11T07:00',
end: '2026-11-11T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-11T12:00',
end: '2026-11-11T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-11T12:00',
end: '2026-11-11T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
},
{
start: '2026-11-12T07:00',
end: '2026-11-12T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-12T12:00',
end: '2026-11-12T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
}
])
const myColors = [
{
background: '#a5ceff4d',
slot: 1,
recurring: {
repeat: 'weekly',
weekDays: 'MO,TU,WE,TH,FR'
}
},
{
background: '#f7f7bb4d',
slot: 2,
recurring: {
repeat: 'weekly',
weekDays: 'MO,TU,WE,TH,FR'
}
}
]
const mySlots = [
{
id: 1,
name: 'Morning'
},
{
id: 2,
name: 'Afternoon'
}
]
const myView = {
timeline: {
type: 'week',
eventDisplay: 'fill',
startDay: 1,
endDay: 5
}
}
function handleEventUpdate(args) {
const event = args.event
const index = shifts.value.findIndex((x) => x.id === event.id)
const newShifts = [...shifts.value]
newShifts.splice(index, 1, {
...event,
title: event.slot === 1 ? '07:00 - 13:00' : '12:00 - 18:00'
})
shifts.value = newShifts
return false
}
function myDefaultEvent(ev) {
const d = ev.start
const start = new Date(d.getFullYear(), d.getMonth(), d.getDate(), ev.slot === 1 ? 7 : 12)
const end = new Date(d.getFullYear(), d.getMonth(), d.getDate(), ev.slot === 1 ? 13 : 18)
return {
title: formatDate('HH:mm', start) + ' - ' + formatDate('HH:mm', end),
start,
end
}
}
</script>
<template>
<MbscEventcalendar
cssClass="md-shift-template"
:view="myView"
:data="shifts"
:resources="staff"
:colors="myColors"
:slots="mySlots"
:clickToCreate="true"
:dragToMove="true"
:dragToResize="false"
:extendDefaultEvent="myDefaultEvent"
@event-update="handleEventUpdate"
>
<template #slot="args">
<div
class="md-employees-cont"
:style="{ background: args.slot.id === 1 ? '#a5ceff4d' : '#f7f7bb4d', padding: '4px' }"
>
<div class="slot-name">{{ args.slot.name }}</div>
<div class="slot-time">{{ args.slot.id === 1 ? '7am - 1pm' : '12pm - 6pm' }}</div>
</div>
</template>
</MbscEventcalendar>
</template>
<style>
.slot-name {
line-height: 20px;
font-size: 15px;
}
.slot-time {
opacity: 0.5;
line-height: 20px;
font-size: 13px;
}
.md-shift-template .mbsc-timeline-header-placeholder {
height: 74px;
}
.md-shift-template .mbsc-timeline-slots {
height: 48px;
text-align: center;
}
.md-shift-template .mbsc-schedule-event {
display: flex;
align-items: center;
justify-content: center;
height: 36px;
}
.md-shift-template .mbsc-timeline-slot-title {
padding: 0;
}
</style> <script setup lang="ts">
import { formatDate, MbscEventcalendar, setOptions } from '@mobiscroll/vue'
import type {
MbscCalendarColor,
MbscCalendarEvent,
MbscEventcalendarView,
MbscEventUpdateEvent,
MbscResource,
MbscSlot
} from '@mobiscroll/vue'
import { ref } from 'vue'
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
})
const staff = ref<MbscResource[]>([
{
id: 1,
name: 'Ryan',
color: '#e20000',
title: 'Cloud System Engineer',
img: 'https://img.mobiscroll.com/demos/m1.png'
},
{
id: 2,
name: 'Kate',
color: '#60e81a',
title: 'Help Desk Specialist',
img: 'https://img.mobiscroll.com/demos/f1.png'
},
{
id: 3,
name: 'John',
color: '#3ba7ff',
title: 'Application Developer',
img: 'https://img.mobiscroll.com/demos/m2.png'
}
])
const shifts = ref<MbscCalendarEvent[]>([
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 2,
slot: 1
},
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 3,
slot: 1
},
{
start: '2026-11-07T07:00',
end: '2026-11-07T13:00',
title: '07:00 - 13:00',
resource: 6,
slot: 1
},
{
start: '2026-11-08T07:00',
end: '2026-11-08T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-08T07:00',
end: '2026-11-08T13:00',
title: '07:00 - 13:00',
resource: 2,
slot: 1
},
{
start: '2026-11-08T12:00',
end: '2026-11-08T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
},
{
start: '2026-11-09T07:00',
end: '2026-11-09T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-09T07:00',
end: '2026-11-09T13:00',
title: '07:00 - 13:00',
resource: 3,
slot: 1
},
{
start: '2026-11-09T12:00',
end: '2026-11-09T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-10T12:00',
end: '2026-11-10T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-11T07:00',
end: '2026-11-11T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-11T12:00',
end: '2026-11-11T18:00',
title: '12:00 - 18:00',
resource: 2,
slot: 2
},
{
start: '2026-11-11T12:00',
end: '2026-11-11T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
},
{
start: '2026-11-12T07:00',
end: '2026-11-12T13:00',
title: '07:00 - 13:00',
resource: 1,
slot: 1
},
{
start: '2026-11-12T12:00',
end: '2026-11-12T18:00',
title: '12:00 - 18:00',
resource: 3,
slot: 2
}
])
const myColors: MbscCalendarColor[] = [
{
background: '#a5ceff4d',
slot: 1,
recurring: {
repeat: 'weekly',
weekDays: 'MO,TU,WE,TH,FR'
}
},
{
background: '#f7f7bb4d',
slot: 2,
recurring: {
repeat: 'weekly',
weekDays: 'MO,TU,WE,TH,FR'
}
}
]
const mySlots: MbscSlot[] = [
{
id: 1,
name: 'Morning'
},
{
id: 2,
name: 'Afternoon'
}
]
const myView: MbscEventcalendarView = {
timeline: {
type: 'week',
eventDisplay: 'fill',
startDay: 1,
endDay: 5
}
}
function handleEventUpdate(args: MbscEventUpdateEvent) {
const event = args.event
const index = shifts.value.findIndex((x) => x.id === event.id)
const newShifts = [...shifts.value]
newShifts.splice(index, 1, {
...event,
title: event.slot === 1 ? '07:00 - 13:00' : '12:00 - 18:00'
})
shifts.value = newShifts
return false
}
function myDefaultEvent(ev: MbscCalendarEvent) {
const d = ev.start as Date
const start = new Date(d.getFullYear(), d.getMonth(), d.getDate(), ev.slot === 1 ? 7 : 12)
const end = new Date(d.getFullYear(), d.getMonth(), d.getDate(), ev.slot === 1 ? 13 : 18)
return {
title: formatDate('HH:mm', start) + ' - ' + formatDate('HH:mm', end),
start,
end
}
}
</script>
<template>
<MbscEventcalendar
cssClass="md-shift-template"
:view="myView"
:data="shifts"
:resources="staff"
:colors="myColors"
:slots="mySlots"
:clickToCreate="true"
:dragToMove="true"
:dragToResize="false"
:extendDefaultEvent="myDefaultEvent"
@event-update="handleEventUpdate"
>
<template #slot="args">
<div
class="md-employees-cont"
:style="{ background: args.slot.id === 1 ? '#a5ceff4d' : '#f7f7bb4d', padding: '4px' }"
>
<div class="slot-name">{{ args.slot.name }}</div>
<div class="slot-time">{{ args.slot.id === 1 ? '7am - 1pm' : '12pm - 6pm' }}</div>
</div>
</template>
</MbscEventcalendar>
</template>
<style>
.slot-name {
line-height: 20px;
font-size: 15px;
}
.slot-time {
opacity: 0.5;
line-height: 20px;
font-size: 13px;
}
.md-shift-template .mbsc-timeline-header-placeholder {
height: 74px;
}
.md-shift-template .mbsc-timeline-slots {
height: 48px;
text-align: center;
}
.md-shift-template .mbsc-schedule-event {
display: flex;
align-items: center;
justify-content: center;
height: 36px;
}
.md-shift-template .mbsc-timeline-slot-title {
padding: 0;
}
</style>