Skip to main content

The event type

Events are plain objects. The only required fields are start, end, and title; everything else is yours. CalendarEvent<T> is generic, so you can attach your own fields and read them back in callbacks and renderers.
  • allDay lays the event out in the all-day lane above the grid instead of in the columns. It’s also inferred for midnight-to-midnight spans. Pass showAllDayEventCell={false} to hide the lane entirely (its events won’t show). In the schedule view (which has no lane) an all-day event reads “All day” instead of a time range; override the wording with allDayLabel (e.g. for a different language).
  • disabled opts an event out of drag interactions.
  • draggable, startEditable, and durationEditable control per-event drag and resize (see the drag guide).
  • Multi-day events draw as one continuous bar across the days they span in the month view, and as a per-day clipped segment on the week/day time grid.

Render your own event

Pass renderEvent — a component (so it can use hooks) that receives RenderEventArgs. It’s used in every mode and for every event shape (timed, all-day, multi-day), so you only write it once.
Wrapping events in a portaling overlay (a context menu, popover) on the web? Portal it into your app’s React root, not document.body — see the Web guide.
On the day/week grid a timed event’s box is sized to its duration and given to your renderer as boxHeight, so it tracks the grid’s hour scale as the grid zooms or resizes. Fit your content to boxHeight: the built-in renderer clamps its own content, and a custom renderer should adapt (show less, or scroll) rather than assume a fixed size, since content taller than the slot is clipped.

Lighter touches

If you only want to tweak the built-in event box, you don’t need a full renderEvent:
  • eventCellStyle — a style (or a function of the event) merged onto the built-in box.
  • keyExtractor — a stable key per event; defaults to start-time + index.
  • showTime shows the time range under the title (default true). The title comes first: on the day/week grid it fills the box with as many whole lines as fit (never a half-cut line), and the time only appears once a full line is free beneath it.
  • ellipsizeTitle ends a single-line title (the all-day lane, month cells) with a trailing ellipsis when it overflows, instead of a hard clip (default false).

Screen-reader labels

Each event announces a built-in label: its title plus the time range (or “all day”), which the grid otherwise only shows visually. Override it per event with eventAccessibilityLabel. It receives the event and a { mode, isAllDay, ampm } context, and its return value replaces the default label across every view.
The same prop is on the standalone MonthView, MonthList, and TimeGrid, so a custom renderer and its label stay in sync.

Background events

Set display: "background" to paint an event’s time range as a shaded, non-interactive band behind the grid instead of an event box — blocked time, maintenance windows, public holidays:
Background events shade the time grid and the resource timeline’s lanes (an all-day or multi-day one covers each day’s full window). They take no overlap column, render no chip in the month grid or agenda, and produce no year-view dot. Restyle the band with the backgroundEvent slot or the theme’s backgroundEvent colour token.

Loading events from a feed

useEventSource (from @super-calendar/core) owns the fetching for you: point it at a JSON feed, an iCalendar feed (.ics URLs are parsed automatically), or your own async function, and hand the result to any view. Set refetchIntervalMs for a live feed; refetch reloads on demand, and a failed refetch keeps the previous events while reporting error.
JSON feeds default to items with ISO start/end strings; pass map to reshape anything else (rename fields, attach a resourceId, filter). One nuance for function sources: swapping the function itself doesn’t trigger a refetch (inline functions change identity every render, which would loop). The next interval tick or a manual refetch() always calls the latest function, so change what the function reads, or call refetch() after swapping it.