# MUI Scheduler > Event calendars, resource timelines, and radial charts for Dash, wrapping the MUI X Scheduler. --- .. toc:: .. llms_copy::MUI Scheduler > 📚 **Full documentation:** [dash-mui-scheduler.onrender.com](https://dash-mui-scheduler.onrender.com) — the dedicated docs site with every calendar/timeline component, live examples, and props tables. This page is the quick-start overview. ### Installation [Visit GitHub Repo](https://github.com/pip-install-python/dash-mui-scheduler) · [PyPI](https://pypi.org/project/dash-mui-scheduler/) ```bash pip install dash-mui-scheduler ``` ### Introduction `dash-mui-scheduler` is the successor to `dash-fullcalendar` — it replaces it in this catalogue. It wraps the [MUI X Scheduler](https://mui.com/x/react-scheduler/) for Plotly Dash, so you can build event calendars and resource timelines in pure Python. Events cross the Dash ↔ Python boundary as plain dictionaries with ISO-string dates, and every user interaction (create / move / resize / delete) round-trips straight back into your callbacks. Dark mode is automatic — the components follow the surrounding Dash Mantine Components color scheme. The suite includes: | Component | Plan | What it is | |:----------|:-----|:-----------| | `EventCalendar` | **Community (MIT)** | Day / week / month / agenda calendar with drag-and-drop, resizing, resources, and an editing dialog. No license key. | | `EventCalendarPremium` | Premium | The calendar plus the recurrence engine (RRULE events + exception dates). | | `EventTimeline` | Premium | A resource-row, Gantt-style timeline across configurable zoom presets. | | `RadialLineChart` | Premium (preview) | Polar line/area charts for trends along periodic values. | | `RadialBarChart` | Premium (preview) | Polar bar charts for comparing values along periodic categories. | > The underlying MUI X Scheduler is in **beta** (`@mui/x-scheduler@9.0.0-beta.0`); this wrapper pins the beta exactly, so the upstream API may change before its stable release. ### Quick Start Pass a list of event dicts — each needs at least `id`, `title`, `start`, and `end` (ISO strings). Optional keys include `description`, `color`, `allDay`, `resource`, and per-event `draggable` / `resizable` / `readOnly` overrides. .. exec::docs.dash_mui_scheduler.quickstart_example :code: false ```python # File: docs/dash_mui_scheduler/quickstart_example.py """Quick-start EventCalendar example with sample events.""" from datetime import datetime, timedelta import dash_mantine_components as dmc import dash_mui_scheduler as dms # Anchor the sample events to the current week so the calendar # always opens with something to look at. _monday = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) _monday -= timedelta(days=_monday.weekday()) def _iso(day_offset: int, hour: int, minute: int = 0) -> str: return (_monday + timedelta(days=day_offset, hours=hour, minutes=minute)).isoformat() # Events are plain dicts with ISO-string dates. # Required keys: id, title, start, end. Everything else is optional. events = [ { "id": "1", "title": "Team Standup", "start": _iso(0, 9), "end": _iso(0, 9, 30), "color": "blue", }, { "id": "2", "title": "Design Review", "start": _iso(1, 13), "end": _iso(1, 14, 30), "color": "purple", "description": "Review the new dashboard mockups.", }, { "id": "3", "title": "Client Call", "start": _iso(2, 10), "end": _iso(2, 11), "color": "teal", }, { "id": "4", "title": "Sprint Demo", "start": _iso(3, 15), "end": _iso(3, 16), "color": "green", }, { "id": "5", "title": "Conference Day", "start": _iso(4, 0), "end": _iso(4, 23, 59), "allDay": True, "color": "orange", }, ] component = dmc.Paper( dms.EventCalendar( id="mui-scheduler-quickstart-cal", events=events, defaultView="week", height=620, ), withBorder=True, p="md", ) ``` ### Events & Callbacks The `events` prop is **both an input and an output**. Seed it with your data; the calendar writes the full new array back whenever the user creates, moves, resizes, or deletes an event. For a lighter-weight signal, `lastAction` reports just the most recent change: ```python {"type": "create" | "update" | "delete" | "move" | "resize" | "change", "event": {...}, # the affected event (or None) "event_timestamp": ...} ``` Other stateful props (`view`, `visibleDate`, `preferences`, `visibleResources`) each come as a controlled prop plus an uncontrolled `defaultX` variant, and are written back on change — so you can read the active view or the date the user navigated to in a callback. .. exec::docs.dash_mui_scheduler.interactive_example :code: false ```python # File: docs/dash_mui_scheduler/interactive_example.py """Interactive example: round-tripping event edits through callbacks. `events` is BOTH an input and an output — the calendar writes the full array back on every create / move / resize / delete. `lastAction` is a convenience output describing just the most recent change. """ import json from datetime import datetime, timedelta import dash_mantine_components as dmc import dash_mui_scheduler as dms from dash import callback, Input, Output _monday = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) _monday -= timedelta(days=_monday.weekday()) def _iso(day_offset: int, hour: int, minute: int = 0) -> str: return (_monday + timedelta(days=day_offset, hours=hour, minutes=minute)).isoformat() events = [ {"id": "a", "title": "Drag me around", "start": _iso(0, 10), "end": _iso(0, 11), "color": "indigo"}, {"id": "b", "title": "Resize my edges", "start": _iso(2, 13), "end": _iso(2, 15), "color": "pink"}, {"id": "c", "title": "Click to edit or delete", "start": _iso(4, 9), "end": _iso(4, 10), "color": "amber"}, ] component = dmc.Stack( [ dms.EventCalendar( id="mui-scheduler-interactive-cal", events=events, defaultView="week", height=560, eventCreation={"interaction": "click", "duration": 60}, ), dmc.Group( [ dmc.Badge("try it", color="teal", variant="light"), dmc.Text( "Drag, resize, create (click an empty slot), edit, or delete an event — " "every change lands in a Dash callback.", size="sm", c="dimmed", ), ], gap="xs", ), dmc.SimpleGrid( cols={"base": 1, "md": 2}, children=[ dmc.Paper( [ dmc.Text("lastAction", fw=600, size="sm", mb="xs"), dmc.Code( "Interact with the calendar…", id="mui-scheduler-last-action-output", block=True, ), ], withBorder=True, p="md", ), dmc.Paper( [ dmc.Text("events (round-tripped)", fw=600, size="sm", mb="xs"), dmc.Text( f"{len(events)} events", id="mui-scheduler-event-count-output", size="sm", c="dimmed", ), ], withBorder=True, p="md", ), ], ), ], gap="md", ) @callback( Output("mui-scheduler-last-action-output", "children"), Input("mui-scheduler-interactive-cal", "lastAction"), prevent_initial_call=True, ) def show_last_action(last_action): if not last_action: return "Interact with the calendar…" # lastAction = {"type": "create"|"update"|"delete"|"move"|"resize"|"change", # "event": {...}, "event_timestamp": ...} return json.dumps( {"type": last_action.get("type"), "event": last_action.get("event")}, indent=2, default=str, ) @callback( Output("mui-scheduler-event-count-output", "children"), Input("mui-scheduler-interactive-cal", "events"), prevent_initial_call=True, ) def show_event_count(current_events): current_events = current_events or [] titles = ", ".join(e.get("title", "?") for e in current_events) return f"{len(current_events)} events — {titles}" ``` ### Premium Components `EventCalendarPremium`, `EventTimeline`, and the radial charts wrap MUI X **Premium** packages. They all accept a `licenseKey` prop; without a valid MUI X Premium license key they still render, but with a watermark. All Premium components share the same `@mui/x-license` singleton, so a single key covers everything. The Dash wrapper code in this package is MIT-licensed; the underlying MUI X Premium libraries are not. #### EventCalendarPremium — recurrence Same API as `EventCalendar`, plus `licenseKey` and support for recurring events via `rrule` (an RFC-5545 RRULE string or an object) and `exDates` (exception dates): ```python import os import dash_mui_scheduler as dms dms.EventCalendarPremium( id="mui-scheduler-premium-cal", licenseKey=os.environ["MUI_X_LICENSE_KEY"], events=[{ "id": 1, "title": "Standup", "start": "2026-07-06T09:00:00", "end": "2026-07-06T09:15:00", "rrule": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", }], defaultVisibleDate="2026-07-06", ) ``` #### EventTimeline A Gantt-style timeline that lays events out in resource rows across configurable zoom presets. It shares the calendar's event/resource model (`events`, `resources`, `lastAction`, drag/resize props) and swaps the `view`/`views` props for `preset` / `defaultPreset` / `presets`, plus a `resourceColumnLabel` for the resource column header. #### Radial Charts (Premium preview) `RadialLineChart` and `RadialBarChart` are polar charts from `@mui/x-charts-premium`. Pass row-oriented `dataset` rows plus `series` that reference columns via `dataKey`; `rotationAxis` replaces the cartesian x-axis and `radiusAxis` replaces the y-axis. Clicking the chart reports the hit axis item via the `clickData` output. They are `Unstable_` previews — production-ready, but their API may shift. .. exec::docs.dash_mui_scheduler.radial_chart_example :code: false ```python # File: docs/dash_mui_scheduler/radial_chart_example.py """RadialLineChart example (Premium preview). Renders with a watermark unless a MUI X Premium `licenseKey` is provided. Set the MUI_X_LICENSE_KEY environment variable to remove it. """ import os import dash_mantine_components as dmc import dash_mui_scheduler as dms from dash import callback, Input, Output # Row-oriented data; each series references a column via `dataKey`. dataset = [ {"month": "Jan", "london": 49, "paris": 51}, {"month": "Feb", "london": 38, "paris": 41}, {"month": "Mar", "london": 40, "paris": 47}, {"month": "Apr", "london": 44, "paris": 52}, {"month": "May", "london": 49, "paris": 63}, {"month": "Jun", "london": 45, "paris": 49}, {"month": "Jul", "london": 45, "paris": 62}, {"month": "Aug", "london": 50, "paris": 53}, {"month": "Sep", "london": 49, "paris": 47}, {"month": "Oct", "london": 69, "paris": 61}, {"month": "Nov", "london": 59, "paris": 55}, {"month": "Dec", "london": 56, "paris": 58}, ] component = dmc.Paper( dmc.Stack( [ dms.RadialLineChart( id="mui-scheduler-radial-lines", height=420, licenseKey=os.environ.get("MUI_X_LICENSE_KEY", ""), dataset=dataset, # rotationAxis = angular (x-like) axis, radiusAxis = radial (y-like) axis series=[ {"dataKey": "london", "label": "London (mm)", "curve": "natural", "showMark": True}, {"dataKey": "paris", "label": "Paris (mm)", "curve": "natural", "showMark": True}, ], rotationAxis=[{"scaleType": "point", "dataKey": "month", "disableLine": True}], radiusAxis=[{"disableLine": True}], grid={"rotation": True, "radius": True}, ), dmc.Text( "Click the chart to inspect an axis item.", id="mui-scheduler-radial-click-output", size="sm", c="dimmed", ta="center", ), ], gap="xs", ), withBorder=True, p="md", ) @callback( Output("mui-scheduler-radial-click-output", "children"), Input("mui-scheduler-radial-lines", "clickData"), prevent_initial_call=True, ) def show_click(click_data): if not click_data: return "Click the chart to inspect an axis item." return ( f"Clicked {click_data.get('axisValue')} — " f"series values: {click_data.get('seriesValues')}" ) ``` ### EventCalendar Properties | Property | Type | Default | Description | |:---------|:-----|:--------|:------------| | `id` | string | - | Component ID for Dash callbacks. | | `events` | list of dicts | - | The events to render. Each needs `id`, `title`, `start`, `end` (ISO strings); optional `description`, `timezone`, `resource`, `rrule`, `exDates`, `allDay`, `readOnly`, `color`, `draggable`, `resizable`, `className`. **Input AND output** — written back on every edit. | | `lastAction` | dict | - | **Output.** The most recent change: `{type, event, event_timestamp}`. | | `view` | `'day'` \| `'week'` \| `'month'` \| `'agenda'` | - | Controlled active view. Also an **output** (updated on view change). | | `defaultView` | string | `'week'` | Uncontrolled initial view. | | `views` | list of strings | `['day','week','month','agenda']` | Which views are offered. | | `visibleDate` | string | - | Controlled visible date (ISO string). Also an **output** on navigation. | | `defaultVisibleDate` | string | today | Uncontrolled initial visible date. | | `eventColor` | string | `'teal'` | Default event palette: `red`, `pink`, `purple`, `indigo`, `blue`, `teal`, `green`, `lime`, `amber`, `orange`, `grey`. Overridden per resource and per event. | | `eventCreation` | bool \| dict | - | `False` disables creation; a dict sets `{interaction: 'click'\|'double-click', duration}` (minutes). | | `resources` | list of dicts | - | Resources events can be assigned to (supports nested `children`). | | `visibleResources` | dict | - | Controlled resource visibility map `{resourceId: bool}`. Also an **output**. | | `defaultVisibleResources` | dict | `{}` | Uncontrolled initial resource visibility (all visible). | | `shouldEventRequireResource` | boolean | `False` | Require every event to be assigned to a resource. | | `areEventsDraggable` | boolean | `True` | Allow drag-to-reschedule. | | `areEventsResizable` | bool \| `'start'` \| `'end'` | `True` | Allow resize (or restrict to one edge). | | `canDragEventsFromTheOutside` | boolean | `False` | Allow external events to be dragged in. | | `canDropEventsToTheOutside` | boolean | `False` | Allow events to be dragged out of the calendar. | | `readOnly` | boolean | - | Global read-only mode (disables create / drag / resize / dialog). | | `showCurrentTimeIndicator` | boolean | `True` | Show the current-time indicator line in time views. | | `scrollToCurrentTime` | boolean | `False` | Scroll day/week views so the current time is centered on first render. | | `displayTimezone` | string | `'default'` | Render timezone: IANA name, `'default'`, `'locale'`, or `'UTC'`. Render-only. | | `preferences` | dict | - | Controlled user preferences `{ampm, weekStartsOn, showWeekends, showWeekNumber, isSidePanelOpen, showEmptyDaysInAgenda}`. Also an **output**. | | `defaultPreferences` | dict | - | Uncontrolled initial preferences (same shape). | | `preferencesMenuConfig` | `False` \| dict | - | Which items appear in the preferences menu, or `False` to hide it. | | `localeText` | dict | - | Override UI label strings (partial map of translation keys). | | `eventDialogVariant` | `'drawer'` \| `'dialog'` | `'drawer'` | Event editor presentation: responsive drawer or floating dialog. | | `eventDialogTopOffset` | number | `0` | Desktop drawer inset from the top (px) — e.g. your fixed header height. | | `responsiveSidePanel` | boolean | `True` | Side panel opens on wide screens, collapses below `mobileBreakpoint`. | | `mobileBreakpoint` | number | `768` | Width (px) below which the UI switches to its mobile layout. | | `height` | number \| string | `600` | Height of the wrapping container. | | `className` | string | - | CSS class applied to the wrapping div. | | `sx` | dict | - | MUI `sx` styling object (object form only). | **Note:** `EventCalendarPremium` accepts all of the above plus `licenseKey`. `EventTimeline` accepts `licenseKey`, `preset` / `defaultPreset` / `presets`, and `resourceColumnLabel` in place of the `view` props; the radial charts take `dataset`, `series`, `rotationAxis`, `radiusAxis`, `grid`, `axisHighlight`, `colors`, `hideLegend`, `margin`, `showToolbar`, `slotProps`, and the `clickData` output. See the component docstrings for full details. --- *Source: /pip/dash_mui_scheduler* *Generated with dash-improve-my-llms*