Timeline
Use the Timeline view which features a horizontally scrollable view with multiple resource support for day, week, work-week, month and year view with built in templating, drag & drop and more.
Overview
This Timeline view displays a timeline with its related events. You can render the times/days horizontally and the resources vertically. The Timeline can easily accommodate a large number of resources thanks to the vertical scroll that is easy to understand for users. This plays well on larger screens and in landscape containers. Work hours and work days along with disabled time-spans, breaks can be added. Use it to for advanced tasks with built-in drag & drop.
By default the Timeline rows will have variable height and will expand to accommodate the displayed events. But, this can be changed by the rowHeight property of the Timeline view option. If it is set to equal, the rows will have equal heights, and overlapping events will be distributed evenly to fit in the row.
Also, the eventDisplay property transforms the event display into a daily listing mode. This view represents a daily summary rather than an hour-by-hour layout.
The capabilities like recurring events, all-day, multi-day events, responsiveness are supported by the Timeline.

Showing the Timeline
Configuring the view
The Timeline view can be configured through the view option. Below are listed the timeline object properties which can help you fine-tune this view.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myViewOptions = {
timeline: {
maxEventStack: 2,
eventDisplay: 'fill',
resolutionHorizontal: 'day',
type: 'month',
resourceReorder: true
}
};
return <Eventcalendar view={myViewOptions} />
}
columnWidth
MbscTimelineColumnWidth
Sets the width of grid columns in the timeline to one of the predefined column widths. Possible values and their corresponding widths:
xxsmall: 1.5emxsmall: 3emsmall: 4.5emmedium: 6emlarge: 7.5emxlarge: 9emxxlarge: 10.5emxxxlarge: 12em;
When not defined, the column width will be set automatically based on the view type and size.
You can customize the predefined column widths using CSS to fit your layout needs.
Default value: undefined
currentTimeIndicator
boolean
Show or hide the current time indicator.
Defaults to true, when the horizontal resolution is less than a day.
endDay
number
Specifies the last visible weekday of the view. Sunday is 0, Monday is 1, etc.
Days outside of the startDay and endDay range will not be visible.
Default value: 6
endTime
string
Set the end time of timeline days. Hours, minutes and an optional positive day offset can be specified in the same string.
- Standard format: 'HH:MM' (e.g.,
'18:30'). - Offset format (extends the view N days after - supported only for single day view): 'HH:MM+N' (e.g.,
'08:00+1').
Default value: '24:00'
eventDisplay
"fill" | "exact"
Specifies how events are displayed.
- If set to
'exact', events are displayed according to their start and end times. - If set to
'fill', events cover the entire cell.
Default value: 'exact'
eventHeight
"variable" | "equal"
Specifies wether the height of the events is equal or variable.
Default value: 'equal'
eventList (deprecated)
boolean
DEPRECATED: Use the eventDisplay property instead.
If true, transforms the layout into a summary view.
The events are listed in the appropriate cell one after the other.
Default value: false
hideEmptyRows
boolean
Hide the empty rows.
Parent resources will always be displayed, even when empty.
Default value: false.
hideInvalidRows
boolean
Hide the fully invalid rows.
Parent resources will always be displayed, even when fully invalid, unless resolutionVertical: 'day' is used.
Default value: false.
maxEventStack
number | "all"
Limit the number of displayed events. When the number of overlapping events reaches the specified value, a "more" button will be displayed which opens a popover showing the rest of the events.
- If it is a
number, it specifies how many events will be displayed before the "more" button appears. - If set to
'all', all events will be displayed.
Default value: 'all'
resolutionHorizontal
"day" | "hour" | "month" | "year" | "week" | "quarter"
Sets the horizontal resolution of the timeline.
In case of hourly resolution, the columns can be split to minutes (1, 5, 15, 20, 30) or merge to multiple
hours (2, 3, 4, 6, 8, 12) using the timeCellStep and timeLabelStep properties.
Default value: 'hour'
resolutionVertical
"day"
Sets the vertical time unit of the timeline to days. When set to 'day', the days will be rendered on the vertical axis, while the hours of the day will be displayed on the horizontal axis.
Default value: undefined
resourceReorder
boolean
Specifies whether the resource can be dragged and reordered. A drag handle icon will appear in front of the resource name, serving as the point of interaction to drag and reposition the resource.
Default value: false
rowHeight
"variable" | "equal"
Controls the height of the timeline rows.
By default rows will have variable height and will expand to accommodate the displayed events.
If it is set to 'equal', the rows will have equal heights.
Default value: 'variable'
size
number
Specifies the number of displayed years, months, weeks or days.
Default value: 1
startDay
number
Specifies the first visible weekday of the view. Sunday is 0, Monday is 1, etc.
Days outside of the startDay and endDay range will not be visible.
Should not be mistaken for the firstDay option,
which sets the first day of the week, and, if not set, is defined by the localization.
Default value: 0
startTime
string
Set the start time of timeline days. Hours, minutes and an optional negative day offset can be specified in the same string.
- Standard format: 'HH:MM' (e.g.,
'09:30'). - Offset format (initiates the view N days prior - supported only for single day view): 'HH:MM-N' (e.g.,
'20:00-1').
Default value: '00:00'
timeCellStep
number
Specifies the step of the grid cells in minutes. Supported values: 1, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 480, 720, 1440
Default value: 60
timeLabelStep
number
Specifies the step of the time labels in minutes. Supported values: 1, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 480, 720, 1440.
Default value: 60
type
"day" | "month" | "year" | "week"
Specifies the timeline type.
Default value: 'week'
virtualScroll
boolean
Enable or disable virtual scroll.
Default value: true
weekNumbers
boolean
Show or hide week numbers.
Default value: false
zoomLevels
{ [key:string]: MbscTimelineZoomLevel }
Defines configuration options for multiple zoom levels for the timeline view. Each zoom level can specify its own properties for displaying a custom layout.
Use the zoomLevel option to select the current zoom level.
Available properties:
sizeresolutionHorizontalresolutionVerticalcolumnWidthcurrentTimeIndicatorendDayendTimeeventListstartDaystartTimetimeCellSteptimeLabelStepweekNumberstype
Default value: undefined
Event slots
Besides the resources which are grouping data for the whole date range, slots introduce a horizontal daily grouping in case of the Timeline view. Slots can be used alongside resources.
The renderSlot function can be used to customize the slot template of the Timeline view.
When slots are used the Timeline view will display in daily listing mode and only the dragToMove event iteraction will be available. The dragToCreate and dragToResize interactions will be truned off.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myShifts: [
{
id: 1,
name: "Morning shift",
},
{
id: 2,
name: "Afternoon shift",
},
];
return <Eventcalendar slots={myShifts} />
}

