Installation
Theme
Mode

Data display

Calendar

A month schedule view: a six-week grid with a weekday header, a pill marker on today, event chips in the six-tone status palette with a “+N more” overflow, and prev / next / Today navigation. Pure local date math — no date library.

$npx shadcn@latest add @orbit/calendar

Overview

Events render as soft-tinted chips in their day cells — a dot in the tone color plus the title. Clicking a chip fires onSelectEvent (open your own detail dialog); clicking a cell fires onSelectDate.

Live · navigate, click an event or a day
June 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+1 more
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12

Click an event chip or a day cell — navigate with ‹ › and Today.

Event tones

Six palette tones — blue, violet, green, amber, rose, teal — map categories to color. Keep the tone → category mapping stable so people learn to read the calendar by color. Tones derive from theme tokens, so they survive dark mode and every preset.

Controlled month + maxVisibleEvents={2}
June 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+2 more
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12

Controlled month: 2026-06 · maxVisibleEvents={2} tightens the overflow to “+N more” sooner.

Real today

today defaults to the current date, so a bare <Calendar /> opens on the live month with the marker in the right place. Pass a fixed today (and defaultMonth) when demos or tests need stable output.

<Calendar /> with no props
August 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Props

PropTypeDefaultDescription
monthDateControlled visible month (any date within it). Leave undefined for uncontrolled use.
defaultMonthDateStarting month for uncontrolled use. Falls back to today's month.
onMonthChange(month: Date) => voidFires on ‹ › and Today navigation with the first of the new month.
eventsCalendarEvent[][]Chips per day. { id, date: "YYYY-MM-DD", title, tone?, start?, end? } — start orders chips within a day.
todayDatenew Date()The pri-pill day marker and the Today button's target. Override for stable demos and tests.
onSelectDate(date: Date) => voidA day cell was clicked.
onSelectEvent(event: CalendarEvent) => voidAn event chip was clicked — open your detail dialog here.
maxVisibleEventsnumber3Chips shown per day before the “+N more” overflow.
…restHTMLAttributes<HTMLDivElement>Everything else is forwarded to the root element, including ref.

Usage

Do

Color by category, consistently

Keep the tone → category mapping stable so people learn to read the calendar by color.

Don’t

Cram every detail into a chip

A chip is a dot and a title. Push time, location, and guests into a detail dialog via onSelectEvent.

Do

Keep the path back to today

The Today button lets a user who's navigated months away return in one click — don't hide it.

Don’t

Use a calendar when time isn't the axis

A calendar earns its complexity only when dates drive the content — otherwise a list or table is clearer.

Keyboard & accessibility

The grid uses ARIA grid semantics with labelled cells; the month title is a polite live region so navigation announces. Event chips are real buttons — Tab reaches them, Enter and Space activate. Prev / next / Today are labelled buttons with the 3px themed focus ring.

Tab to the toolbar and chips
June 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+1 more
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12

Click an event chip or a day cell — navigate with ‹ › and Today.