Lumeo

Scheduler

A calendar & event scheduler with month, week, day, and agenda views. Drag events to reschedule, resize to change duration, or drag across the grid to create new ones.

Installation

dotnet add package Lumeo.Scheduler

One-time app setup (AddLumeo(), CSS & JS) is covered in the installation guide.

Usage

@using Lumeo

<Scheduler />

When to Use

  • Displaying appointments, meetings, shifts, or any time-based event grid.
  • Giving users direct manipulation controls — drag to reschedule, drag-to-select to create, resize to change duration.
  • Switching between month overviews, focused day/week planning, and a flat agenda list within the same data.
  • Showing overlapping events (double-booked rooms, parallel tracks), multi-day spans, and recurring series side by side.

The views

Month, week/day, agenda and resource renderers, written in Blazor. Each is usable on its own, and Scheduler composes them behind its toolbar.

Realistic month with overlapping events, a multi-day span, and a weekday-recurring standup. Today's cell has 5 events — more than the 3-lane budget — so it overflows into a "+N more" popover. Drag an event to move it (ghost preview until you release); drag across empty days to create one.

MonTueWedThuFriSatSun
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Last interaction
Drag an event, or drag-select empty days, to see it here.

Same event set, time-grid layout. Overlapping events are packed side by side, off-hours are shaded, and the red line tracks the current time. Drag moves an event across days/times as a ghost outline; drag the bottom edge to resize.

Mon
17
Tue
18
Wed
19
Thu
20
Fri
21
Sat
22
Sun
23
All day
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00
Last change
Drag or resize an event to see it here.
Wed
19
All day
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

Flat chronological list across the next 30 days — the same events as the calendar views above, including recurring occurrences and multi-day spans, grouped by day.

Wednesday, 19 August 2026
Team offsite
Daily stand-up 09:00
Kickoff — Design 10:00
Kickoff — Backend 10:15
Kickoff — Docs 10:30
Kickoff — QA 10:45
Release readiness 15:00
Thursday, 20 August 2026
Daily stand-up 09:00
1:1 sync 16:00
Friday, 21 August 2026
Daily stand-up 09:00
Client call 11:00
Sunday, 23 August 2026
Hackathon
Monday, 24 August 2026
Daily stand-up 09:00
Tuesday, 25 August 2026
Daily stand-up 09:00
Design review 14:00
Wednesday, 26 August 2026
Daily stand-up 09:00
Sprint review 15:00
Thursday, 27 August 2026
Daily stand-up 09:00
1:1 sync 16:00
Friday, 28 August 2026
Daily stand-up 09:00
Saturday, 29 August 2026
Docs sprint
Monday, 31 August 2026
Daily stand-up 09:00
Tuesday, 01 September 2026
Daily stand-up 09:00
Design review 14:00
Wednesday, 02 September 2026
Daily stand-up 09:00
Thursday, 03 September 2026
Daily stand-up 09:00
Beta tag 09:00
1:1 sync 16:00
Friday, 04 September 2026
Daily stand-up 09:00
Monday, 07 September 2026
Daily stand-up 09:00
Tuesday, 08 September 2026
Daily stand-up 09:00
Design review 14:00
Wednesday, 09 September 2026
Daily stand-up 09:00
Thursday, 10 September 2026
Daily stand-up 09:00
1:1 sync 16:00
Friday, 11 September 2026
Daily stand-up 09:00
Monday, 14 September 2026
Daily stand-up 09:00
Tuesday, 15 September 2026
Daily stand-up 09:00
Design review 14:00
Wednesday, 16 September 2026
Daily stand-up 09:00
Thursday, 17 September 2026
Daily stand-up 09:00
1:1 sync 16:00

CanDrop is a three-way gate evaluated before any drop commits: SchedulerDropResult.Reject, .Accept, or .AcceptWith(adjustment) to snap the drop to a different time than the user dragged to. Nothing mutates until CanDrop returns — dragging only ever moves a ghost outline. Try dragging the event onto the 15th (rejected) or the 22nd (accepted, but snapped forward one day) of this month.

