# Events

> Define calendar events as plain dictionaries with ISO-string dates — including colors, all-day events, and creation controls.

**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  


---



### Events

An event is just a Python `dict`. You pass a list of them to the `events` prop, and
the calendar renders one block per event. Dates cross the boundary as **ISO strings**,
never Python `datetime` objects.

The `events` prop is both an **input and an output**: when a user creates, moves,
resizes, or deletes an event, the component writes the *entire* new array back to
`events`. You don't diff anything yourself — read `events` for the full picture, or
read `lastAction` for just-what-changed.



```python
# File: docs/events/events_basic.py

import dash_mui_scheduler as dms
from dash import html, dcc, Input, Output, callback

# Each event is a plain dict. Dates are ISO strings (no "Z" = wall time).
# Required keys: id, title, start, end. Everything else is optional.
events = [
    {
        "id": "kickoff",
        "title": "Project Kickoff",
        "start": "2024-01-15T09:00:00",
        "end": "2024-01-15T10:00:00",
        "description": "Align on goals for the quarter.",
    },
    {
        "id": "standup",
        "title": "Daily Standup",
        "start": "2024-01-16T09:30:00",
        "end": "2024-01-16T09:45:00",
    },
    {
        "id": "review",
        "title": "Design Review",
        "start": "2024-01-17T14:00:00",
        "end": "2024-01-17T15:30:00",
        "description": "Walk through the new dashboard mockups.",
    },
    {
        "id": "1on1",
        "title": "1:1",
        "start": "2024-01-18T11:00:00",
        "end": "2024-01-18T11:30:00",
    },
]

component = html.Div(
    [
        dms.EventCalendar(
            id="events-basic-cal",
            events=events,
            defaultVisibleDate="2024-01-15",
            height=600,
        ),
        dcc.Markdown(id="events-basic-out", style={"marginTop": "0.75rem"}),
    ]
)


@callback(
    Output("events-basic-out", "children"),
    Input("events-basic-cal", "events"),
)
def show_count(current_events):
    return f"**{len(current_events or [])}** events currently on the calendar."
```


The callback above only *reads* `events` to display a count. The calendar is fully
interactive **without any callback** — drag, create, and delete all persist on their
own through Dash's normal `setProps` round-trip. Add a callback only when you want to
*display* an output (`events`, `lastAction`, `view`, or `visibleDate`).

### Event fields

Every event needs four required keys; the rest are optional.

| Key | Type | Notes |
|---|---|---|
| `id` | str \| int | Unique per event. **Required.** |
| `title` | str | Shown on the event block. **Required.** |
| `start` | ISO str | e.g. `"2024-01-15T10:00:00"`. **Required.** |
| `end` | ISO str | e.g. `"2024-01-15T11:00:00"`. **Required.** |
| `description` | str | Free-text shown in the event dialog. |
| `resource` | str | Id of a resource this event belongs to. |
| `allDay` | bool | Render in the all-day row (see below). |
| `color` | str | One of the 11 palette names (see below). |
| `timezone` | str | IANA name, e.g. `"America/New_York"`. |
| `draggable` | bool | Override drag for this one event. |
| `resizable` | bool \| `'start'` \| `'end'` | Override resize for this one event. |
| `readOnly` | bool | Make this event non-editable. |
| `className` | str | CSS class on the event element. |


    Dates must be ISO **strings**. A string without a `Z` suffix
    (`"2024-01-15T10:00:00"`) is treated as wall-clock time; a string with `Z`
    (`"2024-01-15T10:00:00Z"`) is UTC. Never pass a Python `datetime` — it is not
    JSON-serializable across the Dash boundary.

### Colors

Set a per-event `color` to any of the **11 palette names**:

`red` · `pink` · `purple` · `indigo` · `blue` · `teal` *(default)* · `green` · `lime` · `amber` · `orange` · `grey`

The calendar-wide `eventColor` prop sets the default color for any event that does
**not** carry its own `color` key. A per-event `color` always overrides `eventColor`.



```python
# File: docs/events/event_colors.py

import dash_mui_scheduler as dms
from dash import html

# The 11-color palette. Set a per-event "color" with any of these names.
PALETTE = [
    "red", "pink", "purple", "indigo", "blue",
    "teal", "green", "lime", "amber", "orange", "grey",
]

# One event per palette color, laid across the week so each is visible.
events = []
for i, name in enumerate(PALETTE):
    day = 15 + (i % 5)          # Mon–Fri of the week of 2024-01-15
    hour = 8 + (i // 5) * 3      # stagger rows so they don't overlap
    events.append(
        {
            "id": f"color-{name}",
            "title": name.capitalize(),
            "start": f"2024-01-{day:02d}T{hour:02d}:00:00",
            "end": f"2024-01-{day:02d}T{hour:02d}:45:00",
            "color": name,
        }
    )

# This event has no "color" of its own, so it falls back to eventColor below.
events.append(
    {
        "id": "color-default",
        "title": "Uses eventColor",
        "start": "2024-01-19T13:00:00",
        "end": "2024-01-19T14:00:00",
    }
)

component = html.Div(
    dms.EventCalendar(
        id="events-colors-cal",
        events=events,
        # eventColor is the calendar-wide default for any event without its
        # own "color" key. Per-event "color" always wins over this.
        eventColor="purple",
        defaultVisibleDate="2024-01-15",
        height=620,
    )
)
```


