View on GitHub

Renderer contracts

This reference covers the exact props and element contracts supplied to custom calendar renderers. The custom renderer guide explains composition and ownership responsibilities.

Extension points

Renderers receive prepared data and elementProps. Spread elementProps onto the semantic root unchanged before adding application props. It carries class, style, ARIA labeling, semantic/raw event handlers, and keyboard behavior owned by the library.

CalendarRendererElementProps always includes className and style, and may include native HTML attributes such as title, aria-label, onClick, and onKeyDown. Foreground event renderers receive a localized title containing the event title, description, and complete start/end date and time details. For example, an interactive event may receive { className: "calendar-event is-selected", style: { "--color": "#2563eb" }, "aria-label": "Planning, Monday, 9:00 AM to 10:00 AM", onClick }.

RendererPayload meaningExample data
shared navigationNative button props plus type: "prev" | "next"; preserve labels, disabled visibility, and click handlers.{ type: "next", "aria-label": "Next week", onClick }
agenda eventComplete normalized event, prepared timeLabel, selection state, and root elementProps.{ event: planning, timeLabel: "9:00 AM – 10:00 AM", selected: true, elementProps }
agenda dayHeaderNormalized day and prepared label.{ day: monday, label: "Monday, September 14" }
agenda emptyPrepared empty-state message.{ message: "No events in this range." }
month eventComplete normalized event, represented day, prepared timeLabel, selection state, and root props.{ event: planning, day: monday, timeLabel: "9:00 AM", selected: false, elementProps }
month dayHeaderNormalized day, prepared label, and whether it lies outside the active month.{ day: monday, label: "14", outsideMonth: false }
time-grid eventComplete normalized event, semantic visible segment, selection state, and positioned root props.{ event: planning, segment: { start: nine, end: ten, day: monday, resource: studio, resourceId: "studio" }, selected: true, elementProps }
time-grid slotComplete slot, range-overlap selection state, and root props.{ slot: { start: nine, end: nineThirty, duration: 30, resourceId: "studio" }, selected: false, elementProps }
time-grid backgroundEventComplete normalized event, semantic visible segment, and non-interactive positioned root props.{ event: lunchClosure, segment: { start: noon, end: one, day: monday, resource: studio, resourceId: "studio" }, elementProps }
time-grid dayHeaderNormalized day, covered semantic columns, and prepared string title.{ day: monday, columns: [{ day: monday, resource: studio, resourceId: "studio" }], title: "Mon 14" }
time-grid resourceHeaderConcrete resource, its identity, covered semantic columns, and prepared React title.{ resource: studio, resourceId: "studio", columns: [studioColumn], title: "Studio" }
import type { TimeGridEventProps } from "@chronolanejs/react";

function MeetingEvent({ event, segment, selected, elementProps }: TimeGridEventProps<Meeting, Room>) {
    return (
        <div
            {...elementProps}
            data-resource-id={segment.resourceId ?? undefined}
            data-selected={selected || undefined}
        >
            <strong>{event.title}</strong>
            <span>{event.owner.name}</span>
        </div>
    );
}

See Accessibility before replacing interactive renderers.