The event type
Events are plain objects. The only required fields arestart, 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.
allDaylays 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. PassshowAllDayEventCell={false}to hide the lane entirely (its events won’t show). In thescheduleview (which has no lane) an all-day event reads “All day” instead of a time range; override the wording withallDayLabel(e.g. for a different language).disabledopts an event out of drag interactions.draggable,startEditable, anddurationEditablecontrol 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
PassrenderEvent — 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.
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. boxHeight
never drops below the grid’s minEventHeight (default 32 on native, 14 on the
dom renderer); set it to 0 if your renderer should get the exact duration
height. The box is inset from its slot by eventGap (see
Event boxes).
Lighter touches
If you only want to tweak the built-in event box, you don’t need a fullrenderEvent:
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.showTimeshows 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.ellipsizeTitleends 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 witheventAccessibilityLabel. It receives the event and a { mode, isAllDay, ampm }
context, and its return value replaces the default label across every view.
MonthView, MonthList, and TimeGrid, so a
custom renderer and its label stay in sync.
Background events
Setdisplay: "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:
backgroundEvent slot or the theme’s
backgroundEvent colour token.
To draw a band yourself, or make it pressable, pass a component as
renderBackgroundEvent to Calendar or TimeGrid on either renderer (the
resource timeline keeps the shade). It is rendered like renderEvent, so it may
use hooks, and receives the event, the mode, the band’s boxHeight, the
ampm flag, continuesBefore / continuesAfter for a multi-day event, and
onPress, which fires onPressEvent; React Native adds onLongPress and makes
boxHeight a live shared value that follows a pinch. The themed tint is
dropped, the band lets touches or pointer events through to what you render, and
it is no longer hidden from assistive tech. On the web the band itself takes no
focus, so render a focusable control such as a button for keyboard users. Cell
presses and drag-to-create are unreachable underneath such a band. Define the
component outside your render so it keeps its identity (on the web the args
type is
DomRenderEventArgs from @super-calendar/dom):
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.
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.