Examples
Agenda
A flat list of days with the events under each, and empty days left out.
An agenda
Two weeks as a flat list: one row per day that has something in it, with the all-day entries above the timed ones. There is no grid here at all, so as turns the whole thing into a real ul.
Running here
The component
Agenda.tsx
import { createCalendarComponents } from '@midstem/chronous-react' import type { CalendarRange, EventInput } from '@midstem/chronous-react' type EventData = { title: string } const Calendar = createCalendarComponents<EventData>() const RANGE: CalendarRange = { view: 'agenda', dayCount: 14, currentDate: '2026-03-18', timeZone: 'Europe/Kyiv', } const EVENTS: EventInput<EventData>[] = [ { id: 'offsite', start: '2026-03-18', end: '2026-03-20', data: { title: 'Offsite' }, }, { id: 'standup', start: '2026-03-18T09:00', duration: 'PT15M', recurrence: { rule: 'FREQ=WEEKLY;BYDAY=MO,WE,FR' }, data: { title: 'Standup' }, }, { id: 'review', start: '2026-03-19T14:00', end: '2026-03-19T15:30', data: { title: 'Design review' }, }, ] export const Agenda = (): JSX.Element => ( <Calendar.Root range={RANGE} events={EVENTS} locale="en-GB"> <Calendar.AgendaList as="ul" className="agenda"> <Calendar.AgendaDays as="li" className="agenda-day"> {({ weekdayLabel, dayLabel, monthLabel }) => ( <> <span className="agenda-date"> {weekdayLabel} {dayLabel} {monthLabel} </span> <span className="agenda-events"> <Calendar.AgendaAllDayEvents as="span" className="agenda-event"> {({ event }) => `${event.data?.title} · all-day`} </Calendar.AgendaAllDayEvents> <Calendar.AgendaTimedEvents as="span" className="agenda-event"> {({ event, timeRangeLabel }) => `${event.data?.title} · ${timeRangeLabel}` } </Calendar.AgendaTimedEvents> </span> </> )} </Calendar.AgendaDays> </Calendar.AgendaList> </Calendar.Root> )
The stylesheet
agenda.css
.agenda { margin: 0; padding: 0; list-style: none; color: #d8e5ff; } .agenda-day { display: flex; gap: 16px; padding: 12px 16px; border-top: 1px solid rgba(255, 255, 255, 0.08); } .agenda-date { flex: 0 0 120px; font-size: 13px; font-weight: 600; } .agenda-events { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: #8d8da0; }
Empty days
By default a day with nothing in it is skipped, which is what makes an agenda read as a list rather than as a calendar. Pass showEmptyDays to render the whole span instead.
tsx
import { Calendar } from '@midstem/chronous-react' import type { CalendarRange } from '@midstem/chronous-react' const range: CalendarRange = { view: 'agenda', dayCount: 7, currentDate: '2026-03-18', timeZone: 'Europe/Kyiv', } // Every day in the span, not only the ones that have something in them. export const Agenda = () => ( <Calendar.Root range={range} events={[]} locale="en-GB"> <Calendar.AgendaList as="ul" className="agenda"> <Calendar.AgendaDays as="li" className="agenda-day" showEmptyDays> {({ dayLabel, monthLabel }) => ( <span className="agenda-date"> {dayLabel} {monthLabel} </span> )} </Calendar.AgendaDays> </Calendar.AgendaList> </Calendar.Root> )
timeRangeLabel is formatted in the calendar’s locale before it reaches you — the same as every other name ending in Label, as Labels describes.