Skip to content
weftGitHub

Calendar

A full calendar with month, week, day, agenda, timeline and year views.

SourcePackage @weft-js/warp

Preview

tsx
import { state } from '@weft-js/core'import { Calendar } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function Week() {  const s = useEvents()  return <Calendar events={s.events.value} calendars={CALENDARS} defaultView="week" defaultDate={CAL_TODAY} today={CAL_TODAY} now={CAL_NOW} locale="en-US" firstDayOfWeek={1} workingHours={[540, 1080]} onMove={s.change} onResize={s.change} onCreate={s.create} onEdit={s.edit} onDelete={s.remove} />}const CAL_TODAY = '2026-11-02'const CAL_NOW = '2026-11-04T10:40'const CALENDARS = ['Releases', 'On-call', 'Team', 'Customers'].map((name, i) => ({ id: i + 1, name }))const EVENTS: CalEvent[] = [  { id: 'e1', title: 'Standup', start: '2026-11-02T09:30', end: '2026-11-02T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e2', title: 'Standup', start: '2026-11-03T09:30', end: '2026-11-03T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e3', title: 'Standup', start: '2026-11-04T09:30', end: '2026-11-04T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e4', title: 'Standup', start: '2026-11-05T09:30', end: '2026-11-05T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e5', title: 'Standup', start: '2026-11-06T09:30', end: '2026-11-06T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e6', title: 'Ship checkout to production', start: '2026-11-02T11:00', end: '2026-11-02T12:00', cal: 1, location: 'Room Atlas', attendees: ['Tomás Oliveira', 'Mara Lindqvist'], resource: 'atlas' },  { id: 'e7', title: 'Search ranking review', start: '2026-11-03T14:00', end: '2026-11-03T15:30', cal: 3, attendees: ['Lena Fischer', 'Noor Haddad'], video: true, resource: 'birch' },  { id: 'e8', title: 'Acme onboarding', start: '2026-11-04T10:00', end: '2026-11-04T11:00', cal: 4, video: true, attendees: ['Priya Raman'] },  { id: 'e9', title: 'Incident review: mobile-bff', start: '2026-11-04T10:30', end: '2026-11-04T11:30', cal: 2, attendees: ['Sam Okafor', 'Jun Tanaka'], resource: 'cedar' },  { id: 'e10', title: 'Rotate edge certificates', start: '2026-11-05T13:00', end: '2026-11-05T14:00', cal: 2, locked: true, location: 'Do not move' },  { id: 'e11', title: 'Northwind renewal', start: '2026-11-05T15:00', end: '2026-11-05T16:00', cal: 4, tentative: true, location: 'Waiting on Inés' },  { id: 'e12', title: 'Release retro', start: '2026-11-06T11:00', end: '2026-11-06T12:00', cal: 1, video: true, resource: 'atlas' },  { id: 'e13', title: 'Design crit', start: '2026-11-04T09:00', end: '2026-11-04T10:00', cal: 3, resource: 'atlas' },  { id: 'e14', title: 'Hiring sync', start: '2026-11-04T13:00', end: '2026-11-04T14:30', cal: 3, resource: 'atlas' },  { id: 'e15', title: 'Billing walkthrough', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 4, resource: 'birch' },  { id: 'e16', title: 'Roadmap', start: '2026-11-04T15:00', end: '2026-11-04T16:30', cal: 3, resource: 'cedar' },  { id: 'a1', title: 'Jun on call', start: '2026-11-02', end: '2026-11-04', allDay: true, cal: 2 },  { id: 'a2', title: 'Release 2026.11', start: '2026-11-06', end: '2026-11-06', allDay: true, cal: 1 },]type Event = (typeof EVENTS)[number]function useEvents() {  const events = state<Event[]>(EVENTS)  const change = (e: Event, to: Partial<Event>) => { events.value = events.value.map(x => (x.id === e.id ? { ...x, ...to } : x)) }  return {    events,    change,    create: (e: Event) => (events.value = [...events.value, e]),    edit: (e: Event) => change(e, e),    remove: (e: Event) => (events.value = events.value.filter(x => x.id !== e.id)),  }}