Column width
The columnWidth option in the timeline view allows you to control the width of the timeline columns. It supports the following predefined sizes: xxsmall, xsmall, small, medium, large, xlarge, xxlarge, and xxxlarge.
Here are the default sizes and their corresponding widths:
.mbsc-timeline-column-xxs {
width: 1.5em; // 24px
}
.mbsc-timeline-column-xs {
width: 3em; // 48px
}
.mbsc-timeline-column-s {
width: 4.5em; // 72px
}
.mbsc-timeline-column-m {
width: 6em; // 96px
}
.mbsc-timeline-column-l {
width: 7.5em; // 120px
}
.mbsc-timeline-column-xl {
width: 9em; // 144px
}
.mbsc-timeline-column-xxl {
width: 10.5em; // 168px
}
.mbsc-timeline-column-xxxl {
width: 12em; // 192px
}
To specify the columnWidth in your view configuration, include it as part of the timeline view options:
view: {
timeline: {
columnWidth: 'large'
}
}
The predefined sizes correspond to specific default widths, but you can override them using CSS:
.mbsc-timeline-column-l {
width: 50px;
}
You need to apply these rules after the mobiscroll default rules, otherwise the default rules will take precedence over them.
Shifted days
Shifted views can be implemented by extending the daily timeline view with hours from the previous or next calendar days using the startTime and endTime properties with a day-offset format.