MonTueWedThuFriSatSun
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Last CanDrop check
Drag the event onto the 15th or the 22nd.

Using Scheduler

The views above are standalone components. Scheduler puts the same renderers behind its own toolbar and adds the surrounding API — InitialView, Height, @bind-Events, OnDateSelect, OnEventChange, prev/next/today.

Switch views with the toolbar and page with prev/next.

August 2026
WkMonTueWedThuFriSatSun
31
27
28
29
30
31
1
2
32
3
4
5
6
7
8
9
33
10
11
12
13
14
15
16
34
17
18
19
20
21
22
23
35
24
25
26
27
28
29
30
36
31
1
2
3
4
5
6

A 15-minute grid. The gutter still prints one label per hour and hour boundaries keep the stronger rule, so the day still reads as hours rather than 96 stripes. Drags snap to the grid unless SnapDuration says otherwise. Values that do not divide an hour are rounded up to one that does — rows have to tile an hour exactly or the labels drift away from the lines they name.

Wednesday, Aug 19, 2026
Wed
19
All day
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

A rolling window of VisibleDays days. Unlike the week view it does not snap to a week start, and prev/next page by the window's own width, so consecutive pages tile the calendar instead of overlapping. The toolbar button appears only once you have chosen a width — an N-day view with no N is not a view.

Aug 19 – Aug 21, 2026
Wed
19
Thu
20
Fri
21
All day
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

Both calendars below hold the same events, read in two zones. Only events carrying a real instant move: a DateTime with Kind of Utc or Local denotes a point in time and can be re-read elsewhere, while an Unspecified value is a wall-clock reading that is already in whatever zone you meant — so setting a zone cannot silently shift existing data. Edits are converted back before they reach OnEventChange: what you get out is in the frame you put in. All-day events are dates, not instants, and never move.

Europe/Berlin
Wednesday, Aug 19, 2026
Wed
19
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00
Asia/Tokyo
Wednesday, Aug 19, 2026
Wed
19
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

SchedulerView.Timeline puts one row per resource and runs the time axis horizontally across days, weeks or months — the shape Outlook's scheduling assistant has. A different question from the resource view below: this one shows how a resource is booked over a stretch, that one shows who is where on a single day.

Overlapping bookings stack into their own lanes rather than drawing over each other, so a double booking is visible instead of hidden, and the row grows to fit. A booking running in from before the window is clamped to the edge, not dropped — a resource that is busy must never read as free.

Aug 19 – Aug 28, 2026
Alice Chen
Bob Kim
Carol Wu
Resources
Alice Chen
Bob Kim
Carol Wu

SchedulerView.Resource lays out one column per entry in Resources — genuinely separate lanes, not just color-coding.

Wednesday, Aug 19, 2026
Alice Chen
Bob Kim
Carol Wu
Alice Chen
Bob Kim
Carol Wu
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

BuiltInEventDialog is off by default, because most apps already have their own appointment form wired through OnDateSelect and OnEventClick. Turning it on never displaces that: both callbacks still fire exactly as before, so the dialog is additive. Double-click a day to create, click an event to edit; saving reports through EventsChanged — the same channel a drag uses.

August 2026
MonTueWedThuFriSatSun
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

A SchedulerCalendar is which FEED an event came from, where a SchedulerResource is what it consumes — so calendars decide whether an event is shown at all. Click a chip to hide one; the button beside them splits the visible calendars into their own panes and merges them back. An event with no CalendarId belongs to no calendar and is never hidden.

A selection drawn in a pane reports that pane on SchedulerDateRange.CalendarId, so your own appointment form can file the new event into the column the user drew it in. It is null while the calendars are overlaid, where no single one owns the gesture.

Week of Aug 17, 2026
Mon
17
Tue
18
Wed
19
Thu
20
Fri
21
Sat
22
Sun
23
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00

API Reference

Scheduler

SchedulerEvent