Installation

npm install @weft-js/warp

Usage

tsx
import { Calendar } from '@weft-js/warp'

Views

Read-only month

views limits the tabs and readOnly turns off every edit.

tsx
import { Calendar } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function Month() {  return (    <Calendar events={EVENTS} calendars={CALENDARS} views={[...COMPACT_VIEWS]} defaultView="month" defaultDate={CAL_TODAY} today={CAL_TODAY} now={CAL_NOW} locale="en-US" firstDayOfWeek={1} readOnly />  )}const CAL_TODAY = '2026-11-02'const CAL_NOW = '2026-11-04T10:40'const CALENDARS = ['Releases', 'On-call', 'Team', 'Customers'].map((name, i) => ({ id: i + 1, name }))const EVENTS: CalEvent[] = [  { id: 'e1', title: 'Standup', start: '2026-11-02T09:30', end: '2026-11-02T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e2', title: 'Standup', start: '2026-11-03T09:30', end: '2026-11-03T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e3', title: 'Standup', start: '2026-11-04T09:30', end: '2026-11-04T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e4', title: 'Standup', start: '2026-11-05T09:30', end: '2026-11-05T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e5', title: 'Standup', start: '2026-11-06T09:30', end: '2026-11-06T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e6', title: 'Ship checkout to production', start: '2026-11-02T11:00', end: '2026-11-02T12:00', cal: 1, location: 'Room Atlas', attendees: ['Tomás Oliveira', 'Mara Lindqvist'], resource: 'atlas' },  { id: 'e7', title: 'Search ranking review', start: '2026-11-03T14:00', end: '2026-11-03T15:30', cal: 3, attendees: ['Lena Fischer', 'Noor Haddad'], video: true, resource: 'birch' },  { id: 'e8', title: 'Acme onboarding', start: '2026-11-04T10:00', end: '2026-11-04T11:00', cal: 4, video: true, attendees: ['Priya Raman'] },  { id: 'e9', title: 'Incident review: mobile-bff', start: '2026-11-04T10:30', end: '2026-11-04T11:30', cal: 2, attendees: ['Sam Okafor', 'Jun Tanaka'], resource: 'cedar' },  { id: 'e10', title: 'Rotate edge certificates', start: '2026-11-05T13:00', end: '2026-11-05T14:00', cal: 2, locked: true, location: 'Do not move' },  { id: 'e11', title: 'Northwind renewal', start: '2026-11-05T15:00', end: '2026-11-05T16:00', cal: 4, tentative: true, location: 'Waiting on Inés' },  { id: 'e12', title: 'Release retro', start: '2026-11-06T11:00', end: '2026-11-06T12:00', cal: 1, video: true, resource: 'atlas' },  { id: 'e13', title: 'Design crit', start: '2026-11-04T09:00', end: '2026-11-04T10:00', cal: 3, resource: 'atlas' },  { id: 'e14', title: 'Hiring sync', start: '2026-11-04T13:00', end: '2026-11-04T14:30', cal: 3, resource: 'atlas' },  { id: 'e15', title: 'Billing walkthrough', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 4, resource: 'birch' },  { id: 'e16', title: 'Roadmap', start: '2026-11-04T15:00', end: '2026-11-04T16:30', cal: 3, resource: 'cedar' },  { id: 'a1', title: 'Jun on call', start: '2026-11-02', end: '2026-11-04', allDay: true, cal: 2 },  { id: 'a2', title: 'Release 2026.11', start: '2026-11-06', end: '2026-11-06', allDay: true, cal: 1 },]const COMPACT_VIEWS = ['month', 'agenda'] as const

Rooms timeline

resources adds the rows, and events point at one with resource. timeline sets the hours it spans.

