# 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` | — |