Shift Start Time (Previous Day Offset)
Use a negative day offset (HH:MM-D) to show hours from the previous day (e.g., '20:00-1').
Shift End Time (Next Day Offset)
Use a positive day offset (HH:MM+D) to extend the view into the next day (e.g., '06:00+1').
view: {
timeline: {
type: 'day',
resolutionHorizontal: 'hour',
resolutionVertical: 'day',
// Starts the view at 20:00 on the previous day
startTime: '20:00-1',
// Ends the view at 06:00 on the next day
endTime: '06:00+1'
}
}
The day-offset feature is strictly dependent on the type: 'day' and the default hourly resolutionHorizontal setting. This can be efficiently combined with resolutionVertical: 'day' of any size.
Resources
Resource grouping and hierarchy
The Timeline view supports resource hierarchy. Hierarchy groups can be defined with the children property of the resource object. Child objects are also resources and have the same properties, thus they can also have children.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myResources = [{
name: 'Site 1',
children: [{
name: 'Building 1'
children: [{
name: 'Room 1'
}, {
name: 'Room 2'
}]
}, {
name: 'Building 2'
}]
}, {
name: 'Site 2',
children: [{
name: 'Building A'
}]
}];
return <Eventcalendar resources={myResources} />
}
By default every resource group will be displayed and this can be modified with the collapsed attribute of the parent objects.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myResources = [{
name: 'Main Building',
id: 'main',
description: 'Used the most for scheduling'
collapsed: true,
children: [{
name: 'Big conf. room'
id: 'bfg',
}, {
name: 'Smaller conf. room'
id: 'sfg',
}]
}, {
name: 'Secondary Building',
id: 'sec',
description: 'For smaller, less important meetings'
collapsed: false,
children: [...]
}, {
name: 'Long forgotten Cave',
id: 'cave',
description: 'Where developers used to work'
collapsed: false,
}];
return <Eventcalendar resources={myResources} />
}
Both parent and child rows can contain events and events can be moved between any rows.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myResources = [{
name: 'Main Building',
id: 'main',
children: [{
name: 'Big conf. room'
id: 'bfg',
}]
}, {
name: 'Secondary Building',
id: 'sec',
}];
const myEvents: [
{ title: 'Open day celebration', resource: 'main', date: '2023-08-24'},
{ title: 'Monthly staff meeting', resource: 'bfg', start: '2023-08-01T11:00', end: '2023-08-01T11:00' },
{ title: 'Weekly chit-chat', resource: 'sec', start: '2023-08-02T09:00', end: '2023-08-02T09:40' },
...
];
return <Eventcalendar resources={myResources} data={myEvents} />
}
Child or parent rows can be disabled by creating an invalid rule which repeats daily and it is tied to the specific resources. Example:
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myInvalid = [
{
recurring: { repeat: "daily" },
resource: [
/* resource id(s) */
],
},
];
return <Eventcalendar invalid={myInvalid} />
}
Resource order
The initial order in which the resources appear on the timeline follows the order of the array passed to the component. If the initial order needs to be changed, sort the resource array before passing it to the event calendar.
For dynamic sorting during runtime, sort the resource array and pass the updated array to the calendar.
Resources can be reordered directly through the UI by enabling the resourceReorder option in the view configuration. When enabled, a drag handle icon will appear before each resource, serving as the point of interaction to drag and reposition the resource.
After a resource is dragged and dropped to a new position, the onResourceOrderUpdate lifecycle event is triggered. To make specific resources non-draggable, set the reorder property of the corresponding resource object to false;
Resource external drag and drop
You can drag and drop resources into or out of the timeline view, allowing for easy organization and adjustments.
Targeting the timeline
To allow external resources to be dragged into your timeline, first set the the externalResourceDrop option to true. As a second step, you'll need to create your external draggable element and pass a skeleton resource definition through the dragData option. Make sure to also set type="resource" on the draggable element so the timeline correctly identifies it as a resource.
The timeline as a source
Resources can be dragged out of the timeline and dropped onto another instance of the Timeline or any Dropcontainer. To enable this behavior, you'll need to set the externalResourceDrag option to true.
When a resource is dragged out of the timeline, the onResourceDragLeave lifecycle event is triggered. A visual clone of the resource is shown to indicate the movement. If the resource is dropped into an external drop container or another timeline, it gets removed from the original timeline. This action also triggers the onResourceDelete and onResourceDeleted lifecycle events.
When a resource is dragged into the timeline, the onResourceDragEnter lifecycle event is triggered. If the resource is dropped, the onResourceCreate and onResourceCreated events will be fired, finalizing the addition.
Resource column width
The width of the resources column on the Timeline view is fixed. It can be overwritten from CSS using the following rule:
.mbsc-timeline-resource-col {
width: 200px;
}
The width of the resource column adjusts as resources are expanded or collapsed. The default increment step can be modified with a CSS rule:
.mbsc-timeline-resource-depth-step {
width: 20px;
}
If the step adjustment is not needed, it can disabled by setting the value to width: 0;.
Resource row height
There are three CSS classes which can be used for changing the height of resource rows:
-
For setting the resource row heights in general, you can use the
.mbsc-timeline-rowclass..mbsc-timeline-row {height: 80px;} -
For setting the height of the parent resources, you can use the
.mbsc-timeline-parentclass..mbsc-timeline-parent {height: 30px;}infoThere's minimum height of the rows which can only be decreased if the event creation is disabled on the relevant resource. You can prevent event creation by using the
eventCreationproperty of the theresourcesoption. -
For customizing the remaining empty space below the events, you can use the
.mbsc-timeline-row-gutterclass..mbsc-timeline-row-gutter {height: 6px;}
Hide empty resources
Rows without any events can be hidden by setting hideEmptyRows to true under the view configuration.
Parent resources will always be displayed, even when empty.
If resolutionVertical is set to 'day' and all resources for a given day are empty, the entire day will be hidden.
Hide invalid resources
Fully invalid rows can be hidden by setting hideInvalidRows to true under the view configuration.
A resource row is considered fully invalid if it contains invalid periods defined with allDay, date values,
or a single time range that covers a full day or multiple days.
Parent resources will always be displayed, even when fully invalid.
If resolutionVertical is set to 'day' and all resources for a given day are fully invalid, the entire day will be hidden.
Virtual scroll
Virtual scroll is a performance optimization that ensures smooth scrolling and fast rendering when displaying large numbers of events or resources in the timeline.
The timeline view is virtualized, meaning its markup is dynamically generated and managed as needed. As you scroll vertically or horizontally, the component updates what's visible in real time, only rendering the elements that appear in the viewport. This approach dramatically improves performance for large datasets: events and resources are not all loaded into memory at once, keeping the interface fast and responsive.
When virtual scroll is enabled, the timeline calculates which items should be displayed based on the current scroll position.
Only the visible portion of the view is rendered, while non-visible parts are skipped until they come into view.
Scrolling triggers the onVirtualLoading lifecycle event, which can be used to load data incrementally during scrolling, instead of fetching everything upfront.
You can see an example of this pattern in the Load resources on scroll demo.
The calendar needs to be to placed inside a container which has a height. This can be either a fixed height, a height in percentage, or a flex height. When the calendar is placed directly in a container with a fixed height, it will work out of the box. If the height of the container is specified in percentage, e.g. you'd like to fill the full page height, you need to make sure that all parent elements also have height: 100% specified, up until the body and html elements, or until the closest parent which has a fixed height. If the container is inside a parent with flex layout, it will also work out of the box.
In some cases, you may want to disable virtual scroll, for example:
- When working with a small dataset that doesn't benefit from virtualization.
- When you need to access or manipulate all DOM elements at once.
To disable it, set virtualScroll to false.
Event connections
The Timeline view can display connections between events. Events will be linked with lines and additionally arrows can be displayed to illustrate the direction of the connection. Events can have multiple connections simultaneously. Connections can be specified with the connections option.

