Calendar
A date and event view for schedules, with Month, Week, and Day modes.
Default
Custom Header
Pass a #header slot to replace the default toolbar. The slot receives the current title (currentMonthYear), the active view (activeView), the enabled view options (enabledModes), and navigation functions (increment, decrement, updateActiveView, setCalendarDate, onMonthYearChange).
Events
Each entry in events is a CalendarEvent:
{
id: 'EV-001',
title: 'Design review',
participant: 'Jane Doe',
venue: 'Room 1',
fromDate: '2026-08-10',
toDate: '2026-08-10',
fromTime: '10:00',
toTime: '11:00',
color: 'blue', // amber | violet | pink | cyan | blue | orange | green
isFullDay: false,
}The calendar keeps an internal copy of events and refreshes it when the prop changes. Edits made inside the calendar (create, drag, resize, delete) mutate the copy and come back through the create, update, and delete emits — persist them and refresh your source of truth from there.
CalendarColorMap exports the color palette (amber, violet, pink, cyan, blue, orange, green) with the CSS variables used per state, for building matching UI such as a color picker.
Config
The config prop takes a partial CalendarConfig; unset keys use these defaults:
{
defaultMode: 'Month', // 'Day' | 'Week' | 'Month'
disableModes: [], // views removed from the view switcher
isEditMode: false, // create / drag / resize / delete
enableShortcuts: true, // keyboard shortcuts (below)
scrollToHour: 15, // hour Week and Day views scroll to
hourHeight: 50, // pixel height of one hour row
timeFormat: '12h', // '12h' | '24h'
weekends: ['sunday'], // days shaded as weekend
eventIcons: {}, // icons keyed by an event's `type`
showIcon: true, // show the eventIcons icon on cards
noBorder: false, // remove the outer grid border
}eventIcons values are Vue components.
Keyboard shortcuts
With enableShortcuts on: m / w / d switch views, t jumps to today, ← / → navigate, and Delete removes the event whose popover is open (edit mode only).
Click handling
By default, a single click on an event opens its detail popover and a double click opens the edit modal (edit mode only). Clicking an empty cell opens the new-event modal in edit mode. Each behavior is replaceable with the onClick, onDblClick, and onCellClick callback props — passing one turns the default off for that interaction.
The popover's content is replaceable with the #event-popover-content slot, which receives { calendarEvent, date, isEditMode, close }.
CalendarActiveEvent exports the ref holding the id of the event whose popover is open. Set it from outside to highlight an event, or clear it with an empty string. The ref is module-level: every <Calendar> on the page shares it.
Template ref
A template ref on <Calendar> exposes the calendar's state and navigation:
<Calendar ref="calendar" :events="events" />const calendar = useTemplateRef('calendar')
calendar.value.setCalendarDate('2026-08-10') // jump to a date (today if omitted)
calendar.value.updateActiveView('Week') // switch the view
calendar.value.activeView // the visible view
calendar.value.increment() // move forward one day / week / month
calendar.value.decrement() // move back one day / week / month
calendar.value.reloadEvents() // re-sync the internal copy of `events`
calendar.value.currentMonthYear // formatted title, e.g. "August 2026"
calendar.value.currentYear // 2026
calendar.value.currentMonth // 7 (0 = January)
calendar.value.currentDay // day of month anchoring the view
calendar.value.enabledModes // view options not disabled via config (fixed at mount)
calendar.value.selectedMonthDate // the month picker's date, `YYYY-MM-DD`
calendar.value.onMonthYearChange // jump to a date and sync the month pickerAPI Reference
Show types
import type { Component, InjectionKey, Ref } from 'vue'
export type CalendarMode = 'Day' | 'Week' | 'Month'
export type CalendarTimeFormat = '12h' | '24h'
export interface CalendarColor {
color: string
border: string
borderActive: string
text: string
textActive?: string
subtext: string
subtextActive: string
bg: string
bgHover: string
bgActive: string
}
export interface CalendarEvent {
id?: string | number
name?: string | number
title?: string
date?: string
fromDate?: string
toDate?: string
fromTime?: string
toTime?: string
fromDateTime?: string
toDateTime?: string
participant?: string
venue?: string
color?: string
type?: string
isFullDay?: boolean
startTime?: number
endTime?: number
hallNumber?: number
idx?: number
[key: string]: unknown
}
export interface CalendarConfig {
/** Hour (0-23) the Week and Day views scroll to on mount. */
scrollToHour: number
/** Views removed from the view switcher in the default header. */
disableModes: CalendarMode[]
/** View shown when the calendar mounts. */
defaultMode: CalendarMode
/**
* Enables editing: create events by clicking a cell, edit on double
* click, drag to move, resize, and delete with the keyboard.
*/
isEditMode: boolean
/** Icons keyed by an event's `type` field. */
eventIcons: Record<string, Component>
/** Pixel height of one hour row in the Week and Day views. */
hourHeight: number
/**
* Enables keyboard shortcuts: `m`/`w`/`d` switch views, `t` jumps to
* today, arrow keys navigate, Delete removes the open event.
*/
enableShortcuts: boolean
/** Shows the event's `eventIcons` icon on its card. */
showIcon: boolean
/** Clock format for time labels: `'12h'` or `'24h'`. */
timeFormat: CalendarTimeFormat
/**
* Days shaded as weekend. Weekday names (`'sunday'`) or indexes
* (0 = Sunday).
*/
weekends: string[]
/** Removes the outer grid border. */
noBorder?: boolean
}
export interface CalendarCellClickData {
e: MouseEvent
view: CalendarMode
date: Date | string
time: string
isFullDay: boolean
}
export interface CalendarPublicProps {
/** Events to render. Each needs an `id`, a title, and date/time fields. */
events: CalendarEvent[]
/** Behavior overrides, merged over the defaults. */
config?: Partial<CalendarConfig>
/**
* Replaces the default single-click behavior (opening the event
* popover) with your own handler.
*/
onClick?: (data: { e: MouseEvent; calendarEvent: CalendarEvent }) => void
/**
* Replaces the default double-click behavior (opening the edit
* modal) with your own handler.
*/
onDblClick?: (data: {
e: MouseEvent | null
calendarEvent: CalendarEvent
}) => void
/**
* Replaces the default cell-click behavior (opening the new-event
* modal in edit mode) with your own handler.
*/
onCellClick?: (data: CalendarCellClickData) => void
}
export interface CalendarActions {
createNewEvent: (event: CalendarEvent) => void
updateEventState: (event: CalendarEvent) => void
deleteEvent: (eventID: CalendarEvent['id']) => void
handleCellClick: (
e: MouseEvent,
date: Date | string,
time?: string,
isFullDay?: boolean,
) => void
updateActiveView: (
value: CalendarMode,
date?: Date,
isPreviousMonth?: boolean,
isNextMonth?: boolean,
) => void
props: CalendarPublicProps
}
export type GroupedCalendarEvents = Record<string, CalendarEvent[]>
export const ACTIVE_VIEW_KEY = Symbol(
'frappe-ui.calendar.active-view',
) as InjectionKey<Ref<CalendarMode>>
export const CALENDAR_CONFIG_KEY = Symbol(
'frappe-ui.calendar.config',
) as InjectionKey<CalendarConfig>
export const CALENDAR_ACTIONS_KEY = Symbol(
'frappe-ui.calendar.actions',
) as InjectionKey<CalendarActions>Events to render. Each needs an `id`, a title, and date/time fields.
Behavior overrides, merged over the defaults.
Replaces the default single-click behavior (opening the event popover) with your own handler.
Replaces the default double-click behavior (opening the edit modal) with your own handler.
Replaces the default cell-click behavior (opening the new-event modal in edit mode) with your own handler.
| Slot | Payload |
|---|---|
header | { currentMonthYear: string; currentYear: number; currentMonth: number; enabledModes: CalendarActionO |
event-popover-content | { calendarEvent: { [x: string]: unknown; id?: string | number | undefined; name?: string | number | |
daily-header | { parseDateWithDay: any; currentDate: any; fullDay: any; } |
| Event | Payload |
|---|---|
delete | [eventID: string | number | undefined] |
create | [event: CalendarEvent] |
update | [event: CalendarEvent] |
rangeChange | [payload: { view: CalendarMode; startDate: string; endDate: string; }] |