tsx
import { state } from '@weft-js/core'import { Calendar } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function Rooms() {  const s = useEvents()  return <Calendar events={s.events.value} calendars={CALENDARS} resources={ROOMS} views={[...ROOM_VIEWS]} timeline={ROOM_HOURS} defaultView="timeline" defaultDate="2026-11-04" today={CAL_TODAY} now={CAL_NOW} locale="en-US" onMove={s.change} onResize={s.change} />}const CAL_TODAY = '2026-11-02'const CAL_NOW = '2026-11-04T10:40'const CALENDARS = ['Releases', 'On-call', 'Team', 'Customers'].map((name, i) => ({ id: i + 1, name }))const ROOMS = [{ id: 'atlas', name: 'Atlas', meta: '8 seats' }, { id: 'birch', name: 'Birch', meta: '6 seats' }, { id: 'cedar', name: 'Cedar', meta: '12 seats' }]const EVENTS: CalEvent[] = [  { id: 'e1', title: 'Standup', start: '2026-11-02T09:30', end: '2026-11-02T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e2', title: 'Standup', start: '2026-11-03T09:30', end: '2026-11-03T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e3', title: 'Standup', start: '2026-11-04T09:30', end: '2026-11-04T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e4', title: 'Standup', start: '2026-11-05T09:30', end: '2026-11-05T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e5', title: 'Standup', start: '2026-11-06T09:30', end: '2026-11-06T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e6', title: 'Ship checkout to production', start: '2026-11-02T11:00', end: '2026-11-02T12:00', cal: 1, location: 'Room Atlas', attendees: ['Tomás Oliveira', 'Mara Lindqvist'], resource: 'atlas' },  { id: 'e7', title: 'Search ranking review', start: '2026-11-03T14:00', end: '2026-11-03T15:30', cal: 3, attendees: ['Lena Fischer', 'Noor Haddad'], video: true, resource: 'birch' },  { id: 'e8', title: 'Acme onboarding', start: '2026-11-04T10:00', end: '2026-11-04T11:00', cal: 4, video: true, attendees: ['Priya Raman'] },  { id: 'e9', title: 'Incident review: mobile-bff', start: '2026-11-04T10:30', end: '2026-11-04T11:30', cal: 2, attendees: ['Sam Okafor', 'Jun Tanaka'], resource: 'cedar' },  { id: 'e10', title: 'Rotate edge certificates', start: '2026-11-05T13:00', end: '2026-11-05T14:00', cal: 2, locked: true, location: 'Do not move' },  { id: 'e11', title: 'Northwind renewal', start: '2026-11-05T15:00', end: '2026-11-05T16:00', cal: 4, tentative: true, location: 'Waiting on Inés' },  { id: 'e12', title: 'Release retro', start: '2026-11-06T11:00', end: '2026-11-06T12:00', cal: 1, video: true, resource: 'atlas' },  { id: 'e13', title: 'Design crit', start: '2026-11-04T09:00', end: '2026-11-04T10:00', cal: 3, resource: 'atlas' },  { id: 'e14', title: 'Hiring sync', start: '2026-11-04T13:00', end: '2026-11-04T14:30', cal: 3, resource: 'atlas' },  { id: 'e15', title: 'Billing walkthrough', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 4, resource: 'birch' },  { id: 'e16', title: 'Roadmap', start: '2026-11-04T15:00', end: '2026-11-04T16:30', cal: 3, resource: 'cedar' },  { id: 'a1', title: 'Jun on call', start: '2026-11-02', end: '2026-11-04', allDay: true, cal: 2 },  { id: 'a2', title: 'Release 2026.11', start: '2026-11-06', end: '2026-11-06', allDay: true, cal: 1 },]type Event = (typeof EVENTS)[number]function useEvents() {  const events = state<Event[]>(EVENTS)  const change = (e: Event, to: Partial<Event>) => { events.value = events.value.map(x => (x.id === e.id ? { ...x, ...to } : x)) }  return {    events,    change,    create: (e: Event) => (events.value = [...events.value, e]),    edit: (e: Event) => change(e, e),    remove: (e: Event) => (events.value = events.value.filter(x => x.id !== e.id)),  }}const ROOM_VIEWS = ['timeline', 'day'] as constconst ROOM_HOURS: [number, number] = [540, 1020]