Event order
The rendered event order is determined by the following two concepts:
- Event data order
- Event layout
The combination of these concepts results in the final rendered event order.
Event data order
The sequence in which events are processed before being passed to the layout algorithm. The default ordering rules are as follows:
- All-day events are placed at the top.
- Non-all-day events follow, sorted by their start times.
- Events with the same start time are further ordered alphabetically by their titles.
This default order can be modified using the order property in the event event data. The order property takes precedence over the default rules. If two events have the same order value, the default rules apply. For more complex ordering requirements, the eventOrder option can be used. This option accepts a function that compares two events and returns an order (-1 or 1).
Event layout
The event layout process determines the visual positioning and dimensions of events. This is a built-in functionality and cannot be altered externally. The layout algorithm processes the sorted event list and calculates each event's position and size. The algorithm follows these steps:
- The first event is placed in the first position of the event track.
- If two or more events overlap in their start/end times, the later event is placed in the next event track, positioned below to the previous event.
- If a subsequent event does not overlap with any already added events, it is placed back in the first event track.
- This process continues until all events are positioned within their respective rows.
Responsiveness
The Timeline is fully responsive. It adapts to the available space and fills the screen to look good everywhere. While you don't have to worry about the width the height can be manually adjusted with the height option. This specifies different options for different container widths, in a form of an object, where the keys are the name of the breakpoints, and the values are objects containing the options for the given breakpoint.
Use the responsive option to configure how the calendar behaves on different sized screens. The responsive option is equipped with five breakpoints:
xsmall(up to 575px),small(up to 767px),medium(up to 991px),large(up to 1199px),xlarge(from 1200px).
Also, custom breakpoints can be added if necessary:
my-custom-breakpoint: { breakpoint: 600 }(from 600px up to the next breakpoint).
The available width is queried from the container element of the component and not the browsers viewport like in css media queries.
import { Eventcalendar } from '@mobiscroll/react';
import '@mobiscroll/react/dist/css/mobiscroll.min.css';
function App() {
const myResponsive = {
xsmall: {
view: { timeline: { type: 'day', size: 2 }}
},
medium: {
view: {
timeline: { type: 'week' }
}
},
custom: { // Custom breakpoint, you can use multiple if needed, but each must have a unique name.
breakpoint: 1000,
view: { timeline: { type: 'month' }}
}
};
return <Eventcalendar responsive={myResponsive} />
}

