Shadcn-native calendar primitives

Scheduling primitives for shadcn apps that need real interaction.

CalendarCN gives you a reusable scheduler with month, week, day, and agenda views, recurring events, resource lanes, drag-and-drop editing, resize handles, and typed callbacks you can wire into your own state and persistence.

Month, week, day, and agenda views on one event model

Recurring events, resources, drag, resize, and selection built in

Token-driven styling that fits the rest of your shadcn app

npx shadcn@latest add https://calendarcn.phantomtechind.com/r/calendarcn.json

Quick start

Install the calendar directly into your app

Use the hosted registry item for the fastest install path. Clone the repo only when you want the full docs site, showcase, and reference app.

May 25 - 31, 2026

3/3 calendars

All calendars active
Time

Mon

May 25

Tue

May 26

Today

Wed

May 27

Thu

May 28

Fri

May 29

Sat

May 30

Sun

May 31

All day

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.

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

11 PM

12 AM

1 AM

Qualified routes

Start from the route that matches your product.

CalendarCN is strongest for teams embedding scheduling into a React or Next.js product. These routes filter out generic calendar-app intent and move qualified visitors straight into the right install and docs path.

Best fit

  • React and Next.js teams already shipping with shadcn/ui.
  • Products embedding scheduling into internal tools, SaaS workflows, or booking surfaces.
  • Builders who want source-installed calendar code with direct event interactions.

Not for

  • Consumer users searching for a standalone calendar app.
  • Projects that only need a date picker or a static month grid.
  • Teams optimizing for the largest ecosystem before design-system fit or source ownership.
Use case

Shadcn Calendar for real scheduling UIs

CalendarCN gives shadcn/ui apps a real scheduling surface with month, week, day, and agenda views plus drag, resize, recurrence, and typed event handlers.

Use case

React scheduler component for shadcn and Next.js apps

CalendarCN is a React scheduler component for product teams that need direct editing, recurring events, resource lanes, and a controlled state model.

Use case

Drag and drop calendar in React with typed event operations

CalendarCN supports drag-and-drop calendar workflows in React with event creation, move, resize, keyboard nudges, and touch interactions.

Use case

React calendar with recurring events for scheduling products

CalendarCN handles recurring events in React scheduling UIs while keeping the rendered occurrences tied to one controlled event model.

Use case

Resource scheduling in React with shared calendar interactions

CalendarCN supports resource scheduling in React with parallel lanes for teams, rooms, staff, or calendars while keeping the same editing model.

Alternative

FullCalendar alternative for source-installed React scheduling

CalendarCN is a FullCalendar alternative for React teams that want source-installed calendar code, shadcn/ui fit, and a product-first controlled integration model.

Alternative

react-big-calendar alternative for shadcn and Next.js products

CalendarCN is a react-big-calendar alternative for teams that want stronger design-system fit, direct scheduling interactions, and modern shadcn-first presentation.

Exports

Composable building blocks for shipping scheduling UI.

CalendarCN is structured as open code for shadcn-style installs. Use the primitive surface, the starter scheduler, or pull in the toolbar, individual views, types, and slots where they fit.

CalendarRoot

The primitive scheduling surface

It coordinates visible range, recurrence expansion, selection, drag and resize interactions, and view rendering from one controlled API.

Use it when you want the calendar surface without baking toolbar, sheets, or persistence rules into the component.

CalendarToolbar

Navigation wired to calendar state

Previous, next, today, and view switching already line up with the calendar API, so you are not rebuilding basic controls around every embed.

Install it separately when you want the lean primitive path, or swap it for your own controls.

Views

Month, week, day, and agenda

Each view reads the same event and resource contracts, so you can change density and planning mode without changing your data layer.

That makes it practical to ship a broad planner, a focused day view, and an agenda feed from one model.

Types + slots

Typed contracts and slot-level customization

Events, resources, recurrences, and mutation payloads are typed, and the component exposes className slots for the key calendar surfaces.

You keep the interaction model, then adapt the styling and rendering to your own product.

Core behavior

Built for schedules that keep changing.

A useful calendar has to do more than render boxes. CalendarCN ships the interactions and state contracts you need once users start moving work around.

One contract across every view

