Calendar Overview
Install CalendarCN, preview the main examples, and wire the calendar into controlled React state.
CalendarCN installs source into your app. The primary path is now primitive:
CalendarRoot for the surface, CalendarToolbar for navigation, and optional
add-ons for sheets, menus, and shortcut docs. CalendarScheduler remains
available as the starter bundle when you want the current full CalendarCN
behavior in one install.
Preview
Example Variants
Primitive starter
Compose `CalendarRoot` and `CalendarToolbar` directly when you want the smallest install surface and total source ownership.
Mar 23 - 29, 2026
Mon
Mar 23
Tue
Mar 24
Wed
Mar 25
Thu
Mar 26
Fri
Mar 27
Sat
Mar 28
Sun
Mar 29
Use arrow keys to move the active time slot. Use left and right arrows to change days. Press Enter or Space to create an event at the active slot.
6 AM
7 AM
8 AM
9 AM
10 AM
11 AM
12 PM
1 PM
2 PM
3 PM
4 PM
5 PM
6 PM
7 PM
8 PM
9 PM
10 PM
Installation
Install the lean surface first. This gives you `CalendarRoot` plus the controlled toolbar, with the rest left open for composition.
Pull the selected CalendarCN bundle directly from the hosted item URLs. The primitive path installs separate open-code files; the starter path keeps the current composed scheduler.
npx shadcn@latest add \ https://calendarcn.phantomtechind.com/r/calendar-core.json \ https://calendarcn.phantomtechind.com/r/calendar-toolbar.jsonUsage
"use client"import * as React from "react"import type { CalendarClassNames, CalendarCreateOperation, CalendarEvent, CalendarMoveOperation, CalendarResizeOperation, CalendarView,} from "@/components/calendar/types"import { CalendarRoot } from "@/components/calendar/root"import { CalendarToolbar } from "@/components/calendar/toolbar"import { getRangeLabel, applyMoveOperation, applyResizeOperation, createEventFromOperation, shiftDate,} from "@/components/calendar/utils"const primitiveEventClassNames: CalendarClassNames = { agendaEvent: "data-[selected=true]:border-ring data-[selected=true]:ring-2 data-[selected=true]:ring-ring/60", monthEvent: "data-[selected=true]:border-ring data-[selected=true]:ring-2 data-[selected=true]:ring-ring/60", timeGridEvent: "data-[selected=true]:border-ring data-[selected=true]:ring-2 data-[selected=true]:ring-ring/60",}export function TeamSchedule() { const [date, setDate] = React.useState(new Date()) const [events, setEvents] = React.useState<CalendarEvent[]>([]) const [selectedEventId, setSelectedEventId] = React.useState<string>() const [view, setView] = React.useState<CalendarView>("week") const currentLabel = React.useMemo(() => getRangeLabel(date, view), [date, view]) function handleCreate(operation: CalendarCreateOperation) { setEvents((currentEvents) => [ ...currentEvents, createEventFromOperation(operation, { title: "New event", }), ]) } function handleMove(operation: CalendarMoveOperation) { setEvents((currentEvents) => applyMoveOperation(currentEvents, operation)) } function handleResize(operation: CalendarResizeOperation) { setEvents((currentEvents) => applyResizeOperation(currentEvents, operation)) } return ( <div className="overflow-hidden rounded-[calc(var(--radius)*1.6)] border border-border/70"> <CalendarToolbar activeResourceIds={[]} availableViews={["month", "week", "day", "agenda"]} currentLabel={currentLabel} onNavigate={(direction) => setDate((currentDate) => shiftDate(currentDate, view, direction)) } onToday={() => setDate(new Date())} onViewChange={setView} view={view} /> <CalendarRoot classNames={primitiveEventClassNames} date={date} events={events} onEventCreate={handleCreate} onEventMove={handleMove} onEventResize={handleResize} onSelectedEventChange={setSelectedEventId} secondaryTimeZone="America/New_York" selectedEventId={selectedEventId} showSecondaryTimeZone view={view} /> </div> )}Examples
The calendar surface should document more than a single happy path. These versions cover both implementation patterns and the individual views that most teams need to wire up.
Implementation Patterns
Preset configurations that show how the same calendar surface adapts to different product constraints.
Starter
Primitive starter
Compose `CalendarRoot` and `CalendarToolbar` directly when you want the smallest install surface and total source ownership.
Workweek
Workweek constraints
Compact density, weekday-only navigation, business hours, and blocked ranges for focused team planning.
Resources
Resource lanes
Assign events to teams, rooms, or calendars and keep the same editing model across each lane.
Interactions
Direct editing flow
Use the `CalendarScheduler` starter when you want the current full CalendarCN overlays and productized interaction flow.
Calendar Views
Focused docs for each supported view so users can land directly on the surface they need to implement.
Month
Month view
Use the month surface for high-level planning, all-day scheduling, and multi-day event visibility.
Week
Week view
The week grid is the main interactive planning surface for timed events, editing, and schedule density.
Day
Day view
Reduce the schedule to one day when users need focus, denser event detail, or single-day workflows.
Agenda
Agenda view
Render the schedule as a chronological list for upcoming events, summaries, or lower-density layouts.
Related guides
- Shadcn calendar if your main question is design-system fit
- React scheduler component if you are comparing embedded scheduling options
- Drag and drop calendar in React if direct editing is the deciding requirement
- Resource scheduling in React if teams, rooms, or lanes are central to the workflow
Accessibility
- Week and day views expose a roving schedule grid. Tab enters the active day
once, arrow keys move the active slot, and
EnterorSpacestarts the create flow for that slot. - Event cards stay as buttons. Arrow keys move a selected event,
Shift + Arrowresizes the end,Alt + Arrowresizes the start, andShift + F10opens the event context menu. - Month uses grid semantics and agenda uses list semantics so assistive technology gets the same structural cues as the visual layout.
- The optional sheets, confirmation dialog, and shortcuts dialog add-ons all use modal focus management with escape handling, overlay dismiss, and focus restore.
Notes
CalendarRootis fully controlled. Keepdate,view, andeventsin your own state or wire them into your store.CalendarToolbaris separate on purpose. Primitive installs keep navigation, view switching, and quick actions outside the surface component.CalendarRootexposes selected events throughdata-selected="true"on the event surface. Primitive installs should style selected state throughclassNamesor CSS selectors, whileCalendarScheduleralready ships with starter defaults for selected events.- The utility helpers in
@/components/calendar/utilsare the fastest path to local optimistic handlers for move, resize, and create flows. - Use
onEventCreateRequest,onEventMoveRequest, andonEventResizeRequestwhen your app wants to open a sheet or confirmation dialog before committing a change. resources,businessHours, andblockedRangesare optional. The same core interaction model works with or without them.CalendarScheduleris the starter bundle. Use it when you want the current composed toolbar, create/details sheets, confirmation dialog, and shortcuts dialog out of the box.exportEventsToICS,parseICSText, andparseICSFilelive in@/components/calendar/utilsfor import and export workflows outside the rendered calendar.