Zoom Levels
The timeline view allows you to define and use multiple zoom levels, making it easy to switch between different time scales. You can select a specific zoom level to focus on the desired level of detail.
Configuring Zoom Levels
Zoom levels are set up in the zoomLevels property of the timeline view. Each zoom level can have its own options for customizing the timeline's layout and behavior. You can specify a zoom level using number or string-based keys, and the corresponding view options will be applied.
Available options
- type
- size
- resolutionHorizontal
- resolutionVertical
- columnWidth
- currentTimeIndicator
- startDay - endDay
- startTime - endTime
- timeCellStep
- timeLabelStep
- weekNumbers
Example Configuration
view: {
timeline: {
zoomLevels: {
-4: { type: 'year', size: 6, resolutionHorizontal: 'year' },
-3: { type: 'month', size: 6, resolutionHorizontal: 'month' },
-2: { type: 'week', size: 5, resolutionHorizontal: 'week' },
-1: { type: 'week', size: 5, resolutionHorizontal: 'day' },
0: { type: 'week', size: 5, resolutionHorizontal: 'day', columnWidth: 'large' },
1: { type: 'week', size: 5, resolutionHorizontal: 'day', columnWidth: 'xlarge' },
2: { type: 'day', size: 3, resolutionHorizontal: 'hour', timeCellStep: 360, timeLabelStep: 360 },
3: { type: 'day', size: 3, resolutionHorizontal: 'hour', timeCellStep: 180, timeLabelStep: 360 },
4: { type: 'day', size: 3, resolutionHorizontal: 'hour', timeCellStep: 30, timeLabelStep: 60 },
}
}
},
zoomLevel: 0
Setting the Active Zoom Level
The zoomLevel option determines which zoom level is currently active. When set, the timeline automatically applies the corresponding settings from zoomLevels.
To ensure the calendar view is correctly aligned when zooming, the getViewDate() method is used to retrieve the current middle date of the visible calendar view. Based on the zoom level, the refDate is set to a corresponding date, ensuring that the view date can always be scrolled to the center.
Learn how to implement and adjust zoom levels by checking this example.
Templating
The display of Timeline can be customized with different render functions.
The cell
Use the renderCell option to fully customize the Timeline cells. Customize how the cell look and what they show. The renderer function gets an object with properties like date, events, colors, invalids, resource, and slot which can be used to display custom content.
Since cells are rendered frequently while scrolling, keep the customization lightweight for best performance.
Check out how you can style the cell in this example or just play with the slider below to see the differences.


