Calendar

Organism
Month grid, week timeline, and day timeline in one component. Events mark their days with a dot in the month grid and week strip, and timed events render as blocks on the week/day hour timelines.

Playground

Every control sets a real prop of CalendarProps. The JSX below updates as you go.
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Props
selected
number
26
today
number
26
range
boolean
compact
boolean
View
pick one
JSX · CalendarProps
<Calendar selected={26} today={26} />

Variants

6 examples from src/organisms/calendar/calendar.md, each rendered live from its own JSX.
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Events
Each event carries the day it falls on, plus an optional title and start/end hours. The month grid marks event days with a dot and reads the count to assistive tech.
<Calendar
month="May 2026"
today={23}
defaultSelected={24}
daysInMonth={31}
startWeekday={4}
events={[
{ day: 8, title: "Design review" },
{ day: 14, title: "1:1 with manager" },
{ day: 24, title: "Sprint planning" }
]}
/>
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Day peek
With dayPeek, pressing a marked day opens that day's hour timeline (the same timeline the day view renders) beside the cell: at its trailing side (the right in a left-to-right layout), at its leading side when that lacks room, and above or below it when neither side fits. A tap anywhere else or Escape dismisses it.
<Calendar
dayPeek
month="May 2026"
today={23}
defaultSelected={24}
daysInMonth={31}
startWeekday={4}
events={[
{ day: 24, title: "Sprint planning", start: 9, end: 10.5 },
{ day: 24, title: "Team lunch", start: 12.5, end: 13.5 }
]}
/>
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
12 AM
1 AM
2 AM
3 AM
4 AM
5 AM
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
11 PM
Design review
Sprint planning
User interviews
Week
week renders the selected day's week: a strip of seven selectable day cells over an hour timeline, with each timed event as a block in its day column. The timeline spans the full day; the scroller opens on the 8 AM to 5 PM window and scrolls to the rest, and the 12h/24h control flips the hour labels (12-hour by default). Overlapping events split their column into side-by-side lanes, hovering a block floats its details, and the chevrons page a week at a time.
<Calendar
week
month="May 2026"
today={23}
defaultSelected={20}
daysInMonth={31}
startWeekday={4}
events={[
{ day: 19, title: "Design review", start: 11, end: 12.5 },
{ day: 20, title: "Sprint planning", start: 9.5, end: 11 },
{ day: 21, title: "User interviews", start: 10, end: 12 }
]}
/>
Saturday, May 24
12 AM
1 AM
2 AM
3 AM
4 AM
5 AM
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
11 PM
Sprint planning
9 AM – 10:30 AM
Design review
11:30 AM – 1 PM
Team lunch
12:30 PM – 1:30 PM
Day
day renders a single day's hour timeline with each block carrying its title and time span. The timeline covers the whole day (narrow it with startHour/endHour); the scroller opens on 8 AM to 5 PM and scrolls to the remaining hours, and the 12h/24h control flips the labels. Hovering a block floats a detail card with the event's description. The chevrons page a day at a time.
<Calendar
day
month="May 2026"
today={23}
defaultSelected={24}
daysInMonth={31}
startWeekday={4}
events={[
{ day: 24, title: "Sprint planning", start: 9, end: 10.5, description: "Backlog grooming and capacity check for the next sprint." },
{ day: 24, title: "Design review", start: 11.5, end: 13 },
{ day: 24, title: "Team lunch", start: 12.5, end: 13.5 }
]}
/>
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Range
range turns the month grid into a check-in/check-out picker for booking flows: the first press sets the start day, a later press sets the end, and a tinted band spans the days between; pressing an earlier day restarts the pick. Control it with rangeStart/rangeEnd and onRangeChange, or seed it with the default pair.
<Calendar
range
month="May 2026"
today={23}
daysInMonth={31}
startWeekday={4}
defaultRangeStart={14}
defaultRangeEnd={20}
/>
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Compact
compact tightens the cells and type for dense surfaces, in every view.
<Calendar
compact
month="May 2026"
today={23}
defaultSelected={24}
daysInMonth={31}
startWeekday={4}
/>

States

Hover, focus and press are pinned so they can be compared side by side; the rest are real props.
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
default
May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
focus

Anatomy

May 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
Header
2
Weekday row
3
Day
4
Selected day
5
Event dot
Dimmed parts appear only in some states or variants.

Props