### All-day events

Mark an event `allDay: True` to place it in the calendar's all-day row, spanning
whole days instead of a time slot. All-day and timed events mix freely in the same
`events` list.



```python
# File: docs/events/all_day.py

import dash_mui_scheduler as dms
from dash import html

# allDay events render in the calendar's all-day row, spanning whole days.
# Mix them freely with ordinary timed events.
events = [
    # All-day events: allDay=True. The time portion of start/end is ignored,
    # but keep them as valid ISO strings. end is exclusive of its last instant,
    # so a single-day all-day event ends the same day.
    {
        "id": "allday-holiday",
        "title": "Company Holiday",
        "start": "2024-01-15T00:00:00",
        "end": "2024-01-15T23:59:59",
        "allDay": True,
        "color": "green",
    },
    {
        "id": "allday-conference",
        "title": "Conference (3 days)",
        "start": "2024-01-17T00:00:00",
        "end": "2024-01-19T23:59:59",
        "allDay": True,
        "color": "indigo",
    },
    # Ordinary timed events sit in the day grid below the all-day row.
    {
        "id": "allday-call",
        "title": "Client Call",
        "start": "2024-01-16T10:00:00",
        "end": "2024-01-16T10:30:00",
        "color": "blue",
    },
    {
        "id": "allday-lunch",
        "title": "Team Lunch",
        "start": "2024-01-18T12:00:00",
        "end": "2024-01-18T13:00:00",
        "color": "amber",
    },
]

component = html.Div(
    dms.EventCalendar(
        id="events-allday-cal",
        events=events,
        defaultVisibleDate="2024-01-15",
        height=600,
    )
)
```



    For an all-day event the time portion of `start`/`end` is ignored, but keep them
    as valid ISO strings. A multi-day span (`"2024-01-17"` → `"2024-01-19"`) shows as
    a single bar across those days.

### Controlling creation

The `eventCreation` prop decides whether — and how — users can create new events by
interacting with empty space.

- **`eventCreation=True`** *(default)* — creation is on with the component's default
  gesture.
- **`eventCreation=False`** — disable click/drag-to-create entirely (existing events
  can still be edited unless you also set `readOnly=True`).
- **`eventCreation={...}`** — fine-tune the gesture with two keys:
  - `interaction`: `'click'` or `'double-click'` — how a new event is started.
  - `duration`: minutes (int) — the length of an event created by a single click.

```python
# A double-click creates a 30-minute event in empty space.
dms.EventCalendar(
    id="events-creation-cal",
    events=events,
    eventCreation={"interaction": "double-click", "duration": 30},
    defaultVisibleDate="2024-01-15",
    height=600,
)
```

When a user creates an event, the new block is appended to `events` and
`lastAction` reports `{"type": "create", "event": {...}, "event_timestamp": ...}`.

### EventCalendar props


#### `EventCalendar` props

