---
title: "Vue Timeline Header and Footer Template Example | Mobiscroll"
component: "Timeline"
framework: "Vue"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/vue/timeline/hour-day-week-month-quarter-year-header-footer-template"
---

# Header and Footer Template - Vue Timeline demo

Customize time-scale headers and add occupancy footers to a Vue Timeline — format cells from hour to year and display per-slot utilization. For Vue and Nuxt.

- [Live demo](https://demo.mobiscroll.com/vue/timeline/hour-day-week-month-quarter-year-header-footer-template)
- [View SFC JS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue/tree/main/src/demos/eventcalendar/timeline/hour-day-week-month-quarter-year-header-footer-template)
- [View SFC TS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue-ts/tree/main/src/demos/eventcalendar/timeline/hour-day-week-month-quarter-year-header-footer-template)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/timeline/hour-day-week-month-quarter-year-header-footer-template.md), [jQuery](https://demo.mobiscroll.com/jquery/timeline/hour-day-week-month-quarter-year-header-footer-template.md), [Angular](https://demo.mobiscroll.com/angular/timeline/hour-day-week-month-quarter-year-header-footer-template.md), [React](https://demo.mobiscroll.com/react/timeline/hour-day-week-month-quarter-year-header-footer-template.md)

## Description

The headers hold key information like the date, day of the week and in some cases it also holds the full date. Whenever you need to show extra information, or if you would like to change the styling or date format, time format you can use the various header templates, depending on the view configuration. You can also show a footer element, for displaying more information.

Add summaries, statistics or simply color the background depending on the number events that occur on that specific day, like in this example.

**Check out how you can customize the date header for the scheduler** [Let's go →](https://demo.mobiscroll.com/vue/scheduler/date-header-template)

## What this demo shows

- Shows six timeline configurations with hour, day, week, month, quarter, and year resolutions.
- **Timeline layout** Time periods are arranged horizontally, while resources are listed as rows on the left.
- **Header templates** Each timeline resolution uses a custom header format for its time scale, such as hours, days, weeks, months, quarters, or years.
- **Footer templates** Footer cells display the resource occupancy percentage for each visible time slot.
- **Occupancy calculation** Percentages are calculated from the number of distinct resources occupied by events in each time slot.
- **Density overview** Values such as 25%, 63%, 88%, and 100% highlight how fully booked each time slot is.
- **Header and footer rendering** The demo demonstrates custom rendering for timeline header and footer cells with aggregated scheduling metrics.
- **Dynamic updates** Occupancy values update as events are created, moved, resized, or removed.
- **Event cards** Events are shown as colored cards with a left color stripe, a bold title, and the exact start and end time.
- **Date positioning** Events are positioned by their assigned resource and exact date and time range.
- **Event interaction** Events highlight on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** New events can be created by double-clicking the timeline or by clicking and dragging across a time range.
- **Scrolling** The timeline supports horizontal and vertical scrolling for navigating through time and resources.

## Best for

- **Workforce planning** Compare staffing coverage and open capacity across different timeline resolutions.
- **Equipment scheduling** Track when shared equipment is booked and identify time slots with remaining availability.
- **Room booking** Review resource occupancy across rooms while keeping the individual event schedule visible.
- **Asset management** Monitor scheduled usage for multiple resources in a row-based timeline layout.
- **Capacity analysis** Show high-level utilization metrics without hiding the detailed events for each resource.
- **Custom scheduling dashboards** Add summary values, occupancy indicators, or other aggregated metrics to timeline headers and footers.

## Tutorial

### Hourly header/footer template

With an hourly (or sub-hourly) resolution the [`hour`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-hour) and [`hourFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-hourFooter) options can be used for customizing the header and footer.

```vue
<script setup>
const hourView = {
  timeline: {
    type: 'day'
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="hourView">
  <template #hour="day">
    <div :class="'md-date-header-hour md-date-header-events-' + getEventOccurrence(day)">
      {{ formatDate('h:mm A', day.date) }}
    </div>
  </template>
  <template #hourFooter="day">
    <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
  </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-hour {
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    line-height: 20px;
    border-radius: 8px;
    margin: 3px;
    color: #000;
}

.md-date-header-events-one {
    background: #e9f5e4;
}

.md-date-header-events-few {
    background: #d0e3c6;
}

.md-date-header-events-more {
    background: #8ca77e;
}

.md-date-footer {
    font-size: 14px;
    font-weight: 600;
    text-align: center;
    line-height: 26px;
}
```

### Daily header/footer template

With a daily resolution, the [`timelineDay`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-timelineDay) and [`dayFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-dayFooter) options can come in handy for customizing the header and footer.

```vue
<script setup>
const dayView = {
  timeline: {
    type: 'month'
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="dayView">
    <template #timelineDay="day">
      <div :class="'md-date-header-day md-date-header-events-' + getEventOccurrence(day)">
        <div class="md-date-header-day-name">{{ formatDate('DDD', day.date) }}</div>
        <div class="md-date-header-day-nr">{{ formatDate('DD', day.date) }}</div>
      </div>
    </template>
    <template #dayFooter="day">
      <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
    </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-day {
    text-align: center;
    line-height: 20px;
    border-radius: 8px;
    margin: 4px;
}

.md-date-header-day-name {
    font-size: 13px;
    font-weight: 600;
}

.md-date-header-day-nr {
    font-size: 14px;
}

.md-date-header-events-one {
	background: #e9f5e4;
}

.md-date-header-events-few {
	background: #d0e3c6;
}

.md-date-header-events-more {
	background: #8ca77e;
}

.md-date-footer {
	font-size: 14px;
	font-weight: 600;
	text-align: center;
	line-height: 26px;
}
```

### Weekly header/footer template

When the resolution is weekly, the [`week`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-week) and [`weekFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-weekFooter) options can be used.

```vue
<script setup>
const weekView = {
  timeline: {
    type: 'week',
    resolutionHorizontal: 'week',
    size: 6
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="weekView">
    <template #week="day">
      <div :class="'md-date-header-week md-date-header-events-' + getEventOccurrence(day)">
        {{ formatDate('MMM DD', day.date) }}
      </div>
    </template>
    <template #weekFooter="day">
      <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
    </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-template .mbsc-timeline-header-week-text {
    display: block;
}

.md-date-header-template .mbsc-timeline-footer-week {
    text-align: center;
}

.md-date-header-week {
	text-align: center;
	font-weight: 600;
	color: initial;
	line-height: 20px;
	border-radius: 8px;
	margin: 3px;
}

.md-date-header-events-one {
	background: #e9f5e4;
}

.md-date-header-events-few {
	background: #d0e3c6;
}

.md-date-header-events-more {
	background: #8ca77e;
}

.md-date-footer {
	font-size: 14px;
	font-weight: 600;
	text-align: center;
	line-height: 26px;
}
```

### Monthly header/footer template

When displaying multiple months, the [`month`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-month) and [`monthFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-monthFooter) options can be used for customizing the header and footer per month.

```vue
<script setup>
const monthView = {
  timeline: {
    type: 'month',
    resolutionHorizontal: 'month',
    size: 6
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="monthView">
    <template #month="day">
      <div :class=" 'md-date-header-month md-date-header-events-' + getEventOccurrence(day)">
        {{ formatDate('MMM', day.startDate) + ' - ' + formatDate('MMM', day.endDate) }}
      </div>
    </template>
    <template #monthFooter="day">
      <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
    </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-month {
	text-align: center;
	font-weight: 600;
	color: initial;
	line-height: 20px;
	border-radius: 8px;
	margin: 3px;
}

.md-date-header-events-one {
	background: #e9f5e4;
}

.md-date-header-events-few {
	background: #d0e3c6;
}

.md-date-header-events-more {
	background: #8ca77e;
}

.md-date-footer {
	font-size: 14px;
	font-weight: 600;
	text-align: center;
	line-height: 26px;
}
```

### Quarter header/footer template

When displaying multiple quarters, the [`quarter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-quarter) and [`quarterFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-quarterFooter) options can be used for customizing the header and footer per quarter.

```vue
<script setup>
const quarterView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'quarter',
    size: 1
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="quarterView">
    <template #quarter="day">
      <div :class=" 'md-date-header-quarter md-date-header-events-' + getEventOccurrence(day)">
        Quarter {{ (day.date.getMonth() / 3 + 1) }}
      </div>
    </template>
    <template #quarterFooter="day">
      <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
    </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-quarter {
	text-align: center;
	font-weight: 600;
	color: initial;
	line-height: 20px;
	border-radius: 8px;
	margin: 3px;
}

.md-date-header-events-one {
	background: #e9f5e4;
}

.md-date-header-events-few {
	background: #d0e3c6;
}

.md-date-header-events-more {
	background: #8ca77e;
}

.md-date-footer {
	font-size: 14px;
	font-weight: 600;
	text-align: center;
	line-height: 26px;
}
```

### Yearly header/footer template

With a yearly resolution, the [`year`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-year) and [`yearFooter`](https://mobiscroll.com/docs/vue/eventcalendar/timeline#slot-yearFooter) options can be used for customizing the header and footer.

```vue
<script setup>
const yearView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'year',
    size: 6
  }
}

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    var resourceIds = []
    var nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = ((nr * 100) / this.myResources.length).toFixed(0)
  }
  return occuppancy
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    var eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <MbscEventcalendar :view="yearView">
    <template #year="day">
      <div :class="'md-date-header-year md-date-header-events-' + getEventOccurrence(day)">
        {{ formatDate('YYYY', day.date) }}
      </div>
    </template>
    <template #yearFooter="day">
      <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
    </template>
  </MbscEventcalendar>
</template>
```

```css
.md-date-header-year {
	text-align: center;
	font-weight: 600;
	color: initial;
	line-height: 20px;
	border-radius: 8px;
	margin: 3px;
}

.md-date-header-events-one {
	background: #e9f5e4;
}

.md-date-header-events-few {
	background: #d0e3c6;
}

.md-date-header-events-more {
	background: #8ca77e;
}

.md-date-footer {
	font-size: 14px;
	font-weight: 600;
	text-align: center;
	line-height: 26px;
}
```

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-themeVariant) - option
- [`view`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-view) - option
- [`data`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-resources) - option

## Code

### SFC JS

```vue
<script setup>
import { formatDate, MbscEventcalendar, setOptions } from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myHourView = {
  timeline: {
    type: 'day'
  }
}

const hourlyEvents = ref([
  {
    id: 1,
    start: '2026-10-31T02:00',
    end: '2026-10-31T10:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-10-31T15:00',
    end: '2026-10-31T21:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-31T08:00',
    end: '2026-10-31T15:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-31T05:00',
    end: '2026-10-31T13:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-31T03:00',
    end: '2026-10-31T10:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-10-31T16:00',
    end: '2026-10-31T23:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-31T06:00',
    end: '2026-10-31T11:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-10-31T15:00',
    end: '2026-10-31T22:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-31T08:00',
    end: '2026-10-31T17:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-31T05:00',
    end: '2026-10-31T13:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-10-31T16:00',
    end: '2026-10-31T21:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-31T09:00',
    end: '2026-10-31T18:00',
    title: 'Event 12',
    resource: 8
  }
])

const myDayView = {
  timeline: {
    type: 'month'
  }
}

const dailyEvents = ref([
  {
    id: 1,
    start: '2026-10-02T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-10-16T00:00',
    end: '2026-10-24T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-08T00:00',
    end: '2026-10-15T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-04T00:00',
    end: '2026-10-11T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-07T00:00',
    end: '2026-10-15T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-10-21T00:00',
    end: '2026-10-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-10T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-10-24T00:00',
    end: '2026-10-30T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-08T00:00',
    end: '2026-10-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-05T00:00',
    end: '2026-10-13T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-10-17T00:00',
    end: '2026-10-26T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-09T00:00',
    end: '2026-10-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myWeekView = {
  timeline: {
    type: 'week',
    resolutionHorizontal: 'week',
    size: 6
  }
}

const weeklyEvents = ref([
  {
    id: 1,
    start: '2026-10-10T00:00',
    end: '2026-10-24T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-11-02T00:00',
    end: '2026-11-18T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-27T00:00',
    end: '2026-11-13T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-11-04T00:00',
    end: '2026-11-27T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-24T00:00',
    end: '2026-11-02T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-11-10T00:00',
    end: '2026-11-24T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-20T00:00',
    end: '2026-11-03T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-11-08T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-28T00:00',
    end: '2026-11-15T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-09T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-11-05T00:00',
    end: '2026-11-22T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-24T00:00',
    end: '2026-11-13T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myMonthView = {
  timeline: {
    type: 'month',
    resolutionHorizontal: 'month',
    size: 6
  }
}

const monthlyEvents = ref([
  {
    id: 1,
    start: '2026-09-10T00:00',
    end: '2026-11-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2027-01-01T00:00',
    end: '2027-02-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-11-27T00:00',
    end: '2026-12-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-25T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-11-10T00:00',
    end: '2026-12-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2027-02-24T00:00',
    end: '2027-03-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-12-02T00:00',
    end: '2027-01-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2027-02-08T00:00',
    end: '2027-03-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-12-20T00:00',
    end: '2027-01-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2026-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2027-02-14T00:00',
    end: '2027-03-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-11-24T00:00',
    end: '2026-12-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myQuarterView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'quarter',
    size: 1
  }
}

const quarterEvents = ref([
  {
    id: 1,
    start: '2026-09-10T00:00',
    end: '2026-11-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2027-01-01T00:00',
    end: '2027-02-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-11-27T00:00',
    end: '2026-12-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-25T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-11-10T00:00',
    end: '2026-12-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2027-02-24T00:00',
    end: '2027-03-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-12-02T00:00',
    end: '2027-01-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2027-02-08T00:00',
    end: '2027-03-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-12-20T00:00',
    end: '2027-01-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2026-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2027-02-14T00:00',
    end: '2027-03-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-11-24T00:00',
    end: '2026-12-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myYearView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'year',
    size: 6
  }
}

const yearlyEvents = ref([
  {
    id: 1,
    start: '2027-04-10T00:00',
    end: '2028-08-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2029-06-01T00:00',
    end: '2030-09-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2028-03-27T00:00',
    end: '2029-10-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2028-08-25T00:00',
    end: '2029-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2027-09-10T00:00',
    end: '2029-04-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2030-01-24T00:00',
    end: '2031-05-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2025-04-02T00:00',
    end: '2026-08-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2028-04-08T00:00',
    end: '2029-11-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2028-01-20T00:00',
    end: '2029-08-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2027-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2029-10-14T00:00',
    end: '2030-11-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2029-02-24T00:00',
    end: '2031-04-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myResources = [
  {
    id: 1,
    name: 'Resource A',
    color: '#e20000'
  },
  {
    id: 2,
    name: 'Resource B',
    color: '#d6d145'
  },
  {
    id: 3,
    name: 'Resource C',
    color: '#4981d6'
  },
  {
    id: 4,
    name: 'Resource D',
    color: '#e25dd2'
  },
  {
    id: 5,
    name: 'Resource E',
    color: '#1dab2f'
  },
  {
    id: 6,
    name: 'Resource F',
    color: '#430404'
  },
  {
    id: 7,
    name: 'Resource G',
    color: '#f7961e'
  },
  {
    id: 8,
    name: 'Resource H',
    color: '#34c8e0'
  }
]

function getOccuppancy(events) {
  let occuppancy = 0
  if (events) {
    let resourceIds = []
    let nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = (nr * 100) / myResources.length
  }
  return occuppancy.toFixed(0)
}

function getEventOccurrence(args) {
  let eventOccurrence = 'none'

  if (args.events) {
    const eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <div class="md-date-header-template">
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Hourly header template</div>
      <MbscEventcalendar :view="myHourView" :data="hourlyEvents" :resources="myResources">
        <template #hour="day">
          <div
            :class="
              'md-date-header md-date-header-hour md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('h:mm A', day.date) }}
          </div>
        </template>
        <template #hourFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Daily header template</div>
      <MbscEventcalendar :view="myDayView" :data="dailyEvents" :resources="myResources">
        <template #timelineDay="day">
          <div
            :class="
              'md-date-header md-date-header-day md-date-header-events-' + getEventOccurrence(day)
            "
          >
            <div class="md-date-header-day-name">{{ formatDate('DDD', day.date) }}</div>
            <div class="md-date-header-day-nr">{{ formatDate('DD', day.date) }}</div>
          </div>
        </template>
        <template #dayFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Weekly header template</div>
      <MbscEventcalendar :view="myWeekView" :data="weeklyEvents" :resources="myResources">
        <template #week="day">
          <div
            :class="
              'md-date-header md-date-header-week md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('MMM DD', day.date) }}
          </div>
        </template>
        <template #weekFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Monthly header template</div>
      <MbscEventcalendar :view="myMonthView" :data="monthlyEvents" :resources="myResources">
        <template #month="day">
          <div
            :class="
              'md-date-header md-date-header-month md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('MMM', day.startDate) + ' - ' + formatDate('MMM', day.endDate) }}
          </div>
        </template>
        <template #monthFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Quarter header template</div>
      <MbscEventcalendar :view="myQuarterView" :data="quarterEvents" :resources="myResources">
        <template #quarter="day">
          <div
            :class="
              'md-date-header md-date-header-quarter md-date-header-events-' +
              getEventOccurrence(day)
            "
          >
            Quarter {{ day.date.getMonth() / 3 + 1 }}
          </div>
        </template>
        <template #quarterFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Yearly header template</div>
      <MbscEventcalendar :view="myYearView" :data="yearlyEvents" :resources="myResources">
        <template #year="day">
          <div
            :class="
              'md-date-header md-date-header-year md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('YYYY', day.date) }}
          </div>
        </template>
        <template #yearFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
  </div>
</template>

<style>
.md-date-header-template .mbsc-timeline-header-week-text {
  display: block;
}

.md-date-header {
  text-align: center;
  border-radius: 8px;
  line-height: 20px;
}

.md-date-header-day {
  padding: 3px;
  margin: 4px;
}

.md-date-header-hour {
  font-size: 12px;
  padding: 0;
  margin: 3px;
  color: #000;
  font-weight: 600;
}

.md-date-header-week,
.md-date-header-month,
.md-date-header-quarter,
.md-date-header-year {
  padding: 0 8px;
  margin: 3px;
  color: initial;
  font-weight: 600;
}

.md-date-header-template .mbsc-timeline-footer-week {
  text-align: center;
}

.md-date-header-day-name {
  font-size: 13px;
  font-weight: 600;
}

.md-date-header-day-nr {
  font-size: 14px;
}

.md-date-header-events-one {
  background: #e9f5e4;
}

.md-date-header-events-few {
  background: #d0e3c6;
}

.md-date-header-events-more {
  background: #8ca77e;
}

.md-date-footer {
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  line-height: 26px;
}
</style>
```

### SFC TS

```vue
<script setup lang="ts">
import { formatDate, MbscEventcalendar, setOptions } from '@mobiscroll/vue'
import type { MbscCalendarEvent, MbscEventcalendarView, MbscResource } from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myHourView: MbscEventcalendarView = {
  timeline: {
    type: 'day'
  }
}

const hourlyEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2026-10-31T02:00',
    end: '2026-10-31T10:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-10-31T15:00',
    end: '2026-10-31T21:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-31T08:00',
    end: '2026-10-31T15:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-31T05:00',
    end: '2026-10-31T13:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-31T03:00',
    end: '2026-10-31T10:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-10-31T16:00',
    end: '2026-10-31T23:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-31T06:00',
    end: '2026-10-31T11:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-10-31T15:00',
    end: '2026-10-31T22:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-31T08:00',
    end: '2026-10-31T17:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-31T05:00',
    end: '2026-10-31T13:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-10-31T16:00',
    end: '2026-10-31T21:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-31T09:00',
    end: '2026-10-31T18:00',
    title: 'Event 12',
    resource: 8
  }
])

const myDayView: MbscEventcalendarView = {
  timeline: {
    type: 'month'
  }
}

const dailyEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2026-10-02T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-10-16T00:00',
    end: '2026-10-24T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-08T00:00',
    end: '2026-10-15T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-04T00:00',
    end: '2026-10-11T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-07T00:00',
    end: '2026-10-15T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-10-21T00:00',
    end: '2026-10-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-10T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-10-24T00:00',
    end: '2026-10-30T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-08T00:00',
    end: '2026-10-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-05T00:00',
    end: '2026-10-13T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-10-17T00:00',
    end: '2026-10-26T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-09T00:00',
    end: '2026-10-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myWeekView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    resolutionHorizontal: 'week',
    size: 6
  }
}

const weeklyEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2026-10-10T00:00',
    end: '2026-10-24T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2026-11-02T00:00',
    end: '2026-11-18T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-10-27T00:00',
    end: '2026-11-13T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-11-04T00:00',
    end: '2026-11-27T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-10-24T00:00',
    end: '2026-11-02T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2026-11-10T00:00',
    end: '2026-11-24T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-10-20T00:00',
    end: '2026-11-03T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2026-11-08T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-10-28T00:00',
    end: '2026-11-15T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-09T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2026-11-05T00:00',
    end: '2026-11-22T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-10-24T00:00',
    end: '2026-11-13T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myMonthView: MbscEventcalendarView = {
  timeline: {
    type: 'month',
    resolutionHorizontal: 'month',
    size: 6
  }
}

const monthlyEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2026-09-10T00:00',
    end: '2026-11-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2027-01-01T00:00',
    end: '2027-02-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-11-27T00:00',
    end: '2026-12-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-25T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-11-10T00:00',
    end: '2026-12-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2027-02-24T00:00',
    end: '2027-03-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-12-02T00:00',
    end: '2027-01-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2027-02-08T00:00',
    end: '2027-03-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-12-20T00:00',
    end: '2027-01-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2026-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2027-02-14T00:00',
    end: '2027-03-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-11-24T00:00',
    end: '2026-12-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myQuarterView: MbscEventcalendarView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'quarter',
    size: 6
  }
}

const quarterEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2026-09-10T00:00',
    end: '2026-11-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2027-01-01T00:00',
    end: '2027-02-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2026-11-27T00:00',
    end: '2026-12-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2026-10-25T00:00',
    end: '2026-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2026-11-10T00:00',
    end: '2026-12-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2027-02-24T00:00',
    end: '2027-03-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2026-12-02T00:00',
    end: '2027-01-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2027-02-08T00:00',
    end: '2027-03-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2026-12-20T00:00',
    end: '2027-01-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2026-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2027-02-14T00:00',
    end: '2027-03-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2026-11-24T00:00',
    end: '2026-12-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myYearView: MbscEventcalendarView = {
  timeline: {
    type: 'year',
    resolutionHorizontal: 'year',
    size: 6
  }
}

const yearlyEvents = ref<MbscCalendarEvent[]>([
  {
    id: 1,
    start: '2027-04-10T00:00',
    end: '2028-08-07T00:00',
    title: 'Event 1',
    resource: 1
  },
  {
    id: 2,
    start: '2029-06-01T00:00',
    end: '2030-09-08T00:00',
    title: 'Event 2',
    resource: 1
  },
  {
    id: 3,
    start: '2028-03-27T00:00',
    end: '2029-10-23T00:00',
    title: 'Event 3',
    resource: 2
  },
  {
    id: 4,
    start: '2028-08-25T00:00',
    end: '2029-11-19T00:00',
    title: 'Event 4',
    resource: 3
  },
  {
    id: 5,
    start: '2027-09-10T00:00',
    end: '2029-04-18T00:00',
    title: 'Event 5',
    resource: 4
  },
  {
    id: 6,
    start: '2030-01-24T00:00',
    end: '2031-05-27T00:00',
    title: 'Event 6',
    resource: 4
  },
  {
    id: 7,
    start: '2025-04-02T00:00',
    end: '2026-08-13T00:00',
    title: 'Event 7',
    resource: 5
  },
  {
    id: 8,
    start: '2028-04-08T00:00',
    end: '2029-11-06T00:00',
    title: 'Event 8',
    resource: 5
  },
  {
    id: 9,
    start: '2028-01-20T00:00',
    end: '2029-08-17T00:00',
    title: 'Event 9',
    resource: 6
  },
  {
    id: 10,
    start: '2026-10-01T00:00',
    end: '2027-11-14T00:00',
    title: 'Event 10',
    resource: 7
  },
  {
    id: 11,
    start: '2029-10-14T00:00',
    end: '2030-11-20T00:00',
    title: 'Event 11',
    resource: 7
  },
  {
    id: 12,
    start: '2029-02-24T00:00',
    end: '2031-04-20T00:00',
    title: 'Event 12',
    resource: 8
  }
])

const myResources: MbscResource[] = [
  {
    id: 1,
    name: 'Resource A',
    color: '#e20000'
  },
  {
    id: 2,
    name: 'Resource B',
    color: '#d6d145'
  },
  {
    id: 3,
    name: 'Resource C',
    color: '#4981d6'
  },
  {
    id: 4,
    name: 'Resource D',
    color: '#e25dd2'
  },
  {
    id: 5,
    name: 'Resource E',
    color: '#1dab2f'
  },
  {
    id: 6,
    name: 'Resource F',
    color: '#430404'
  },
  {
    id: 7,
    name: 'Resource G',
    color: '#f7961e'
  },
  {
    id: 8,
    name: 'Resource H',
    color: '#34c8e0'
  }
]

function getOccuppancy(events: any) {
  let occuppancy = 0
  if (events) {
    let resourceIds: number[] = []
    let nr = 0
    for (const event of events) {
      if (resourceIds.indexOf(event.resource) < 0) {
        nr++
        resourceIds = [...resourceIds, event.resource]
      }
    }
    occuppancy = (nr * 100) / myResources.length
  }
  return occuppancy.toFixed(0)
}

function getEventOccurrence(args: any) {
  let eventOccurrence = 'none'

  if (args.events) {
    const eventNr = args.events.length
    if (eventNr === 0) {
      eventOccurrence = 'none'
    } else if (eventNr === 1) {
      eventOccurrence = 'one'
    } else if (eventNr < 4) {
      eventOccurrence = 'few'
    } else {
      eventOccurrence = 'more'
    }
  }
  return eventOccurrence
}
</script>

<template>
  <div class="md-date-header-template">
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Hourly header template</div>
      <MbscEventcalendar :view="myHourView" :data="hourlyEvents" :resources="myResources">
        <template #hour="day">
          <div
            :class="
              'md-date-header md-date-header-hour md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('h:mm A', day.date) }}
          </div>
        </template>
        <template #hourFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Daily header template</div>
      <MbscEventcalendar :view="myDayView" :data="dailyEvents" :resources="myResources">
        <template #timelineDay="day">
          <div
            :class="
              'md-date-header md-date-header-day md-date-header-events-' + getEventOccurrence(day)
            "
          >
            <div class="md-date-header-day-name">{{ formatDate('DDD', day.date) }}</div>
            <div class="md-date-header-day-nr">{{ formatDate('DD', day.date) }}</div>
          </div>
        </template>
        <template #dayFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Weekly header template</div>
      <MbscEventcalendar :view="myWeekView" :data="weeklyEvents" :resources="myResources">
        <template #week="day">
          <div
            :class="
              'md-date-header md-date-header-week md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('MMM DD', day.date) }}
          </div>
        </template>
        <template #weekFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Monthly header template</div>
      <MbscEventcalendar :view="myMonthView" :data="monthlyEvents" :resources="myResources">
        <template #month="day">
          <div
            :class="
              'md-date-header md-date-header-month md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('MMM', day.startDate) + ' - ' + formatDate('MMM', day.endDate) }}
          </div>
        </template>
        <template #monthFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Quarter header template</div>
      <MbscEventcalendar :view="myQuarterView" :data="quarterEvents" :resources="myResources">
        <template #quarter="day">
          <div
            :class="
              'md-date-header md-date-header-quarter md-date-header-events-' +
              getEventOccurrence(day)
            "
          >
            Quarter {{ day.date.getMonth() / 3 + 1 }}
          </div>
        </template>
        <template #quarterFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
    <div class="mbsc-form-group">
      <div class="mbsc-form-group-title">Yearly header template</div>
      <MbscEventcalendar :view="myYearView" :data="yearlyEvents" :resources="myResources">
        <template #year="day">
          <div
            :class="
              'md-date-header md-date-header-year md-date-header-events-' + getEventOccurrence(day)
            "
          >
            {{ formatDate('YYYY', day.date) }}
          </div>
        </template>
        <template #yearFooter="day">
          <div class="md-date-footer">{{ getOccuppancy(day.events) }}</div>
        </template>
      </MbscEventcalendar>
    </div>
  </div>
</template>

<style>
.md-date-header-template .mbsc-timeline-header-week-text {
  display: block;
}

.md-date-header {
  text-align: center;
  border-radius: 8px;
  line-height: 20px;
}

.md-date-header-day {
  padding: 3px;
  margin: 4px;
}

.md-date-header-hour {
  font-size: 12px;
  padding: 0;
  margin: 3px;
  color: #000;
  font-weight: 600;
}

.md-date-header-week,
.md-date-header-month,
.md-date-header-quarter,
.md-date-header-year {
  padding: 0 8px;
  margin: 3px;
  color: initial;
  font-weight: 600;
}

.md-date-header-template .mbsc-timeline-footer-week {
  text-align: center;
}

.md-date-header-day-name {
  font-size: 13px;
  font-weight: 600;
}

.md-date-header-day-nr {
  font-size: 14px;
}

.md-date-header-events-one {
  background: #e9f5e4;
}

.md-date-header-events-few {
  background: #d0e3c6;
}

.md-date-header-events-more {
  background: #8ca77e;
}

.md-date-footer {
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  line-height: 26px;
}
</style>
```

## Implementation notes

- Render 6 separate `Eventcalendar` instances on the same page, one for each timeline resolution: hourly, daily, weekly, monthly, quarterly, and yearly. All instances share the same 8 resources (Resource A-H, each with a distinct color). Each instance has its own independent event dataset of 12 events positioned with `dyndatetime` offsets.
- **View configurations:**
  - Hourly: `timeline: { type: 'day' }` - one column per hour for today
  - Daily: `timeline: { type: 'month' }` - one column per day for the current month
  - Weekly: `timeline: { type: 'week', resolutionHorizontal: 'week', size: 6 }` - 6 week columns
  - Monthly: `timeline: { type: 'month', resolutionHorizontal: 'month', size: 6 }` - 6 month columns
  - Quarterly: `timeline: { type: 'year', resolutionHorizontal: 'quarter', size: 1 }` - 4 quarter columns within 1 year
  - Yearly: `timeline: { type: 'year', resolutionHorizontal: 'year', size: 6 }` - 6 year columns
- Implement two helper functions shared across all renderers:
  - `getEventOccurrence(events)` - categorizes the array length as `'none'` (0), `'one'` (1), `'few'` (2-3), or `'more'` (4+). Used to vary the visual density indicator in headers.
  - `getOccuppancy(events)` - counts distinct resource IDs present in the events array, then returns `(count / totalResources * 100).toFixed(0)`. Used to show the occupancy percentage in footers.
- Each instance uses a **header renderer** and a **footer renderer**. Both receive `args` with `args.events` (all events overlapping that column) and `args.date`. The week header additionally receives `args.startDate` and `args.endDate`. Use `formatDate` for date formatting:
  - Hour: `formatDate('h:mm A', args.date)`
  - Day: `formatDate('DDD', args.date)` (abbreviated day name) + `formatDate('DD', args.date)` (day number)
  - Week: `formatDate('MMM DD', args.startDate) + ' - ' + formatDate('MMM DD', args.endDate)`
  - Month: `formatDate('MMM', args.date)`
  - Quarter: compute as `args.date.getMonth() / 3 + 1` and render `'Quarter N'`
  - Year: `formatDate('YYYY', args.date)`
- All footer renderers are identical: render `getOccuppancy(args.events) + ' %'`.
- The renderer option names differ per resolution. React names → Angular template option → Vue slot:
  - Hour header: `renderHour` → `hourTemplate` → `#hour`
  - Hour footer: `renderHourFooter` → `hourFooterTemplate` → `#hourFooter`
  - Day header: `renderTimelineDay` → `timelineDayTemplate` → `#timelineDay`
  - Day footer: `renderDayFooter` → `dayFooterTemplate` → `#dayFooter`
  - Week header: `renderWeek` → `weekTemplate` → `#week`
  - Week footer: `renderWeekFooter` → `weekFooterTemplate` → `#weekFooter`
  - Month header: `renderMonth` → `monthTemplate` → `#month`
  - Month footer: `renderMonthFooter` → `monthFooterTemplate` → `#monthFooter`
  - Quarter header: `renderQuarter` → `quarterTemplate` → `#quarter`
  - Quarter footer: `renderQuarterFooter` → `quarterFooterTemplate` → `#quarterFooter`
  - Year header: `renderYear` → `yearTemplate` → `#year`
  - Year footer: `renderYearFooter` → `yearFooterTemplate` → `#yearFooter`

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-vue.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config vue
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config vue --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/vue/getting-started/installation

## Related demos

- Previous: [Custom Cell Content](https://demo.mobiscroll.com/vue/timeline/dynamic-cell-content-template.md) - Add workload badges, status icons, and a hover quick-add button to each Vue Timeline cell — and cap events per cell.
- Next: [Employee Shift Slots](https://demo.mobiscroll.com/vue/timeline/shift-template.md) - Build a Vue Timeline with custom shift slot headers — replace hourly intervals with Morning and Afternoon, each with its own time range and color.