Overlapping meetings

Events that overlap share the column in lanes, so none hides another. Switch to Week to see the same morning beside the rest.

tsx
import { state } from '@weft-js/core'import { Calendar } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function BusyDay() {  const s = useEvents()  return <Calendar events={s.events.value} calendars={CALENDARS} views={[...DAY_VIEWS]} defaultView="day" defaultDate="2026-11-04" today={CAL_TODAY} now={CAL_NOW} locale="en-US" firstDayOfWeek={1} workingHours={[540, 1080]} onMove={s.change} onResize={s.change} />}const CAL_TODAY = '2026-11-02'const CAL_NOW = '2026-11-04T10:40'const CALENDARS = ['Releases', 'On-call', 'Team', 'Customers'].map((name, i) => ({ id: i + 1, name }))const EVENTS: CalEvent[] = [  { id: 'e1', title: 'Standup', start: '2026-11-02T09:30', end: '2026-11-02T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e2', title: 'Standup', start: '2026-11-03T09:30', end: '2026-11-03T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e3', title: 'Standup', start: '2026-11-04T09:30', end: '2026-11-04T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e4', title: 'Standup', start: '2026-11-05T09:30', end: '2026-11-05T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e5', title: 'Standup', start: '2026-11-06T09:30', end: '2026-11-06T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e6', title: 'Ship checkout to production', start: '2026-11-02T11:00', end: '2026-11-02T12:00', cal: 1, location: 'Room Atlas', attendees: ['Tomás Oliveira', 'Mara Lindqvist'], resource: 'atlas' },  { id: 'e7', title: 'Search ranking review', start: '2026-11-03T14:00', end: '2026-11-03T15:30', cal: 3, attendees: ['Lena Fischer', 'Noor Haddad'], video: true, resource: 'birch' },  { id: 'e8', title: 'Acme onboarding', start: '2026-11-04T10:00', end: '2026-11-04T11:00', cal: 4, video: true, attendees: ['Priya Raman'] },  { id: 'e9', title: 'Incident review: mobile-bff', start: '2026-11-04T10:30', end: '2026-11-04T11:30', cal: 2, attendees: ['Sam Okafor', 'Jun Tanaka'], resource: 'cedar' },  { id: 'e10', title: 'Rotate edge certificates', start: '2026-11-05T13:00', end: '2026-11-05T14:00', cal: 2, locked: true, location: 'Do not move' },  { id: 'e11', title: 'Northwind renewal', start: '2026-11-05T15:00', end: '2026-11-05T16:00', cal: 4, tentative: true, location: 'Waiting on Inés' },  { id: 'e12', title: 'Release retro', start: '2026-11-06T11:00', end: '2026-11-06T12:00', cal: 1, video: true, resource: 'atlas' },  { id: 'e13', title: 'Design crit', start: '2026-11-04T09:00', end: '2026-11-04T10:00', cal: 3, resource: 'atlas' },  { id: 'e14', title: 'Hiring sync', start: '2026-11-04T13:00', end: '2026-11-04T14:30', cal: 3, resource: 'atlas' },  { id: 'e15', title: 'Billing walkthrough', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 4, resource: 'birch' },  { id: 'e16', title: 'Roadmap', start: '2026-11-04T15:00', end: '2026-11-04T16:30', cal: 3, resource: 'cedar' },  { id: 'a1', title: 'Jun on call', start: '2026-11-02', end: '2026-11-04', allDay: true, cal: 2 },  { id: 'a2', title: 'Release 2026.11', start: '2026-11-06', end: '2026-11-06', allDay: true, cal: 1 },]type Event = (typeof EVENTS)[number]function useEvents() {  const events = state<Event[]>(EVENTS)  const change = (e: Event, to: Partial<Event>) => { events.value = events.value.map(x => (x.id === e.id ? { ...x, ...to } : x)) }  return {    events,    change,    create: (e: Event) => (events.value = [...events.value, e]),    edit: (e: Event) => change(e, e),    remove: (e: Event) => (events.value = events.value.filter(x => x.id !== e.id)),  }}const DAY_VIEWS = ['day', 'week'] as const