Month, week, day, and agenda all consume the same event shape, so your scheduling data does not fork as the UI changes.

Create, move, and resize in place

Drag across open time to create a block, move events between slots and days, and resize directly from the edge where the schedule is visible.

Recurring events and resource-aware planning

Events can repeat, resources can define parallel lanes, and the same occurrence model drives selection, editing, and follow-up actions.

Fits the token system you already use

The calendar inherits the same shadcn color tokens and exposes className slots, so it can sit inside an existing app instead of forcing a separate visual system.

Integration model

Own the state. Let the calendar handle the surface.

CalendarCN is designed as controlled open code. Your app keeps the source of truth for date, view, events, and persistence; the calendar turns that into visible occurrences and interaction callbacks.

Controlled setup

1"use client"
2
3import { CalendarRoot } from "@/components/calendar/root"
4import { CalendarToolbar } from "@/components/calendar/toolbar"
5import type { CalendarEvent, CalendarView } from "@/components/calendar/types"
6import { getRangeLabel, shiftDate } from "@/components/calendar/utils"
7
8const [events, setEvents] = useState<CalendarEvent[]>(seed)
9const [date, setDate] = useState(new Date())
10const [view, setView] = useState<CalendarView>("week")
11const currentLabel = getRangeLabel(date, view)
12const blockedRanges = [{ id: "lunch", start, end }]
13
14<>
15 <CalendarToolbar
16 activeResourceIds={[]}
17 availableViews={["week", "day", "agenda"]}
18 currentLabel={currentLabel}
19 onNavigate={(direction) => setDate((currentDate) => shiftDate(currentDate, view, direction))}
20 onToday={() => setDate(new Date())}
21 onViewChange={setView}
22 view={view}
23 />
24 <CalendarRoot
25 hiddenDays={[0, 6]}
26 businessHours={[{ days: [1, 2, 3, 4, 5], start: "09:00", end: "18:00" }]}
27 blockedRanges={blockedRanges}
28 density="compact"
29 date={date}
30 events={events}
31 hourCycle={24}
32 locale="en-GB"
33 scrollToTime="08:30"
34 view={view}
35 />
36</>

Integration notes

What this controlled setup actually gives you

Your app owns the scheduling truth. CalendarCN turns that state into visible occurrences and returns user actions through handlers you control.

Keep the scheduling contract in your app

useCalendarController in the demo is just one wiring example. In production, date, view, events, and persistence can stay in React state, a server cache, or whatever store already owns your scheduling rules.

CalendarRoot derives the visible schedule

It computes the active range, expands recurring events for that window, renders the current view, and coordinates drag overlays, selection, keyboard moves, and accessibility announcements.

One model works across every exported view

Switching from a month grid to a time grid or agenda feed does not require a second contract. The same events, resources, and constraints keep working across each surface.

Every mutation comes back through your handlers

Create, move, resize, duplicate, archive, and delete actions flow back as typed operations, so your app decides how changes are validated, persisted, synchronized, or rejected.

Interactive demo

One calendar, multiple scheduling setups.

Switch the site theme from the navbar, then try presets and options below. The same calendar keeps its drag, resize, and view behavior while layout, time labels, and scheduling rules adapt to each setup.

Interactive setup

Compare realistic scheduling setups.

Start with a preset, then turn options on or off. The calendar below updates immediately so you can compare the same interactions under different layout, time, and scheduling rules.

Options

Current setup

Workweek setup with compact spacing, 24-hour time, weekday-only planning, unavailable time blocks enabled, and the mixed reference dataset used across the demo.

Workweek presetMixed reference scheduleCompact spacingWeekdays onlyWorking hours highlightedUnavailable time enforced24-hour labelsWeek, day, and agenda views

Implementation props

density="compact"hourCycle={24}locale="en-GB"scrollToTime="08:30"availableViews={["week", "day", "agenda"]}hiddenDays={[0, 6]}businessHours={demoBusinessHours}blockedRanges={demoBlockedRanges}

25 May - 29, 2026

3/3 calendars

All calendars active
Time

Mon

25 May

Tue

26 May

Today

Wed

27 May

Thu

28 May

Fri

29 May

All day

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.

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

00

01

Lunch
Release freeze