Event Calendar / Scheduler
Preview: Month
Month and week views of events, formatted in the React Aria locale. Events are buttons (keyboard reachable) labelled with title and time; a month day with more than three events gets a "+N more" button that expands the day in place.
Import
import { EventCalendar } from '@marbleui/ui'Props
<EventCalendar>
| Prop | Type | Default | Description |
|---|---|---|---|
| events *required | CalendarEvent[] | — | |
| className | string | — | |
| defaultDate | Date | new Date() | Any date inside the initial month/week. |
| defaultView | 'month' | 'week' | 'month' | |
| onEventPress | (e: CalendarEvent) => void | — | |
| weekStartsOn | 0 | 1 | 1 |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria Button. Follow the primitive's docs for the full keyboard map.
Usage notes
EventCalendar displays events in a month grid or a scrolling 24-hour week view, with Today, previous/next and a Month/Week switch. It only shows events; to pick a date use Calendar, and for task schedules use Gantt.
<EventCalendar
events={[
{ id: 'e1', title: 'Design review', start: new Date(2026, 9, 28, 14), end: new Date(2026, 9, 28, 15, 30), color: 7 },
{ id: 'e2', title: 'Company offsite', start: new Date(2026, 9, 30), end: new Date(2026, 9, 31), allDay: true, color: 4 },
]}
onEventPress={(event) => openEvent(event.id)}
/>
- Events use JS
Dates;colorpicks slot 1–8 (--chart-1…8).defaultDateanddefaultViewonly set the starting view, and there’s no callback for the visible range, so pass every event you may need.weekStartsOnis 1 (Monday, default) or 0 (Sunday). - Each event is a button named by its time and title (not its day).
onEventPressfires on click, Enter or Space. - Month view shows three events per day, then a “+N more” button that expands the day in place (and “Show less” to collapse it). Week view shows all-day events in a row above the hours (spanning each day they cover) and lays overlapping timed events out side by side. In month view, multi-day events appear only on their start day.
- Dates and times follow the React Aria locale (
LocaleProvider).
Example source · show· hide
import { useMemo, useState } from 'react'
import { EventCalendar, type CalendarEvent } from './event-calendar'
function useEvents() {
return useMemo(() => {
const now = new Date()
const at = (dayOffset: number, h: number, m = 0, dur = 60) => {
const s = new Date(now.getFullYear(), now.getMonth(), now.getDate() + dayOffset, h, m)
return { start: s, end: new Date(+s + dur * 60000) }
}
const list: CalendarEvent[] = [
{ id: '1', title: 'Standup', ...at(0, 9, 30, 15), color: 1 },
{ id: '2', title: 'Design review', ...at(0, 14, 0, 90), color: 7 },
{ id: '3', title: 'Lunch with Maya', ...at(1, 12, 30, 60), color: 3 },
{ id: '4', title: 'Release v2.4', ...at(2, 16, 0, 30), color: 2 },
{ id: '5', title: 'Planning', ...at(-2, 10, 0, 120), color: 1 },
{ id: '6', title: '1:1 Charles', ...at(3, 11, 0, 30), color: 5 },
{ id: '7', title: 'Offsite', ...at(8, 9, 0, 480), color: 4 },
{ id: '8', title: 'Board update', ...at(-6, 15, 0, 60), color: 8 },
{ id: '9', title: 'Interview', ...at(0, 11, 0, 45), color: 6 },
{ id: '10', title: 'Retro', ...at(0, 16, 30, 45), color: 1 },
]
return list
}, [])
}
function Month() {
const events = useEvents()
const [picked, setPicked] = useState<string | null>(null)
return (
<div className="flex w-[52rem] flex-col gap-2">
<EventCalendar events={events} onEventPress={(e) => setPicked(e.title)} />
{picked && <span className="text-sm text-fg-muted">Opened: {picked}</span>}
</div>
)
}
export const styles = { Month, Week: () => <EventCalendar className="w-[52rem]" events={useEvents()} defaultView="week" /> }Source: packages/ui/src/event-calendar/event-calendar.tsx
Catalog
- Category
- date-time
- Priority
- Pro
- Primitive
- composed
- React Aria
- Calendar + GridList