# Event Timeline

> Build a resource-row, Gantt-style timeline in dash-mui-scheduler with EventTimeline — resources as rows, multi-day allocation bars and zoom presets.

**Site index:** [https://muischeduler.2plot.dev/llms.txt](https://muischeduler.2plot.dev/llms.txt) — every page on this site, as Markdown.  
**Network index:** [https://2plot.dev/llms.txt](https://2plot.dev/llms.txt) — The 2plot network; start here to discover sibling sites.  
**Sibling sites:** 13 more in The 2plot network — listed in the site index above.  
**Sitemap:** https://muischeduler.2plot.dev/sitemap.xml  


---



### Event Timeline (Premium)

`dms.EventTimeline` is a resource-row, Gantt-style timeline. Where the calendar
lays events out on a day/week/month grid, the timeline turns each **resource
into a row** and draws every event as a horizontal allocation bar on its row,
across a configurable zoom `preset`. It wraps the MUI X `EventTimelinePremium`
and, like every component here, is currently **beta**.


    `EventTimeline` requires a MUI X Premium license key. Pass it via
    `licenseKey=os.environ.get("MUI_X_LICENSE_KEY", "")`. Without a valid key
    the timeline still renders and stays fully interactive, but a MUI watermark
    is drawn over it. That is expected — supply a real key to remove it.

The data boundary is the same as the calendar. `events` is a list of plain
dicts and is **both input and output**: the component writes the full array
back on every create, move, resize or delete. Dates are ISO **strings** (for
example `"2024-01-15T09:00:00"` for wall time, or a trailing `Z` for UTC),
never Python `datetime` objects. The read-only `lastAction` output is
`{type, event, event_timestamp}`, where `type` is one of `create`, `update`,
`delete`, `move`, `resize` or `change`.

### Resources as rows

A timeline needs `resources` — they are the rows. Each resource is a dict with
at least an `id` and `title`, plus an optional `eventColor`:

```python
resources = [
    {"id": "team-a", "title": "Team A", "eventColor": "blue"},
    {"id": "team-b", "title": "Team B", "eventColor": "green"},
]
```

Each event names its row through the `resource` key, which must match one of
the resource ids. On the timeline events should almost always have a
`resource` — `shouldEventRequireResource` defaults to `True` here. The column
that lists the row labels is titled with `resourceColumnLabel` (for example
`"Team"`). The example below places several multi-day allocation bars across
three rows and opens at the `dayAndWeek` zoom level.



```python
# File: docs/event_timeline/timeline_basic.py

import os

from dash import html
import dash_mui_scheduler as dms

# On a timeline, resources are the ROWS. Each event sits on the row whose id
# matches its `resource` key. Resources carry their own eventColor.
resources = [
    {"id": "team-a", "title": "Team A", "eventColor": "blue"},
    {"id": "team-b", "title": "Team B", "eventColor": "green"},
    {"id": "team-c", "title": "Team C", "eventColor": "orange"},
]

# Allocation bars span days. Dates are ISO strings (never Python datetime),
# and `events` is both input and output — the component writes the full array
# back on every create, move, resize or delete.
events = [
    {
        "id": "alloc-1",
        "title": "Discovery",
        "start": "2024-01-15T09:00:00",
        "end": "2024-01-17T17:00:00",
        "resource": "team-a",
    },
    {
        "id": "alloc-2",
        "title": "Build phase",
        "start": "2024-01-18T09:00:00",
        "end": "2024-01-23T17:00:00",
        "resource": "team-a",
    },
    {
        "id": "alloc-3",
        "title": "API integration",
        "start": "2024-01-16T09:00:00",
        "end": "2024-01-20T17:00:00",
        "resource": "team-b",
    },
    {
        "id": "alloc-4",
        "title": "QA & hardening",
        "start": "2024-01-22T09:00:00",
        "end": "2024-01-25T17:00:00",
        "resource": "team-b",
    },
    {
        "id": "alloc-5",
        "title": "Launch prep",
        "start": "2024-01-19T09:00:00",
        "end": "2024-01-24T17:00:00",
        "resource": "team-c",
    },
]

component = html.Div(
    dms.EventTimeline(
        id="event_timeline-basic",
        licenseKey=os.environ.get("MUI_X_LICENSE_KEY", ""),
        events=events,
        resources=resources,
        resourceColumnLabel="Team",
        defaultPreset="dayAndWeek",
        defaultVisibleDate="2024-01-15",
        height=400,
    )
)
```


### Zoom presets

A preset controls how much time one screen of the timeline spans and how the
header is divided. There are five: `dayAndHour` (the default), `dayAndMonth`,
`dayAndWeek`, `monthAndYear` and `year`. Two props drive this:

- `defaultPreset` / `preset` — the active zoom level. `defaultPreset` is
  uncontrolled (set it once at load); `preset` is controlled **in + out**, so a
  callback can both set it and read the user's changes back.
- `presets` — the list of presets offered in the timeline's own zoom switcher.

To drive the zoom from your own UI, wire a `dmc.SegmentedControl` to the
`preset` prop. Because `preset` is controlled in + out, the callback below sets
the zoom whenever the segmented control changes:

```python
@callback(
    Output("event_timeline-presets", "preset"),
    Input("event_timeline-presets-control", "value"),
)
def set_preset(value):
    return value
```



```python
# File: docs/event_timeline/timeline_presets.py

import os

from dash import Input, Output, callback
import dash_mantine_components as dmc
import dash_mui_scheduler as dms

# Rows.
resources = [
    {"id": "mixer", "title": "Mixer", "eventColor": "purple"},
    {"id": "studio", "title": "Studio", "eventColor": "teal"},
]

# A few multi-day allocations so the effect of each zoom preset is visible.
events = [
    {
        "id": "preset-1",
        "title": "Album mixdown",
        "start": "2024-01-15T10:00:00",
        "end": "2024-01-19T18:00:00",
        "resource": "mixer",
    },
    {
        "id": "preset-2",
        "title": "Tracking sessions",
        "start": "2024-01-16T09:00:00",
        "end": "2024-01-22T20:00:00",
        "resource": "studio",
    },
    {
        "id": "preset-3",
        "title": "Mastering",
        "start": "2024-01-23T10:00:00",
        "end": "2024-01-25T16:00:00",
        "resource": "mixer",
    },
]

# `preset` is controlled in + out: the SegmentedControl drives the zoom level.
# The five presets are dayAndHour, dayAndMonth, dayAndWeek, monthAndYear, year.
presets = ["dayAndHour", "dayAndWeek", "dayAndMonth", "monthAndYear", "year"]

component = dmc.Stack(
    [
        dmc.SegmentedControl(
            id="event_timeline-presets-control",
            data=[
                {"label": "Day / Hour", "value": "dayAndHour"},
                {"label": "Day / Week", "value": "dayAndWeek"},
                {"label": "Day / Month", "value": "dayAndMonth"},
                {"label": "Month / Year", "value": "monthAndYear"},
                {"label": "Year", "value": "year"},
            ],
            value="dayAndWeek",
        ),
        dms.EventTimeline(
            id="event_timeline-presets",
            licenseKey=os.environ.get("MUI_X_LICENSE_KEY", ""),
            events=events,
            resources=resources,
            resourceColumnLabel="Resource",
            presets=presets,
            preset="dayAndWeek",
            defaultVisibleDate="2024-01-15",
            height=400,
        ),
    ],
    gap="sm",
)


@callback(
    Output("event_timeline-presets", "preset"),
    Input("event_timeline-presets-control", "value"),
)
def set_preset(value):
    return value
```


### EventTimeline props

`EventTimeline` shares most of its props with the calendar (events, resources,
visibility, drag/resize flags, preferences, timezone) and adds the timeline
specifics: `resourceColumnLabel`, `preset` / `defaultPreset` and `presets`. It
needs a `licenseKey`.


#### `EventTimeline` props

| prop | type | description |
|---|---|---|
| `id` | string; optional | The id used to identify this component in Dash callbacks. |
| `areEventsDraggable` | boolean; optional | Allow drag-to-reschedule allocations. Default True. |
| `areEventsResizable` | boolean \| a value equal to: 'start', 'end'; optional | Allow resize (bool, or restrict to "start"/"end"). Default True. |
| `canDragEventsFromTheOutside` | boolean; optional | Allow external events to be dragged in. Default False. |
| `canDropEventsToTheOutside` | boolean; optional | Allow events to be dragged out of the timeline. Default False. |
| `className` | string; optional | CSS class applied to the wrapping div. |
| `defaultPreferences` | dict; optional | Uncontrolled initial preferences {ampm, weekStartsOn}. Default {ampm: True}. `defaultPreferences` is a dict with keys: - ampm (boolean; optional) - weekStartsOn (a value equal to: 0, 1, 2, 3, 4, 5, 6; optional) |
| `defaultPreset` | a value equal to: 'dayAndHour', 'dayAndMonth', 'dayAndWeek', 'monthAndYear', 'year'; optional | Uncontrolled initial preset. Default "dayAndHour". |
| `defaultVisibleDate` | string; optional | Uncontrolled initial visible date (ISO string). Default today. |
| `defaultVisibleResources` | dict; optional | Uncontrolled initial resource visibility map. Default {} (all visible). |
| `displayTimezone` | string; optional | Render timezone: IANA name, or "default"/"locale"/"UTC". Default "default". |
| `eventColor` | a value equal to: 'red', 'pink', 'purple', 'indigo', 'blue', 'teal', 'green', 'lime', 'amber', 'orange', 'grey'; optional | Default color palette for all events (overridable). Default "teal". |
| `eventCreation` | dict; optional | Configures event creation. `False` disables it; `True` enables defaults; an object sets {interaction, duration (minutes)}. `eventCreation` is a boolean \| dict with keys: - interaction (a value equal to: 'click', 'double-click'; optional) - duration (number; optional) |
| `eventDialogTopOffset` | number; optional | On desktop, inset the event drawer this many px from the top — e.g. set it to your fixed app header's height. Default 0. |
| `eventDialogVariant` | a value equal to: 'drawer', 'dialog'; default 'drawer' | How the event editor is presented. "drawer" (default) restyles the built-in dialog into a responsive frosted-glass drawer — right-anchored on desktop, an 88%-height bottom sheet on mobile (below `mobileBreakpoint`). "dialog" keeps the library's floating dialog. |
| `events` | list of dicts; optional | Allocation bars. Each event needs `id`, `title`, `start`, `end` (ISO strings) and usually a `resource` (the row it sits on). INPUT + OUTPUT. `events` is a list of dicts with keys: - id (string \| number; required) - title (string; required) - start (string; required) - end (string; required) - description (string; optional) - timezone (string; optional) - resource (string \| number; optional) - rrule (string \| dict; optional) - exDates (list of strings; optional) - allDay (boolean; optional) - readOnly (boolean; optional) - color (a value equal to: 'red', 'pink', 'purple', 'indigo', 'blue', 'teal', 'green', 'lime', 'amber', 'orange', 'grey'; optional) - draggable (boolean; optional) - resizable (boolean \| a value equal to: 'start', 'end'; optional) - className (string; optional) - extractedFromId (string \| number; optional) |
| `height` | number \| string; default 400 | Height of the wrapping container (the timeline fills it). Default 400. |
| `lastAction` | dict; optional | Convenience OUTPUT describing the most recent change to `events`. `lastAction` is a dict with keys: - type (string; optional) - event (dict; optional) - event_timestamp (number; optional) |
| `licenseKey` | string; optional | MUI X Premium license key (removes the watermark). |
| `localeText` | dict; optional | Override UI label strings (a partial map of translation keys). |
| `mobileBreakpoint` | number; default 768 | Width (px) below which the editor uses its mobile layout. Default 768. |
| `preferences` | dict; optional | Controlled preferences {ampm, weekStartsOn}. Also an OUTPUT. `preferences` is a dict with keys: - ampm (boolean; optional) - weekStartsOn (a value equal to: 0, 1, 2, 3, 4, 5, 6; optional) |
| `preset` | a value equal to: 'dayAndHour', 'dayAndMonth', 'dayAndWeek', 'monthAndYear', 'year'; optional | Controlled zoom preset. Also an OUTPUT. One of "dayAndHour" \| "dayAndMonth" \| "dayAndWeek" \| "monthAndYear" \| "year". |
| `presets` | list of a value equal to: 'dayAndHour', 'dayAndMonth', 'dayAndWeek', 'monthAndYear', 'year's; optional | The presets available (zoom levels offered). Default is all five, from most zoomed-in to most zoomed-out. |
| `readOnly` | boolean; optional | Global read-only mode. |
| `resourceColumnLabel` | string; optional | Label shown in the resource column header. |
| `resources` | list of dicts; optional | The resource rows. Each event's `resource` points to one of these ids. |
| `shouldEventRequireResource` | boolean; optional | Require every event to be assigned to a resource. Default True (timeline). |
| `showCurrentTimeIndicator` | boolean; optional | Show the current-time indicator line. Default True. |
| `sx` | dict; optional | MUI `sx` styling object applied to the timeline (object form only). |
| `visibleDate` | string; optional | Controlled visible date (ISO string) — centers the window. Also OUTPUT. |
| `visibleResources` | dict; optional | Controlled resource visibility map {resourceId: bool}. Also an OUTPUT. |


---

*Source: /event-timeline*
