Event Calendar

Events on a month grid, a week or a day of hours, or an agenda list, with Today, previous and next.
Beta
Web
iOS
Android
@advui/data
Source

Month

October 2026

Installation

pnpm
pnpm add @advui/data
npm
npm install @advui/data

Usage

import { EventCalendar } from '@advui/data'

<EventCalendar
  events={[
    { id: 'standup', title: 'Team standup', start: new Date(2026, 9, 28, 9), end: new Date(2026, 9, 28, 9, 30) },
  ]}
  onEventPress={(event) => open(event.id)}
/>

Examples

Week

Starts on Monday; events that overlap share the day’s width. Drag an event, or its bottom edge, to change it; a line marks the current time.
Oct 26 – Nov 1, 2026
Up and Down arrows move it by 15 minutes, Left and Right to another day. With Shift, Up and Down change when it ends.
Press an event to open it, or drag it to move it.

Agenda

A list of the month’s days with events, which suits phones.
October 2026
Thu, Oct 1
5W round kickoff, Thursday, October 1, 2026, 10:00 AM to 11:00 AM
Wed, Oct 7
Data review, Wednesday, October 7, 2026, 2:00 PM to 3:00 PM
Mon, Oct 12
Field visit: Bago, All day, Monday, October 12, 2026 to Wednesday, October 14, 2026
Tue, Oct 13
Field visit: Bago, All day, Monday, October 12, 2026 to Wednesday, October 14, 2026
Wed, Oct 14
Field visit: Bago, All day, Monday, October 12, 2026 to Wednesday, October 14, 2026
Fri, Oct 16
Kobo training, Friday, October 16, 2026, 9:00 AM to 12:00 PM
Fri, Oct 23
Submissions close, All day, Friday, October 23, 2026
Wed, Oct 28
Team standup, Wednesday, October 28, 2026, 9:00 AM to 9:30 AM
Map review, Wednesday, October 28, 2026, 11:00 AM to 12:00 PM

API reference

EventCalendar

PropTypeDefaultDescription
events requiredreadonly CalendarEvent[]—`{ id, title, start, end?, allDay?, tone? }` events.
view'month' | 'week' | 'day' | 'agenda'—The view shown.
defaultView'month' | 'week' | 'day' | 'agenda''month'Starting `view` when uncontrolled.
onViewChange(view: EventCalendarView) => void—Called with the new `view`.
viewsEventCalendarView[]['month', 'week', 'day', 'agenda']The views to switch between, in order. With one, there is no switcher.
dateDate—A day in the shown month, week or day.
defaultDateDate—Starting `date` when uncontrolled. Default: today.
onDateChange(date: Date) => void—Called with the new `date`: previous, next, Today, or a day opened.
onEventPress(event: CalendarEvent) => void—Makes events buttons. Without it they are text.
onEventChange(change: CalendarEventChange) => void—Makes timed events in the week and day views movable: drag one to another time or day (a long press first on touch screens), its bottom edge to change when it ends, or use the arrow keys or screen reader actions. Called with `{ event, start, end }`: update `events` with them.
snapMinutesnumber15Minutes that moved times snap to, from midnight.
nowDate—The time on the line across today in the week and day views. Default: the clock, each minute, from after the first render.
onDatePress(date: Date) => void—A month day’s number or a week day’s heading was pressed. With the day view in `views`, that day opens there too.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 60First day of the week: 0 is Sunday, 1 Monday.
localestring—BCP 47 locale for dates and times. Defaults to the device locale.
todayDate—Overrides today, for tests and screenshots.
maxEventsPerDaynumber3Lines a month day shows: its events, or fewer and “+2 more”.
timeGridHeightSizeTokens | number'128'Height of the scrolling hours in the week and day views.
scrollToHournumber8The hour at the top when the week or day view opens.
labelsPartial<EventCalendarLabels>—Button names and words, such as `today`, `nextMonth`, `allDay` and `more(count)`, for other languages.

CalendarEvent

One event.
PropTypeDefaultDescription
id requiredstring—Unique key.
title requiredstring—Shown and read.
start requiredDate—When it starts.
endDate—When it ends: default an hour after `start`. For an all-day event, its last day.
allDayboolean—Fills whole days; shown above the hours in the week and day views.
tone'primary' | 'success' | 'warning' | 'error' | 'info' | 'neutral''primary'Color, as a soft fill with its text color.
readOnlyboolean—Not moved or resized, even with `onEventChange`.

Accessibility

  • The month is a table named by its month, with a column header per weekday; each day is a cell (web).
  • A day’s number is a button named with its date and event count (“Wednesday, October 28, 2026, 4 events”), with aria-current="date" for today; iOS and Android add “today” to the name.
  • Events are buttons when onEventPress is set, named with their title, day and times (“Team standup, Wednesday, October 28, 2026, 9:00 AM to 9:30 AM”); otherwise that name is hidden text.
  • In the week and day views each day is a group named by its date (web), holding its events in time order. The time gutter is hidden.
  • With onEventChange, timed events in the week and day views are buttons even without onEventPress, described by how to move them with the keyboard (web). Each change is announced with the event’s new name. On iOS and Android they have actions instead: “Move 15 minutes earlier”, “Move to Thursday”, “End 15 minutes later”…
  • The current-time line is hidden from screen readers.
  • The title is a polite live region, so moving by month, week or day is announced. The view switcher is a Toggle Group (radiogroup).
  • On phones a month day shows dots for its events, hidden from screen readers: its name counts them, and its number opens the day.
Keyboard interactions
KeyAction
TabMoves through the toolbar, then the days and events in order.
Enter / SpaceOpens a day or presses an event.
Arrow keysMove between views in the switcher.
Up / DownWith `onEventChange`, move a focused event `snapMinutes` earlier or later.
Left / RightMove a focused event to the day before or after, if shown.
Shift + Up / DownEnd a focused event earlier or later.
EscapePuts an event that is being dragged back.

Responsive behavior

Below sm a month day shows dots instead of event titles; the agenda view lists them in full.

Platform notes

Web
The days and the all-day row stay pinned above the hours with position: sticky. A mouse drags an event once it moves, a finger after holding still for a moment; near the top or bottom of the hours a drag scrolls them.
iOS
The week and day views are a ScrollView whose header is pinned (stickyHeaderIndices), scrolled to scrollToHour once laid out. iOS has no table roles: days and events are buttons. A long press picks an event up (near its bottom edge, its end), and the hours and the ScrollArea around them stop scrolling until the finger lifts, so a drag reaches the hours in view. Not yet checked on a device.
Android
Same as iOS, with the ripple on events when the config has androidRipple.
Since v0.14.0Last updated Nov 2, 2026Edit this page on GitHub