Agenda of the week

The same events as a list, day by day: what a phone or a quick look wants.

tsx
import { Calendar } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function Agenda() {  return (    <Calendar events={EVENTS} calendars={CALENDARS} views={[...AGENDA_VIEWS]} defaultView="agenda" defaultDate={CAL_TODAY} today={CAL_TODAY} now={CAL_NOW} locale="en-US" firstDayOfWeek={1} readOnly />  )}const CAL_TODAY = '2026-11-02'const CAL_NOW = '2026-11-04T10:40'const CALENDARS = ['Releases', 'On-call', 'Team', 'Customers'].map((name, i) => ({ id: i + 1, name }))const EVENTS: CalEvent[] = [  { id: 'e1', title: 'Standup', start: '2026-11-02T09:30', end: '2026-11-02T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e2', title: 'Standup', start: '2026-11-03T09:30', end: '2026-11-03T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e3', title: 'Standup', start: '2026-11-04T09:30', end: '2026-11-04T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e4', title: 'Standup', start: '2026-11-05T09:30', end: '2026-11-05T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e5', title: 'Standup', start: '2026-11-06T09:30', end: '2026-11-06T09:45', cal: 3, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR' },  { id: 'e6', title: 'Ship checkout to production', start: '2026-11-02T11:00', end: '2026-11-02T12:00', cal: 1, location: 'Room Atlas', attendees: ['Tomás Oliveira', 'Mara Lindqvist'], resource: 'atlas' },  { id: 'e7', title: 'Search ranking review', start: '2026-11-03T14:00', end: '2026-11-03T15:30', cal: 3, attendees: ['Lena Fischer', 'Noor Haddad'], video: true, resource: 'birch' },  { id: 'e8', title: 'Acme onboarding', start: '2026-11-04T10:00', end: '2026-11-04T11:00', cal: 4, video: true, attendees: ['Priya Raman'] },  { id: 'e9', title: 'Incident review: mobile-bff', start: '2026-11-04T10:30', end: '2026-11-04T11:30', cal: 2, attendees: ['Sam Okafor', 'Jun Tanaka'], resource: 'cedar' },  { id: 'e10', title: 'Rotate edge certificates', start: '2026-11-05T13:00', end: '2026-11-05T14:00', cal: 2, locked: true, location: 'Do not move' },  { id: 'e11', title: 'Northwind renewal', start: '2026-11-05T15:00', end: '2026-11-05T16:00', cal: 4, tentative: true, location: 'Waiting on Inés' },  { id: 'e12', title: 'Release retro', start: '2026-11-06T11:00', end: '2026-11-06T12:00', cal: 1, video: true, resource: 'atlas' },  { id: 'e13', title: 'Design crit', start: '2026-11-04T09:00', end: '2026-11-04T10:00', cal: 3, resource: 'atlas' },  { id: 'e14', title: 'Hiring sync', start: '2026-11-04T13:00', end: '2026-11-04T14:30', cal: 3, resource: 'atlas' },  { id: 'e15', title: 'Billing walkthrough', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 4, resource: 'birch' },  { id: 'e16', title: 'Roadmap', start: '2026-11-04T15:00', end: '2026-11-04T16:30', cal: 3, resource: 'cedar' },  { id: 'a1', title: 'Jun on call', start: '2026-11-02', end: '2026-11-04', allDay: true, cal: 2 },  { id: 'a2', title: 'Release 2026.11', start: '2026-11-06', end: '2026-11-06', allDay: true, cal: 1 },]const AGENDA_VIEWS = ['agenda', 'week'] as const

When to use

Use it for

  • People read and change a schedule of events
  • Events move, resize or get created by dragging

Reach for something else

Accessibility

Tab
Moves between the toolbar, the views and the events
M
On a focused event: starts moving it with the arrow keys
Enter
Opens the focused event
  • Every drag has a keyboard route, and the event editor can change the same fields without dragging.
  • Pass today and now to keep the server and browser in step. Without them they arrive after the page loads.

API Reference

PropTypeDefaultDescription
eventsCalEvent[]—The events to show. You own this list.
calendarsCalendarSource[]—The named sources in the side rail.
viewCalView | State<CalView>—The view showing: a State to share it, or a value.
defaultViewCalView—The view it opens on when view isn't given. Week without either.
viewsCalView[]—The views offered as tabs, in this order. All six without it.
datestring | State<string>—The date the view is on (2026-11-04): a State to share it, or a value.
defaultDatestring—The date it opens on when date isn't given. Today without either.
timeZonestring | State<string | null>—The toolbar chip's zone. Without one, wall times show as they are.
zones{ label: string; zone: string; }[]—Secondary zones in the rail.
todaystring—Today's date (2026-11-02), marked in every view. The browser's date after mount without it, so hydration writes nothing.
nowstring—The now line's wall time; the browser's clock after mount without it.
localestring—The locale for day and month names, times and the first day of the week. The browser's without it.
hourCyclestring—h12 or h23 to force a clock; the locale's without it.
firstDayOfWeeknumber—The week's first day, 0 for Sunday to 6 for Saturday. The locale's without it.
snapnumber—Minutes a drag or resize snaps to. 15 without it.
workingHours[number, number]—The start and end of the working day, in minutes from midnight: [540, 1080] is 09:00 to 18:00. The rest is shaded.
liveLiveState—The toolbar LiveStatus.
resourcesResource[]—Timeline rows; events point at one with resource.
timeline[number, number]—The hours the timeline spans, in minutes from midnight.
countsRecord<string, number>—Year view's counts; from events without it.
readOnlybooleanfalseTurns off dragging, resizing, creating and the keyboard move mode. Events still open their popover.
EventTypeDefaultDescription
onViewChange((v: CalView) => void)—Hears every change of view, by tab, key or the mini month.
onDateChange((d: string) => void)—Hears the new date when the arrows, Today, the mini month or a drill-in move it.
onTimeZoneChange((z: string | null) => void)—Hears a zone picked from the toolbar chip, or null for wall times.
onMove((e: CalEvent, to: EventChange, reason: Reason) => void | Promise<unknow…—Called with the event and its new times. Return a rejected promise to put it back.
onResize((e: CalEvent, to: EventChange, reason: Reason) => void | Promise<unknow…—An event's edge dragged to a new time. A rejected promise puts it back and announces why.
onCreate((e: CalEvent) => void)—A new event saved from the editor, after a drag over empty time, a press on a slot or New event.
onEdit((e: CalEvent, scope?: RecurrenceScope | undefined) => void)—An event saved from the editor; scope says which of a repeating event's occurrences.
onDelete((e: CalEvent, scope?: RecurrenceScope | undefined) => void)—An event deleted after its confirmation; scope says which of a repeating event's occurrences.
onOpen((e: CalEvent) => void)—An event's popover opened, by press or Enter.
onJoin((e: CalEvent) => void)—Join pressed in the popover of an event with a video link.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="calendar"] [data-part="root"]

rootapp-barapp-titlerange-labelspacerlisttriggerindicatorlayoutraileyebrowsourcesmainyear-wrap

RelatedInline calendarDate fieldRecurrence field