# Calendar URL: /docs/web/components/calendar Calendar component. **Demo:** ```tsx 'use client'; // @custom-demo import { lazy, useMemo, useState } from 'react'; import { type TCalendarView } from '@docyrus/ui/components/calendar'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@docyrus/ui/primitives/ui/select'; import { Switch } from '@docyrus/ui/primitives/ui/switch'; import { cn } from '@docyrus/ui/primitives/lib/utils'; import { PropControls } from '@/components/prop-controls'; import { useDemoData } from '@/data/calendar-data'; const Calendar = lazy(() => import('@docyrus/ui/components/calendar').then(m => ({ default: m.Calendar }))); export function CalendarDemo() { type Variant = 'default' | 'bordered' | 'compact'; const [variant, setVariant] = useState
Size
defaultView
); } ``` ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/ui-calendar ``` **Dependencies:** - [motion](https://www.npmjs.com/package/motion) - [@emotion/is-prop-valid](https://www.npmjs.com/package/@emotion/is-prop-valid) - [date-fns](https://www.npmjs.com/package/date-fns) - [class-variance-authority](https://www.npmjs.com/package/class-variance-authority) - [sonner](https://www.npmjs.com/package/sonner) - [@hookform/resolvers](https://www.npmjs.com/package/@hookform/resolvers) - [react-hook-form](https://www.npmjs.com/package/react-hook-form) - [lucide-react](https://www.npmjs.com/package/lucide-react) - [re-resizable](https://www.npmjs.com/package/re-resizable) - [zod](https://www.npmjs.com/package/zod) ## Usage ```tsx import { Calendar } from "@docyrus/ui/components/calendar"; import type { CalendarProps, CalendarProviderProps, TCalendarView, TEventColor, IEvent, IUser, ICalendarCell, CalendarFilterItem } from "@docyrus/ui/components/calendar"; {}} onEventCreate={() => {}} onEventUpdate={() => {}} onEventDelete={() => {}} onEventClick={() => {}} onDaySelect={() => {}} onSlotClick={() => {}} onVisibleRangeChange={() => {}} onEventDrop={() => {}} hideAddButton hideHeaderAddButton hideCellAddButton hideUserSelect hideSettings hideFilter addButtonLabel="..." hideEventCount eventCountLabel="..." visibleViews="day" filterItems={CalendarFilterItem[]} onFilterChange={() => {}} renderFilterSelect={() => {}} sidebarContent={...} renderEventBadge={() => {}} searchPlaceholder="..." weekStartsOn={...} cellMinHeight={...} cellMinWidth={...} hourSlotHeight={...} startHour={0} endHour={0} disableHoverHighlight hoverHighlightClassName="..." /> ``` ## Variants | Variant | Description | |---------|-------------| | `default` | Default style | | `bordered` | Bordered — `border-2` | | `compact` | Compact — `text-xs` | ## Sizes | Size | Description | |------|-------------| | `sm` | Small — `max-w-3xl mx-auto` | | `default` | Default — `max-w-6xl mx-auto` | | `lg` | Large | ## API Reference | Prop | Type | Default | |------|------|---------| | `variant` | `"default"` \| `"bordered"` \| `"compact"` | `"default"` | | `size` | `"sm"` \| `"default"` \| `"lg"` | `"default"` | | `ref` | `Ref` | — | | `events` | `Array` | `[]` | | `users` | `Array` | `[]` | | `isLoading` | `boolean` | `false` | | `defaultView` | `TCalendarView` | `'month'` | | `onCreateEvent` | `(date: Date) => void` | — | | `onEventCreate` | `(event: IEvent) => void` | — | | `onEventUpdate` | `(event: IEvent) => void` | — | | `onEventDelete` | `(eventId: number) => void` | — | | `onEventClick` | `(event: IEvent) => void` | — | | `onDaySelect` | `(date: Date) => void` | — | | `onSlotClick` | `(start: Date, end: Date) => void` | — | | `onVisibleRangeChange` | `(range: { start: Date; end: Date }, view: TCalendarView) => void` | — | | `onEventDrop` | `(event: IEvent, newStart: Date, newEnd: Date) => void` | — | | `hideAddButton` | `boolean` | — | | `hideHeaderAddButton` | `boolean` | — | | `hideCellAddButton` | `boolean` | — | | `hideUserSelect` | `boolean` | — | | `hideSettings` | `boolean` | — | | `hideFilter` | `boolean` | — | | `addButtonLabel` | `string` | — | | `hideEventCount` | `boolean` | — | | `eventCountLabel` | `string` | — | | `visibleViews` | `Array` | — | | `filterItems` | `Array` | — | | `onFilterChange` | `(id: string) => void` | — | | `renderFilterSelect` | `(context: any) => ReactNode` | — | | `sidebarContent` | `ReactNode` | — | | `renderEventBadge` | `(event: IEvent, defaultBadge: ReactNode) => ReactNode` | — | | `searchPlaceholder` | `string` | — | | `weekStartsOn` | `TWeekStartsOn` | — | | `cellMinHeight` | `number \| string` | — | | `cellMinWidth` | `number \| string` | — | | `hourSlotHeight` | `number \| string` | — | | `startHour` | `number` | — | | `endHour` | `number` | — | | `disableHoverHighlight` | `boolean` | — | | `hoverHighlightClassName` | `string` | — | | `className` | `string` | — | ## Components | Component | Description | |-----------|-------------| | `Calendar` | Public export | | `CalendarBody` | Internal — `calendar-body.tsx` | | `CalendarSidebar` | Internal — `calendar-sidebar.tsx` | | `CalendarProvider` | Internal — `contexts/calendar-context.tsx` | | `DndProvider` | Internal — `contexts/dnd-context.tsx` | | `AddEditEventDialog` | Internal — `dialogs/add-edit-event-dialog.tsx` | | `EventDetailsDialog` | Internal — `dialogs/event-details-dialog.tsx` | | `EventListDialog` | Internal — `dialogs/events-list-dialog.tsx` | | `DraggableEvent` | Internal — `dnd/draggable-event.tsx` | | `DroppableArea` | Internal — `dnd/droppable-area.tsx` | | `ResizableEvent` | Internal — `dnd/resizable-event.tsx` | | `CalendarHeader` | Internal — `header/calendar-header.tsx` | | `DateNavigator` | Internal — `header/date-navigator.tsx` | | `TodayButton` | Internal — `header/today-button.tsx` | | `UserSelect` | Internal — `header/user-select.tsx` | | `Settings` | Internal — `settings/settings.tsx` | | `CalendarHeaderSkeleton` | Internal — `skeletons/calendar-header-skeleton.tsx` | | `CalendarSkeleton` | Internal — `skeletons/calendar-skeleton.tsx` | | `DayViewSkeleton` | Internal — `skeletons/day-view-skeleton.tsx` | | `MonthViewSkeleton` | Internal — `skeletons/month-view-skeleton.tsx` | | `WeekViewSkeleton` | Internal — `skeletons/week-view-skeleton.tsx` | | `YearViewSkeleton` | Internal — `skeletons/year-view-skeleton.tsx` | ## Type Exports | Type | Description | |------|-------------| | `CalendarProps` | — | | `CalendarProviderProps` | — | | `TCalendarView` | — | | `TEventColor` | — | | `IEvent` | — | | `IUser` | — | | `ICalendarCell` | — | | `CalendarFilterItem` | — | ## Type Reference ### CalendarProps | Field | Type | Description | |-------|------|-------------| | `ref` | `Ref` | — | | `events` | `Array` | — | | `users` | `Array` | — | | `isLoading` | `boolean` | — | | `defaultView` | `TCalendarView` | — | | `variant` | `'default' \| 'bordered' \| 'compact'` | — | | `size` | `'sm' \| 'default' \| 'lg'` | — | | `onCreateEvent` | `(date: Date) => void` | — | | `onEventCreate` | `(event: IEvent) => void` | — | | `onEventUpdate` | `(event: IEvent) => void` | — | | `onEventDelete` | `(eventId: number) => void` | — | | `onEventClick` | `(event: IEvent) => void` | — | | `onDaySelect` | `(date: Date) => void` | — | | `onSlotClick` | `(start: Date, end: Date) => void` | — | | `onVisibleRangeChange` | `(range: { start: Date; end: Date }, view: TCalendarView) => void` | — | | `onEventDrop` | `(event: IEvent, newStart: Date, newEnd: Date) => void` | — | | `hideAddButton` | `boolean` | — | | `hideHeaderAddButton` | `boolean` | — | | `hideCellAddButton` | `boolean` | — | | `hideUserSelect` | `boolean` | — | | `hideSettings` | `boolean` | — | | `hideFilter` | `boolean` | — | | `addButtonLabel` | `string` | — | | `hideEventCount` | `boolean` | — | | `eventCountLabel` | `string` | — | | `visibleViews` | `Array` | — | | `filterItems` | `Array` | — | | `onFilterChange` | `(id: string) => void` | — | | `renderFilterSelect` | `(context: any) => ReactNode` | — | | `sidebarContent` | `ReactNode` | — | | `renderEventBadge` | `(event: IEvent, defaultBadge: ReactNode) => ReactNode` | — | | `searchPlaceholder` | `string` | — | | `weekStartsOn` | `TWeekStartsOn` | — | | `cellMinHeight` | `number \| string` | — | | `cellMinWidth` | `number \| string` | — | | `hourSlotHeight` | `number \| string` | — | | `startHour` | `number` | — | | `endHour` | `number` | — | | `disableHoverHighlight` | `boolean` | — | | `hoverHighlightClassName` | `string` | — | ### TCalendarView `"day"` | `"week"` | `"month"` | `"year"` | `"agenda"` ### TEventColor `"blue"` ### IEvent | Field | Type | Description | |-------|------|-------------| | `id` | `number` | — | | `startDate` | `string` | — | | `endDate` | `string` | — | | `title` | `string` | — | | `color` | `TEventColor` | — | | `description` | `string` | — | | `user` | `IUser` | — | ### IUser | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `name` | `string` | — | | `picturePath` | `string \| null` | — | ### ICalendarCell | Field | Type | Description | |-------|------|-------------| | `day` | `number` | — | | `currentMonth` | `boolean` | — | | `date` | `Date` | — | ### CalendarFilterItem | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `label` | `string` | — | | `image` | `string \| null` | — |