build69
build69  /  Components  /  Data Display  /  BuildCalendar

BuildCalendar

v1.0.23Updated 19 Oct 2026

Month / week / day calendar with event chips and drag-to-create. Use when users need to see and schedule events on a grid.

Preview

Live · 19 stories
Beautiful ShowcaseOpen ↗
▸Why this is recommendedcalendareventsschedulemonth+7

A polished showcase bringing several BuildCalendar variations together — beautiful.

Recommended for+14
  • ✓Scheduling surfaces
  • ✓Booking calendars
  • ✓Editorial / publishing calendars
  • ✓a calendar whose events are loaded per month from an API
  • ✓showing who is on leave this month
Tags+6
calendareventsschedulemonthweeki18nlocalethaibuddhistbeautifulshowcase
Features+4
  • Month / week / day views
  • Multi-day event spanning (an event with `end` appears on every intersecting day)
  • Event chips with colour by category
  • Drag-to-create new event
  • Click event to open detail
  • Today highlight + weekend tint
  • All-day vs timed events
  • Read-only friendly: create affordances render only when onCreateEvent is provided
  • Server-backed: onRangeChange reports the visible period (start, end, view, referenceDate) on mount and on every change — chevrons, Today, the mini-calendar, a view switch and "+n more" — so the host can fetch exactly the days on screen. The month range covers the whole 42-cell grid, including the leading/trailing days of the neighbouring months, and it never fires twice for the same range
  • Controlled period: referenceDate + onReferenceDateChange makes the toolbar report instead of moving itself; defaultReferenceDate keeps it self-navigating while still reporting. referenceDate alone behaves exactly as before
  • getCalendarVisibleRange(referenceDate, view, weekStartsOn) is exported, so a host can compute the same range before it renders
  • i18n (FB-18): labels prop overrides every built-in string; LocaleProvider drives localized month/weekday names, Buddhist-calendar headers and weekStartsOn (0 Sunday / 1 Monday, default Monday)
Not recommended for−2
  • ✕Single-date picker (use Calendar primitive)
  • ✕Activity log (use Timeline)

Install

Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.

get_registry_item({ name: "BuildCalendar" })

Usage

import { BuildCalendar } from '@/components/data-display/build-calendar';

<BuildCalendar events={events} view="month" />

Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.

Props

PropTypeRequired
events

Events to render. CalendarEvent = { id, start, end?, title, subtitle?, description?, tone?, accent?, calendarId?, recurring?, allDay? }. An allDay event is lifted into a LANE above the hour grid in the week and day views rather than being given an hour it does not have — hosts used to pin them to 00:00 to make them visible, which filled the top of the day and claimed a time the event has no business claiming. The lane renders only when the period has one, so a calendar with nothing all-day is unchanged. MCP feedback fb_1571eb42.

CalendarEvent[]yes
view

Active view. "agenda" is a list grouped by day over the SAME range the month grid paints, so switching between the two needs no refetch and onRangeChange stays quiet; days with nothing on them are skipped and an empty period is its own state. MCP feedback fb_1571eb42.

'month' | 'week' | 'day' | 'agenda'—
referenceDate

The period to show. An ISO string is accepted, like CalendarEvent.start — a host whose dates came out of JSON has strings, and passing one used to throw during render. Alone: the initial date, re-synced when the prop changes while the toolbar still navigates itself. Together with onReferenceDateChange it is fully CONTROLLED — every navigation control reports and the calendar shows what the host renders

Date | string—
defaultReferenceDate

Where an uncontrolled calendar starts. An ISO string is accepted. Use with onReferenceDateChange to be told about navigation while the calendar still moves itself. Ignored when referenceDate is set

Date | string—
onReferenceDateChange

Fired whenever the visible period moves (chevrons, Today, a mini-calendar day, "+n more"). Not on mount, and not for a view-only change

(date: Date) => void—
onRangeChange

The days now on screen — fired once on mount and once per real change, including a view switch. end is inclusive (23:59:59.999 of the last visible day); a month covers the whole 42-cell grid. Never fires twice for the same range, so an inline arrow does not turn renders into fetches

(range: { start: Date; end: Date; view; referenceDate: Date }) => void—
onEventClick

Event click handler

function—
calendars

The calendars events belong to, for the legend and per-calendar colour. CalendarSource = { id, name, tone?, accent?, visible? }. `accent` is this calendar’s OWN colour and takes any CSS colour value (“#7c5cff”, “oklch(0.7 0.2 160)”, “var(--color-chart-2)”): six tone tokens cannot tell eight calendars apart, and a CalDAV or iCal calendar arrives carrying its own hex. The value is written to a --calendar-accent custom property inline and read back by arbitrary utilities, so it does not depend on Tailwind having seen the colour — which is exactly what the deprecated `color` prop (raw Tailwind CLASSES, composed at runtime, invisible to the static scanner) got wrong. An event can carry its own `accent` too, and it wins over its calendar’s. MCP feedback fb_1571eb42.

CalendarSource[]—
onCreateEvent

Create handler — the toolbar's New event button and the cell + affordances render only when this is set (omit for derived/read-only calendars)

(start: Date, end: Date) => void—
labels

Override any subset of the built-in UI strings (today, previous/next aria, day/week/month/agenda tabs, allDay and allDayEvents for the all-day lane, agendaEmptyTitle and agendaEmptyHint, newEvent, myCalendars, addEvent, moreEvents '+{count} more', showAllEvents). English defaults ship as DEFAULT_BUILD_CALENDAR_LABELS. Month/weekday names and header dates are NOT labels — wrap the app in LocaleProvider ({ locale, calendar: 'buddhist', weekStartsOn }) instead

Partial<BuildCalendarLabels>—

Related