Field Type Description
IdstringStable identifier used to reconcile edits back into the caller's collection.
TitlestringThe label rendered on the event chip.
StartDateTimeStart timestamp (inclusive).
EndDateTimeEnd timestamp (exclusive).
AllDayboolWhen true the event is rendered in the all-day lane.
Colorstring?CSS color or variable reference like "var(--color-primary)".
Urlstring?Optional link opened on click instead of firing OnEventClick.
ExtendedPropsDictionary<string, object>?Arbitrary app-level metadata round-tripped through the JS layer.
DaysOfWeekIReadOnlyList<DayOfWeek>?Recurring: days of the week on which the event repeats (both engines). When set, Start/End provide the time-of-day only.
RecurrenceEndDateTime?Recurring: last date on which the event appears. Only meaningful when DaysOfWeek is set.
ExceptionDatesIReadOnlyList<DateTime>?Recurring: specific dates to skip (one-off exclusions).
RecurrenceSchedulerRecurrenceRule?Structured RRULE-subset recurrence (FREQ, INTERVAL, COUNT, UNTIL, BYDAY). Takes precedence over DaysOfWeek/RecurrenceEnd when set; supported by both engines.
ResourceIdstring?Matches this event to a SchedulerResource for color-coding when the Scheduler has a Resources list.
ClassNamesstring?Extra CSS class names applied directly to this event's chip (space-separated).

SchedulerResource

Field Type Description
IdstringIdentifier matched against SchedulerEvent.ResourceId.
TitlestringDisplay name shown in the resource legend.
Colorstring?CSS color applied to events belonging to this resource when the event has no explicit color.

SchedulerDateRange

Field Type Description
StartDateTimeRange start timestamp.
EndDateTimeRange end timestamp (exclusive).
AllDayboolTrue when the user selected whole days in a day-grid.

SchedulerView

Value Description
MonthDay-grid month view — best for an at-a-glance overview.
WeekTime-grid week view with hourly rows.
DayTime-grid single-day view.
ListAgenda-style list of the current week's events.

View components

Not yet a registered public API surface (no dedicated docs registry entry), but usable and independently testable today. Shared parameters across all three: Events, AnchorDate, OnEventClick, ResolveEventColor, Class, AdditionalAttributes.

Component Distinguishing parameters Description
SchedulerMonthView MaxVisibleLanes, ShowWeekNumbers, HideWeekends, SelectedDate(Changed), CanDrop, Selectable, BusinessHours(Days), Editable, OnDateSelect, OnEventChange Always-42-cell month grid. Events beyond MaxVisibleLanes (default 3) collapse into a "+N more" popover. ShowWeekNumbers adds a leading ISO-8601 week column; HideWeekends drops the Saturday/Sunday columns (keyboard navigation steps over them).
SchedulerTimeGridView Days, SlotMinTime/MaxTime, NowIndicator, CanDrop, BusinessHours(Start/End/Days), Editable, Selectable, OnDateSelect, OnEventChange Hourly time grid. Days="7" is the week view, Days="1" is the day view.
SchedulerAgendaView DaysToShow Flat chronological list, grouped by day, read-only (no drag/resize — it's a list).

SchedulerDropResult / CanDrop

CanDrop is a plain Func<SchedulerEvent, SchedulerScheduleDropContext, SchedulerDropResult> parameter on the Scheduler views. It is evaluated before a drag/resize/create commits — nothing mutates the underlying collection until it returns.

Member Description
SchedulerDropResult.RejectCancels the drop; the event snaps back to its original position.
SchedulerDropResult.AcceptCommits the drop exactly as proposed.
SchedulerDropResult.AcceptWith(adjustment)Commits the drop, overriding Start/End/AllDay with a SchedulerDropAdjustment (e.g. snapping to a valid slot).
SchedulerScheduleDropContextProposedStart, ProposedEnd, Source (which gesture — move, resize, or create — produced this proposal).
  • Calendar — picker-only date grid without events.
  • DatePicker — single-date input with a calendar dropdown.