calendar-tsx

Rendering parts

Props on parts, and swapping a part's element with render.

Props

Every part accepts the props of its element. They merge with the part's own:

  • Most props: yours win, so you can replace role, aria-label or type.
  • className: joined.
  • style: shallow-merged, so you can add styles without losing the --cal-* geometry.
  • Event handlers: yours are attached as given. On day triggers yours runs before the navigation, so preventDefault() can skip it.
export const ColoredEvent = ({ segment }: { segment: Calendar_TimeGridSegment<Booking> }) => (
  <TimeGridViewEvent segment={segment} className='event' style={{ background: segment.event.data.color }}>
    {segment.event.data.title}
  </TimeGridViewEvent>
);

Parts forward ref to their element.

render

render swaps the element a part renders. It takes an element or a function.

An element

The part's props are merged into the element, with the same rules as above; the element's own props win.

export const LinkedEvent = ({ event }: { event: Calendar_Event<Booking> }) => (
  <ListViewEvent event={event} render={<a href={`/bookings/${event.id}`} />}>
    {event.data.title}
  </ListViewEvent>
);

The element receives the part's attributes, geometry, children and ref, so a router link or a design-system button keeps working layout.

A function

render(props, state) receives the part's props, including children, and its state: the model you passed in (the segment, day, column, …). Spread the props yourself:

export const TitledDay = ({ day }: { day: Calendar_DayGridDay<Booking> }) => (
  <DayGridViewDay day={day} render={(props, state) => <div {...props} title={state.isToday ? 'Today' : undefined} />} />
);

The function may return any React node, including a fragment or null. Only the ref is composed for you; everything else is applied as you spread it.