Zephora UI

Data

EventCalendar

Event calendar with month, week and day views — multi-day strips with a +N more overflow, overlapping time-grid blocks, a now indicator, slot and event callbacks and a localized toolbar. No date library.

Import

import { EventCalendar } from "@zephora/react";

Examples

Month view

`maxEventsPerCell` caps the strips per day cell before the `+N more` button takes over. Pass a fixed `defaultDate` (and fixed event dates) so server-rendered output stays deterministic.

July 2026
SunMonTueWedThuFriSat
28
29
30
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

Week view

Overlapping events share the day column side by side. `onSlotClick` fires with the clicked `slotDuration` slot — here it appends a new event.

Jul 5, 2026 – Jul 11, 2026
5 Sun6 Mon7 Tue8 Wed9 Thu10 Fri11 Sat
All-day

Custom event render

`renderEvent` replaces the content inside every event chip — here a colored dot driven by the event `color`.

July 2026
SunMonTueWedThuFriSat
28
29
30
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

API

EventCalendar props

PropTypeDefaultDescription
events *CalendarEvent[]Events to display. Order does not matter — layout sorts internally.
view"month" | "week" | "day"Controlled active view.
defaultViewEventCalendarView"month"Initial view in uncontrolled mode.
onViewChange(view: EventCalendarView) => voidFires when the view switcher changes the view.
viewsEventCalendarView[]["month", "week", "day"]Which views the switcher offers.
dateDateControlled anchor date (any day inside the visible month / week / day).
defaultDateDatetodayInitial anchor date in uncontrolled mode. Pass a fixed date for deterministic SSR.
onDateChange(date: Date) => voidFires when navigation changes the anchor date.
firstDayOfWeeknumberfrom localeFirst day of the week: 0 = Sunday, 1 = Monday…
minTimenumber0Time-grid window start, minutes since midnight.
maxTimenumber1440Time-grid window end, minutes since midnight.
slotDurationnumber30Time-grid slot step in minutes (gutter lines + `onSlotClick` granularity).
maxEventsPerCellnumber3Event strips per month cell before the "+N more" button takes over.
showNowIndicatorbooleantrueRed "now" line in week / day views when today is visible.
onEventClick(event: CalendarEvent, e: MouseEvent) => voidFires when an event chip is clicked.
onSlotClick(start: Date, end: Date, e: MouseEvent) => voidEmpty slot click — a full day in month view, a `slotDuration` slot in week / day.
renderEvent(event, { view }) => ReactNodeReplaces the default content inside every event chip.
renderDayCell(date: Date, events: CalendarEvent[]) => ReactNodeReplaces the default day-number content of a month cell.
localestringfrom configBCP 47 locale for all Intl formatting.
unstyledbooleanfalseHeadless mode — skips Zephora styling.
classNamesPartial<Record<EventCalendarSlot, string>>Per-slot class overrides.

CalendarEvent props

PropTypeDefaultDescription
id *stringUnique event id.
title *ReactNodeEvent title.
start *DateEvent start.
end *DateEvent end. Treated as exclusive at exact day boundaries (00:00 ends the previous day).
allDaybooleanRenders in the month strips / all-day row instead of the time grid.
colorstringAccent color for the event chip (any CSS color).
dataunknownArbitrary consumer payload, passed back through callbacks untouched.

Keyboard

KeyAction
ArrowLeft / ArrowRightMove day focus to the previous / next day in the month grid.
ArrowUp / ArrowDownMove day focus to the same weekday in the previous / next week.
Home / EndMove day focus to the first / last day of the week.
PageUp / PageDownGo to the previous / next month.
Enter / SpaceSelects the focused day (fires `onSlotClick`).
EscapeCloses an open "+N more" day overlay.
TabMoves through the toolbar, event chips and more buttons.