The resource, their header and footer
There are three approaches you can take:
- Use the renderResource option to customize the resource template of the Timeline. Customize how the resource headers look and what they show. Utilize properties passed in the resources array. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well.
- Customize the empty cell content above the resource column with the renderResourceHeader option. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well.
- Or if you want to customize the empty cell content below the resource column you can achieve this with the renderResourceFooter option. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well. This element only renders for the Timeline view, if the renderDayFooter option is present.
Check out how you can style these resource parts in this example or just play with the slider below to see the differences.


The sidebar, their header and footer
Besides the resource template, an additional sidebar can be rendered on the opposite end of the row and there are three approaches you can take:
- Use the renderSidebar option to render a custom sidebar on the right side of the Timeline. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well. The template will receive the resource object as data. This data can be used to show resource specific things on the sidebar.
- Customize the empty cell content above the sidebar column with the renderSidebarHeader option. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well. This element only renders for the Timeline view, if the renderSidebar option is present.
- Or if you want to customize the empty cell content below the sidebar column you can achieve this with the renderSidebarFooter option. It takes a function that should return the desired markup. In the returned markup, you can use custom html as well. This element only renders for the Timeline view, if the renderSidebar option is present.
Check out how you can style the sidebar parts in this example or just play with the slider below to see the differences.


The date header and footer
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.
Depending on the resolution, the first Timeline row under the navigation header can show a line for each of the following:
Hourly header/footer template
With an hourly (or sub-hourly) resolution the renderHour and renderHourFooter options can be used for customizing the header and footer.


Daily header/footer template
With a daily resolution, the renderTimelineDay and renderDayFooter options can come in handy for customizing the header and footer.


Weekly header/footer template
When the resolution is weekly, the renderWeek and renderWeekFooter options can be used.


Monthly header/footer template
When displaying multiple months, the renderMonth and renderMonthFooter options can be used for customizing the header and footer per month.


Quarter header/footer template
When displaying multiple quarters, the renderQuarter and renderQuarterFooter options can be used for customizing the header and footer per quarter.


Yearly header/footer template
With a yearly resolution, the renderYear and renderYearFooter options can be used for customizing the header and footer.


Check out how you can style the date header and footer in this example or just play with the sliders above to see the differences.
The event and buffer areas
You can use the renderTimelineEvent option to customize the events that appear on the scheduler. It should return the markup of the event. The Eventcalendar will take care of the positioning, but anything else you want to show is up to you - like a title, description, color the background or show any content.
The buffers can be customized through the renderBufferBefore and renderBufferAfter options. These can help you visualise delays or added minutes for tasks. For example travel time for meetings/appointments, check in/check out for flights.
Check out how you can style the events and the buffer areas in this example or just play with the slider below to see the differences.


The event content
If you are looking to customize only the content and don't want to bother with the styling of the event, you can use the renderTimelineEventContent option. Mobiscroll will position the event to the right place and will render essential information like the color of the event, the time and if it's an all day event or not. The title, description and any other fields you want to show (like participants or an avatar) will be coming from your custom function.
Check out how you can style the event content in this example or just play with the slider below to see the differences.