28 props on CalendarProps, grouped as they are declared in source. Required props are marked *.
Prop
Type
Default
Description
Props
11 props
month
string
"June 2026"
Month + year label shown in the header, e.g. "June 2026".
selected
number
–
The day number currently selected (CONTROLLED, primary highlight). Omit for uncontrolled use.
defaultSelected
number
–
Initial selected day for uncontrolled use (a bare calendar highlights the day on press).
today
number
–
The day number that is today (primary highlight when unselected).
daysInMonth
number
30
Number of days in the month.
startWeekday
number
0
Weekday (0=Sun .. 6=Sat) the 1st falls on; sets leading blank cells.
events
CalendarEvent[]
–
Events to mark: dots on their days in the month grid and week strip, timed blocks in the week/day timelines.
onSelect
(day: number) => void
–
Fired with the day number when a day cell is pressed (and when week/day chevron paging moves the selection).
onEventPress
(event: CalendarEvent) => void
–
Fired with the event when a timed block in the week/day timeline is pressed.
onPrev
(event: GestureResponderEvent) => void
–
Fired when the previous chevron is pressed in the month view, or when week/day paging would cross into the previous month.
onNext
(event: GestureResponderEvent) => void
–
Fired when the next chevron is pressed in the month view, or when week/day paging would cross into the next month.
View
pick one
3 props
week
boolean
false
Seven-day strip over an hour timeline; chevrons page by week.
day
boolean
false
Single-day hour timeline; chevrons page by day.
dayPeek
boolean
false
Month view: pressing a day that has events also opens that day's hour timeline in an anchored overlay (a tooltip-style day peek) beside the cell, at its trailing side (the right in a left-to-right layout), at its leading side when that lacks room, and above or below it when neither side fits; dismissed by an outside tap or Escape.
Range selection
8 props
range
boolean
false
Month view: two-tap range selection — the first press sets the start day, the second (later) press the end; a press before the start restarts. Days between carry a tinted band.
rangeStart
number
–
The range's start day (CONTROLLED with rangeEnd). Omit both for uncontrolled use.
rangeEnd
number
–
The range's end day (CONTROLLED with rangeStart).
defaultRangeStart
number
–
Initial range start for uncontrolled use.
defaultRangeEnd
number
–
Initial range end for uncontrolled use.
onRangeChange
(start?: number, end?: number) => void
–
Fired as the range is picked: with (start, undefined) after the first press, (start, end) after the second.
startHour
number
–
First hour of the week/day timeline (0-24; default 0, the full day).
endHour
number
–
Last hour of the week/day timeline (0-24; default 24). The scroller initially windows 8 AM–5 PM and scrolls to the rest.
Hour format
3 props
hour24
boolean
false
Timeline labels in 24-hour format (CONTROLLED). Omit to let the built-in 12h/24h toggle manage it.
defaultHour24
boolean
false
Initial hour format for uncontrolled use (default false = 12-hour AM/PM).
onHour24Change
(hour24: boolean) => void
–
Fired when the hour format changes (true = 24-hour).
Density
pick one
3 props
compact
boolean
false
Tighter cells and smaller type, for dense surfaces.
testID
string
–
E2E hook forwarded to the root element.
style
LayoutStyle
–
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Accessibility and keyboard

Keyboard
Arrow keys
Moves between cells
Home
End
Row start · end
PageUp
PageDown
Previous · next page
Enter
Space
Activates or selects
Semantics
Roles
button

Platform skins

The playground's props on each platform: same tree, native shapes, type and touch sizes.
Saturday, May 24
12 AM
1 AM
2 AM
3 AM
4 AM
5 AM
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
11 PM
Sprint planning
9 AM – 10:30 AM
Design review
11:30 AM – 1 PM
Team lunch
12:30 PM – 1:30 PM
Web
control 10 · field 10 · card 16 · Instrument Sans
Saturday, May 24
12 AM
1 AM
2 AM
3 AM
4 AM
5 AM
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
11 PM
Sprint planning
9 AM – 10:30 AM
Design review
11:30 AM – 1 PM
Team lunch
12:30 PM – 1:30 PM
iOS
capsule controls · field 8 · card 12 · SF Pro · 44 pt
Saturday, May 24
12 AM
1 AM
2 AM
3 AM
4 AM
5 AM
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
11 PM
Sprint planning
9 AM – 10:30 AM
Design review
11:30 AM – 1 PM
Team lunch
12:30 PM – 1:30 PM
Android
Material 3 stadium · field 4 · card 12 · Roboto · 48 dp

Usage

A bare calendar is uncontrolled: pressing a day selects it, and in the week/day views the chevrons page the selection a week or a day at a time (crossing into another month hands the press to onPrev/onNext, since the month itself is a prop).
<Calendar
month="May 2026"
today={23}
defaultSelected={24}
daysInMonth={31}
startWeekday={4}
/>
The view is a semantic boolean axis: pass week or day, or neither for the month grid (day wins over week when both are set).
In glass mode the selected day is a brand-tinted control-layer puck behind its number and event dot, in the month grid and along the week strip; in range mode both endpoints carry the puck over the range band. The day peek and the hover card are functional-layer glass cards beside their day. Solid mode keeps the skin's own filled day.

Tokens

Read from the playground render. Values follow the scheme and the ion hue.
--cyan
--fd
--fm
--ft
--ion
--ion-fg
--ion-glow
--ln
--sf
--sh-sm
--tx3

Related components