Header and Footer Template
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.
Demo
With an hourly (or sub-hourly) resolution the
renderHour and renderHourFooter options can be used for customizing the header and footer.
jsxconst hourView = React.useMemo(() => {
return {
timeline: {
type: 'day'
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomHour = (args) => {
return <div className={'md-date-header-hour md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('h:mm A', args.date)}
</div>
}
const renderCustomHourFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={hourView}
renderHour={renderCustomHour}
renderHourFooter={renderCustomHourFooter}
/>
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;
}
With a daily resolution, the
renderTimelineDay and renderDayFooter options can come in handy for customizing the header and footer.
jsxconst dayView = React.useMemo(() => {
return {
timeline: {
type: 'month'
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomDay = (args) => {
const date = args.date;
return <div className={'md-date-header-events-' + getEventOccurrence(args.events)}>
<div className="md-date-header-day-name">{formatDate('DDD', date)}</div>
<div className="md-date-header-day-nr">{formatDate('DD', date)}</div>
</div>;
}
const renderCustomDayFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={dayView}
renderTimelineDay={renderCustomDay}
renderDayFooter={renderCustomDayFooter}
/>
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;
}
When the resolution is weekly, the
renderWeek and renderWeekFooter options can be used.
jsxconst weekView = React.useMemo(() => {
return {
timeline: {
type: 'week',
resolutionHorizontal: 'week',
size: 6
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomWeek = (args) => {
return <div className={'md-date-header-week md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM DD', args.startDate) + ' - ' + formatDate('MMM DD', args.endDate)}
</div>;
}
const renderCustomWeekFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={weekView}
renderWeek={renderCustomWeek}
renderWeekFooter={renderCustomWeekFooter}
/>
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;
}
When displaying multiple months, the
renderMonth and renderMonthFooter options can be used for customizing the header and footer per month.
jsxconst monthView = React.useMemo(() => {
return {
timeline: {
type: 'month',
resolutionHorizontal: 'month',
size: 6
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomMonth = (args) => {
return <div className={'md-date-header-month md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM', args.date)}
</div>
}
const renderCustomMonthFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={monthView}
renderMonth={renderCustomMonth}
renderMonthFooter={renderCustomMonthFooter}
/>
css.md-date-header-month {
text-align: center;
font-weight: 600;
color: initial;
line-height: 20px;
border-radius: 8px;
margin: 3px;
}
.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;
}
When displaying multiple quarters, the
renderQuarter and renderQuarterFooter options can be used for customizing the header and footer per quarter.
jsxconst quarterView = React.useMemo(() => {
return {
timeline: {
type: 'year',
resolutionHorizontal: 'quarter',
size: 1
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomQuarter = (args) => {
const title = 'Quarter ' + (args.date.getMonth() / 3 + 1);
return <div className={'md-date-header-quarter md-date-header-events-' + getEventOccurrence(args.events)}>
{title}
</div>
}
const renderCustomQuarterFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={quarterView}
renderQuarter={renderCustomQuarter}
renderQuarterFooter={renderCustomQuarterFooter}
/>
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;
}
With a yearly resolution, the
renderYear and renderYearFooter options can be used for customizing the header and footer.
jsxconst yearView = React.useMemo(() => {
return {
timeline: {
type: 'year',
resolutionHorizontal: 'year',
size: 6
}
};
}, []);
const getEventOccurrence = React.useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
var eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const 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 / myResources.length).toFixed(0);
}
return occuppancy;
}
const renderCustomYear = (args) => {
return <div className={'md-date-header-year md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('YYYY', args.date)}
</div>
}
const renderCustomYearFooter = (args) => {
return <div className="md-date-footer">{getOccuppancy(args.events)} %</div>;
}
return <Eventcalendar
view={yearView}
renderYear={renderCustomYear}
renderYearFooter={renderCustomYearFooter}
/>
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;
}

import { Eventcalendar, formatDate, setOptions } from '@mobiscroll/react';
import { useCallback, useMemo } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
function App() {
const hourView = useMemo(
() => ({
timeline: {
type: 'day',
},
}),
[],
);
const hourlyEvents = useMemo(
() => [
{
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 dayView = useMemo(
() => ({
timeline: {
type: 'month',
},
}),
[],
);
const dailyEvents = useMemo(
() => [
{
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 weekView = useMemo(
() => ({
timeline: {
type: 'week',
resolutionHorizontal: 'week',
size: 6,
},
}),
[],
);
const weeklyEvents = useMemo(
() => [
{
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 monthView = useMemo(
() => ({
timeline: {
type: 'month',
resolutionHorizontal: 'month',
size: 6,
},
}),
[],
);
const monthlyEvents = useMemo(
() => [
{
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 quarterView = useMemo(
() => ({
timeline: {
type: 'year',
resolutionHorizontal: 'quarter',
size: 1,
},
}),
[],
);
const quarterEvents = useMemo(
() => [
{
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 yearView = useMemo(
() => ({
timeline: {
type: 'year',
resolutionHorizontal: 'year',
size: 6,
},
}),
[],
);
const yearlyEvents = useMemo(
() => [
{
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 = useMemo(
() => [
{
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',
},
],
[],
);
const getEventOccurrence = useCallback((events) => {
let eventOccurrence = 'none';
if (events) {
const eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const getOccuppancy = useCallback(
(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).toFixed(0);
}
return occuppancy;
},
[myResources.length],
);
const renderCustomHour = useCallback(
(args) => (
<div className={'md-date-header md-date-header-hour md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('h:mm A', args.date)}
</div>
),
[getEventOccurrence],
);
const renderCustomHourFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
const renderCustomDay = useCallback(
(args) => {
const date = args.date;
return (
<div className={'md-date-header md-date-header-events-' + getEventOccurrence(args.events)}>
<div className="md-date-header-day-name">{formatDate('DDD', date)}</div>
<div className="md-date-header-day-nr">{formatDate('DD', date)}</div>
</div>
);
},
[getEventOccurrence],
);
const renderCustomDayFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
const renderCustomWeek = useCallback(
(args) => (
<div className={'md-date-header md-date-header-week md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM DD', args.startDate) + ' - ' + formatDate('MMM DD', args.endDate)}
</div>
),
[getEventOccurrence],
);
const renderCustomWeekFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
const renderCustomMonth = useCallback(
(args) => (
<div className={'md-date-header md-date-header-month md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM', args.date)}
</div>
),
[getEventOccurrence],
);
const renderCustomMonthFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
const renderCustomQuarter = useCallback(
(args) => (
<div className={'md-date-header md-date-header-quarter md-date-header-events-' + getEventOccurrence(args.events)}>
Quarter {args.date.getMonth() / 3 + 1}
</div>
),
[getEventOccurrence],
);
const renderCustomQuarterFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
const renderCustomYear = useCallback(
(args) => (
<div className={'md-date-header md-date-header-year md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('YYYY', args.date)}
</div>
),
[getEventOccurrence],
);
const renderCustomYearFooter = useCallback(
(args) => <div className="md-date-footer">{getOccuppancy(args.events)} %</div>,
[getOccuppancy],
);
return (
<div className="md-date-header-template">
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Hourly header template</div>
<Eventcalendar
view={hourView}
data={hourlyEvents}
resources={myResources}
renderHour={renderCustomHour}
renderHourFooter={renderCustomHourFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Daily header template</div>
<Eventcalendar
view={dayView}
data={dailyEvents}
resources={myResources}
renderTimelineDay={renderCustomDay}
renderDayFooter={renderCustomDayFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Weekly header template</div>
<Eventcalendar
view={weekView}
data={weeklyEvents}
resources={myResources}
renderWeek={renderCustomWeek}
renderWeekFooter={renderCustomWeekFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Monthly header template</div>
<Eventcalendar
view={monthView}
data={monthlyEvents}
resources={myResources}
renderMonth={renderCustomMonth}
renderMonthFooter={renderCustomMonthFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Quarterly header template</div>
<Eventcalendar
view={quarterView}
data={quarterEvents}
resources={myResources}
renderQuarter={renderCustomQuarter}
renderQuarterFooter={renderCustomQuarterFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Yearly header template</div>
<Eventcalendar
view={yearView}
data={yearlyEvents}
resources={myResources}
renderYear={renderCustomYear}
renderYearFooter={renderCustomYearFooter}
/>
</div>
</div>
);
}
export default App;
import {
Eventcalendar,
formatDate,
// MbscCalendarDayData,
MbscCalendarEvent,
MbscEventcalendarView,
MbscResource,
setOptions ,
} from '@mobiscroll/react';
import { FC, useCallback, useMemo } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
const App: FC = () => {
const hourView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'day',
},
}),
[],
);
const hourlyEvents = useMemo<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 dayView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'month',
},
}),
[],
);
const dailyEvents = useMemo<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 weekView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'week',
resolutionHorizontal: 'week',
size: 6,
},
}),
[],
);
const weeklyEvents = useMemo<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 monthView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'month',
resolutionHorizontal: 'month',
size: 6,
},
}),
[],
);
const monthlyEvents = useMemo<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 quarterView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'year',
resolutionHorizontal: 'quarter',
size: 1,
},
}),
[],
);
const quarterEvents = useMemo<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 yearView = useMemo<MbscEventcalendarView>(
() => ({
timeline: {
type: 'year',
resolutionHorizontal: 'year',
size: 6,
},
}),
[],
);
const yearlyEvents = useMemo<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 = useMemo<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',
},
],
[],
);
const getEventOccurrence = useCallback((events: MbscCalendarEvent[]) => {
let eventOccurrence = 'none';
if (events) {
const eventNr = events.length;
if (eventNr === 0) {
eventOccurrence = 'none';
} else if (eventNr === 1) {
eventOccurrence = 'one';
} else if (eventNr < 4) {
eventOccurrence = 'few';
} else {
eventOccurrence = 'more';
}
}
return eventOccurrence;
}, []);
const getOccuppancy = (events: MbscCalendarEvent[]) => {
let occuppancy = 0;
if (events) {
let resourceIds: Array<number> = [];
let nr = 0;
for (const event of events) {
if (resourceIds.indexOf(event.resource as number) < 0) {
nr++;
resourceIds = [...resourceIds, event.resource as number];
}
}
occuppancy = +((nr * 100) / myResources.length).toFixed(0);
}
return occuppancy;
};
const renderCustomHour = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className={'md-date-header md-date-header-hour md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('h:mm A', args.date)}
</div>
);
const renderCustomHourFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
const renderCustomDay = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => {
const date = args.date;
return (
<div className={'md-date-header md-date-header-events-' + getEventOccurrence(args.events)}>
<div className="md-date-header-day-name">{formatDate('DDD', date)}</div>
<div className="md-date-header-day-nr">{formatDate('DD', date)}</div>
</div>
);
};
const renderCustomDayFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
const renderCustomWeek = (args: { date: Date; events: Array<MbscCalendarEvent[]>; startDate: Date; endDate: Date }) => (
<div className={'md-date-header md-date-header-week md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM DD', args.startDate) + ' - ' + formatDate('MMM DD', args.endDate)}
</div>
);
const renderCustomWeekFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
const renderCustomMonth = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className={'md-date-header md-date-header-month md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('MMM', args.date)}
</div>
);
const renderCustomMonthFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
const renderCustomQuarter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className={'md-date-header md-date-header-quarter md-date-header-events-' + getEventOccurrence(args.events)}>
Quarter {args.date.getMonth() / 3 + 1}
</div>
);
const renderCustomQuarterFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
const renderCustomYear = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className={'md-date-header md-date-header-year md-date-header-events-' + getEventOccurrence(args.events)}>
{formatDate('YYYY', args.date)}
</div>
);
const renderCustomYearFooter = (args: { date: Date; events: Array<MbscCalendarEvent[]> }) => (
<div className="md-date-footer">{getOccuppancy(args.events)} %</div>
);
return (
<div className="md-date-header-template">
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Hourly header template</div>
<Eventcalendar
view={hourView}
data={hourlyEvents}
resources={myResources}
renderHour={renderCustomHour}
renderHourFooter={renderCustomHourFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Daily header template</div>
<Eventcalendar
view={dayView}
data={dailyEvents}
resources={myResources}
renderTimelineDay={renderCustomDay}
renderDayFooter={renderCustomDayFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Weekly header template</div>
<Eventcalendar
view={weekView}
data={weeklyEvents}
resources={myResources}
renderWeek={renderCustomWeek}
renderWeekFooter={renderCustomWeekFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Monthly header template</div>
<Eventcalendar
view={monthView}
data={monthlyEvents}
resources={myResources}
renderMonth={renderCustomMonth}
renderMonthFooter={renderCustomMonthFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Quarterly header template</div>
<Eventcalendar
view={quarterView}
data={quarterEvents}
resources={myResources}
renderQuarter={renderCustomQuarter}
renderQuarterFooter={renderCustomQuarterFooter}
/>
</div>
<div className="mbsc-form-group">
<div className="mbsc-form-group-title">Yearly header template</div>
<Eventcalendar
view={yearView}
data={yearlyEvents}
resources={myResources}
renderYear={renderCustomYear}
renderYearFooter={renderCustomYearFooter}
/>
</div>
</div>
);
};
export default App;
.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;
}