| prop | type | description |
|---|---|---|
| `id` | string; optional | The id used to identify this component in Dash callbacks. |
| `areEventsDraggable` | boolean; optional | Allow drag-to-reschedule. 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 calendar. Default False. |
| `className` | string; optional | CSS class applied to the wrapping div. |
| `defaultPreferences` | dict; optional | Uncontrolled initial preferences (same shape as `preferences`). `defaultPreferences` is a dict with keys: - ampm (boolean; optional) - weekStartsOn (a value equal to: 0, 1, 2, 3, 4, 5, 6; optional) - showWeekends (boolean; optional) - showWeekNumber (boolean; optional) - isSidePanelOpen (boolean; optional) - showEmptyDaysInAgenda (boolean; optional) |
| `defaultView` | a value equal to: 'day', 'week', 'month', 'agenda'; optional | Uncontrolled initial view. Default "week". |
| `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 | Timezone used to render events: an IANA name ("America/New_York"), or "default" / "locale" / "UTC". Render-only — events keep their own data timezone. Default "default". |
| `eventColor` | a value equal to: 'red', 'pink', 'purple', 'indigo', 'blue', 'teal', 'green', 'lime', 'amber', 'orange', 'grey'; optional | The default color palette used for all events. Overridden per resource (`eventColor`) and per event (`color`). Default "teal". |
| `eventCreation` | dict; optional | Configures event creation. `False` disables it; `True` enables it with defaults; an object sets the interaction and default 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 so the drawer lines up with a sidebar instead of covering the header. 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 drawer — right-anchored on desktop, an 80%-height bottom sheet on mobile (below `mobileBreakpoint`), with a scrollable body and pinned header/actions. "dialog" keeps the library's default floating, draggable dialog. |
| `events` | list of dicts; optional | The events to render. Each event is a dict with at least `id`, `title`, `start` and `end` (ISO strings). This is BOTH an input and an output: the calendar writes the full array back on every create / edit / move / resize / delete. `events` is a list of dicts with keys: - id (string \| number; required): Unique id (string or number). - title (string; required): Event title. - start (string; required): Start date-time, ISO string. "Z" suffix = UTC instant. - end (string; required): End date-time, ISO string. "Z" suffix = UTC instant. - description (string; optional): Optional longer description (shown in the event dialog). - timezone (string; optional): IANA timezone the wall-time start/end are interpreted in. - resource (string \| number; optional): Id of the resource this event belongs to. - rrule (string \| dict; optional): Recurrence rule — an RFC-5545 RRULE string ("FREQ=WEEKLY;INTERVAL=2;BYDAY=TH") or an object {freq, interval, byDay, byMonthDay, byMonth, count, until}. Recurrence is a Premium feature (use EventCalendarPremium). - exDates (list of strings; optional): Exception dates (ISO strings) excluded from the recurrence. - allDay (boolean; optional): Whether the event spans the whole day. - readOnly (boolean; optional): Whether the event cannot be edited / dragged / resized. - color (a value equal to: 'red', 'pink', 'purple', 'indigo', 'blue', 'teal', 'green', 'lime', 'amber', 'orange', 'grey'; optional): Event color (overrides resource + component color). - draggable (boolean; optional): Per-event drag override. - resizable (boolean \| a value equal to: 'start', 'end'; optional): Per-event resize override (bool or which edge). - className (string; optional): Custom CSS class for the event element. - extractedFromId (string \| number; optional): Id of the event this one was split from. |
| `height` | number \| string; default 600 | Height of the wrapping container (the calendar fills it). Default 600. |
| `lastAction` | dict; optional | Convenience OUTPUT describing the most recent change to `events`: {type: "create"\|"update"\|"delete"\|"move"\|"resize"\|"change", event: the affected event (or None), event_timestamp}. `lastAction` is a dict with keys: - type (string; optional) - event (dict; optional) - event_timestamp (number; optional) |
| `localeText` | dict; optional | Override UI label strings (a partial map of translation keys). |
| `mobileBreakpoint` | number; default 768 | Width (px) below which the UI switches to its mobile layout. Default 768. |
| `preferences` | dict; optional | Controlled user preferences. Also an OUTPUT. {ampm, weekStartsOn (0=Sun..6=Sat), showWeekends, showWeekNumber, isSidePanelOpen, showEmptyDaysInAgenda}. `preferences` is a dict with keys: - ampm (boolean; optional) - weekStartsOn (a value equal to: 0, 1, 2, 3, 4, 5, 6; optional) - showWeekends (boolean; optional) - showWeekNumber (boolean; optional) - isSidePanelOpen (boolean; optional) - showEmptyDaysInAgenda (boolean; optional) |
| `preferencesMenuConfig` | dict; optional | Which items appear in the preferences menu, or `False` to hide the menu. `preferencesMenuConfig` is a a value equal to: false \| dict with keys: - toggleWeekendVisibility (boolean; optional) - toggleWeekNumberVisibility (boolean; optional) - toggleAmpm (boolean; optional) - toggleEmptyDaysInAgenda (boolean; optional) - toggleWeekStartsOn (boolean; optional) |
| `readOnly` | boolean; optional | Global read-only mode (disables create / drag / resize / dialog). |
| `resources` | list of dicts; optional | Resources events can be assigned to (supports nested `children`). |
| `responsiveSidePanel` | boolean; default True | When True (default), the side panel starts open on wide screens and collapsed below `mobileBreakpoint` on first render — unless you pin `isSidePanelOpen` via `preferences` / `defaultPreferences`. |
| `scrollToCurrentTime` | boolean; default False | In the day / week views, scroll the time grid on first render (and on view change) so the current-time indicator is centered in view. Pairs with `showCurrentTimeIndicator`. Default False. |
| `shouldEventRequireResource` | boolean; optional | Require every event to be assigned to a resource. Default False. |
| `showCurrentTimeIndicator` | boolean; optional | Show the current-time indicator line in time views. Default True. |
| `sx` | dict; optional | MUI `sx` styling object applied to the calendar (object form only). |
| `view` | a value equal to: 'day', 'week', 'month', 'agenda'; optional | Controlled active view. Also an OUTPUT (updated on view change). |
| `views` | list of a value equal to: 'day', 'week', 'month', 'agenda's; optional | Which views are offered. Default ["day","week","month","agenda"]. |
| `visibleDate` | string; optional | Controlled visible date (ISO string). Drives which date range is shown. Also an OUTPUT — written back (ISO string) when the user navigates. |
| `visibleResources` | dict; optional | Controlled resource visibility map {resourceId: bool}. Also an OUTPUT. |


---

*Source: /events*
