A full calendar surface for mobile: a collapsible month calendar on top of a horizontally paged day / week / month body with draggable, resizable events.
Agenda uses @internationalized/date for all date values (CalendarDate for days, CalendarDateTime for event start/end). Event drag-and-drop requires the optional peer dependency react-native-reanimated-dnd; without it, events render but cannot be moved or resized.
Every level has a default: a childless <Agenda {...agenda} /> renders the full composition above; a childless Agenda.Body renders the whole default page template; a childless Agenda.TimeGrid renders the day columns and the current time indicator; a childless Agenda.DayColumns renders default Agenda.Event cards; a childless Agenda.Calendar renders the prewired calendar.
Agenda: Root container. Receives the useAgenda(options) state as spread props and wraps everything in a SplitView whose snap points derive from the measured header content (collapsed week row / fully expanded calendar).
Agenda.Header: Top SplitView pane. Measures its natural content height, so anything placed under the calendar automatically expands the snap points.
Agenda.Calendar: Month calendar (with year picker) bound to the agenda date. Collapses to the week row containing the selected date at the minimum snap point. Children compose the calendar anatomy from raw Calendar.* parts plus the two Agenda-measured wrappers below.
Agenda.CalendarHeader: Measured wrapper around Calendar.Header; children compose the header content (year picker trigger, nav buttons, Today button).
Agenda.CalendarGrid: Measured, collapse-animated month grid wrapping Calendar.Grid. Optional render-function children customize day cells via Calendar.GridBody's own API; the default cell shows an event-coverage indicator.
Agenda.Heading: Localized month + year title for the active date.
Agenda.TodayButton: Compact outline button that jumps to today and collapses the header.
Agenda.NavButton: Previous / next agenda navigation (slot="previous" | "next"); steps a day, week, or month depending on the current view and collapses the header.
Agenda.DragArea / Agenda.DragHandle: SplitView drag region and pill between the header and the body.
Agenda.Body: Horizontally paged day / week / month area inside the bottom SplitView pane, kept in sync with the calendar. Children act as the page template, rendered once per pager page under the page context; all collection parts self-gate by the page's view, so one template covers every view.
Agenda.WeekHeader: Weekday letters row above the time grid on week pages (showDates switches to full names + tappable date pills).
Agenda.AllDaySection: Packed all-day bars above the time grid. Children act as the per-event template (event available via useAgendaEvent()).
Agenda.TimeGrid: Vertically scrollable hour grid with the time gutter, hour lines, and drag drop-guides. Scroll offset is synchronized across pages. Children compose the grid content.
Agenda.DayColumns: One column per page day. Children act as the per-event template; the default is Agenda.Event.
Agenda.Event: The positioned, draggable, resizable event card. Reads the event from the template context (or an explicit event prop). Children customize the card content; the default renders the color tint, accent bar, title, and time.
Agenda.EventTitle / Agenda.EventTime: Text parts bound to the template context event.
Agenda.CurrentTimeIndicator: Live time badge + line + notch, rendered only on day/week pages containing today.
Agenda.MonthGrid: Six week rows with multi-day spanning bars and per-cell event chips (maxEventsPerCell, moreLabel). Children act as the per-event chip content template.
Agenda.ViewSelector: Floating day / week / month selector built on Segment, absolutely positioned at the bottom-center by default. Exposes Group / Indicator / Item / Label / Separator for custom compositions.
The only required option is events. The Agenda never mutates the array — apply move/resize intents back into your state. Event start/end values are CalendarDateTime objects from @internationalized/date.
import type { CalendarDateTime } from '@internationalized/date';import { Agenda, useAgenda, type AgendaEvent } from 'heroui-native-pro';const [events, setEvents] = useState<AgendaEvent[]>(initialEvents);const applyChange = (id: string, start: CalendarDateTime, end: CalendarDateTime) => { setEvents((prev) => prev.map((event) => (event.id === id ? { ...event, start, end } : event)) );};const agenda = useAgenda({ events, onEventMove: applyChange, onEventResize: applyChange,});<Agenda {...agenda} />;
The hook return is also your window into the agenda from outside the component tree: read agenda.heading, agenda.selectedEventId, or agenda.visibleDays, and drive it with agenda.setView, agenda.setDate, or agenda.goToToday from any surrounding UI.
Events are plain objects built with @internationalized/date helpers. color tints the event chip, all-day events render as bars (day/week) or spanning month rows, read-only events cannot be moved or resized, and "unconfirmed" renders a dashed border. Dates follow the half-open [start, end) convention: an event ending at midnight does not cover the following day, so a one-day all-day event spans from midnight to the next day's midnight.
import { getLocalTimeZone, Time, toCalendarDateTime, today,} from '@internationalized/date';import type { AgendaEvent } from 'heroui-native-pro';const event: AgendaEvent = { id: 'standup', title: 'Daily standup', start: toCalendarDateTime(today(getLocalTimeZone()), new Time(10, 30)), end: toCalendarDateTime(today(getLocalTimeZone()), new Time(11, 0)), color: '#3b82f6', isAllDay: false, isReadOnly: false, status: 'confirmed',};
Control the view mode and active date externally with view / onViewChange and date / onDateChange. The active date is a CalendarDate from @internationalized/date.
By default, pressing an event toggles the internal selection (selectedEventId / onEventSelect). Provide onEventPress to replace the toggle with an app-level action such as opening a details screen.
Collection parts render their own data; their children act as a per-item template rendered with the event available through context. For fully bespoke items, read the event inside your own component with useAgendaEvent().
Agenda.Calendar composes like DatePicker.Calendar: children are raw Calendar.* parts, with Agenda.CalendarHeader and Agenda.CalendarGrid carrying the measurement / collapse machinery.
Two gradient overlays soften scrolling edges: the time grid's top fade (content scrolling under the grid's top edge) and the body's bottom fade (above the floating view selector). Each owner exposes three props — visibility, color, and height. Hide them with showBottomFade={false} (body) / showTopFade={false} (time grid). The colors default to the theme surface color, matching the body background.
Day cells are Calendar.Cell parts, so they expose the Calendar cell data attributes (data-today, data-selected, data-outside-month, ...) — see the Calendar documentation.
prop
type
default
description
children
(date: CalendarDate) => ReactElement
-
Day cell renderer matching Calendar.GridBody's API; defaults to Calendar.Cell with an event-coverage indicator
className
string
-
Additional CSS classes for the grid container
...ViewProps
ViewProps
-
All standard React Native View props are supported
Set on the day and date slots; target them with data-[...] Tailwind variants via classNames (e.g. classNames={{ date: 'data-[today=true]:bg-danger' }}).
attribute
values
description
data-today
boolean
Whether the column's date is today (day and date slots)
data-selected
boolean
Whether the column's date is the selected agenda date and not today (date slot)
Set on the container and resizeGrabber slots. The default styles use them for the selected accent border (data-[selected=true]:border-accent), the unconfirmed dashed border (data-[unconfirmed=true]:border-dashed), and the selected grabber fill (data-[selected=true]:bg-accent).
attribute
values
description
data-selected
boolean
Whether the event is selected (container and resizeGrabber slots)
data-unconfirmed
boolean
Whether the event's status is 'unconfirmed' (container slot)
Set on the cellDate slot. The default styles use them for the today pill (data-[today=true]:bg-accent), the selected pill (data-[selected=true]:bg-accent-soft), and the muted outside-month dates (data-[outside-month=true]:text-muted).
attribute
values
description
data-today
boolean
Whether the cell's date is today
data-selected
boolean
Whether the cell's date is the selected agenda date
data-outside-month
boolean
Whether the cell's date is outside the page's month
Extends the Segment API except the selection value, which is bound to the agenda view. Exposes Agenda.ViewSelector.Group / .Indicator / .Item / .Label / .Separator for custom compositions (item values must be AgendaView strings); Segment.ScrollView is intentionally not exposed.
prop
type
default
description
children
React.ReactNode
-
Custom Segment composition; defaults to a Group with an Indicator and one Item per option
options
AgendaView[]
['day', 'week', 'month']
Which views can be selected, in render order
labels
Partial<Record<AgendaView, string>>
{ day: 'Day', week: 'Week', month: 'Month' }
Custom labels per view
size
SegmentRootProps['size']
'sm'
Visual size of the underlying Segment
className
string
-
Additional CSS classes for the selector root; the default places it absolutely at the bottom-center
...SegmentRootProps
SegmentRootProps
-
All Segment root props are supported except value, defaultValue, and onValueChange