---
title: Calendar
description: "A month grid for picking one day, several days, or a range."
sidebar:
  badge: New
---

```tsx
'use client';

import * as React from 'react';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarDemo() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());

  return <Calendar mode="single" selected={date} onSelect={setDate} />;
}
```

## Install

```bash
npx @madeui/cli add calendar
```

Installs `react-day-picker` and `date-fns` alongside the component.

## Usage

```tsx
import { Calendar } from '@/components/ui/calendar';
```

```tsx
const [date, setDate] = React.useState<Date | undefined>(new Date());

<Calendar mode="single" selected={date} onSelect={setDate} />
```

## Range

```tsx
'use client';

import * as React from 'react';

import { addDays } from 'date-fns';
import type { DateRange } from 'react-day-picker';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarRange() {
  const [range, setRange] = React.useState<DateRange | undefined>({
    from: new Date(),
    to: addDays(new Date(), 6),
  });

  return (
    <Calendar
      mode="range"
      selected={range}
      onSelect={setRange}
      numberOfMonths={2}
    />
  );
}
```

## Multiple

```tsx
'use client';

import * as React from 'react';

import { addDays } from 'date-fns';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarMultiple() {
  const [dates, setDates] = React.useState<Date[] | undefined>([
    new Date(),
    addDays(new Date(), 2),
    addDays(new Date(), 5),
  ]);

  return (
    <Calendar mode="multiple" selected={dates} onSelect={setDates} max={5} />
  );
}
```

## Dropdown caption

`captionLayout="dropdown"` swaps the caption for month and year selects, rendered with this library's [Select](/docs/components/select). `startMonth` / `endMonth` bound the navigable years.

Each trigger is sized to the longest label in the active locale, so month names are never truncated and the caption keeps its width as you move through the year.

```tsx
'use client';

import * as React from 'react';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarDropdown() {
  const [date, setDate] = React.useState<Date | undefined>(
    new Date(1990, 5, 15)
  );

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
      captionLayout="dropdown"
      defaultMonth={date}
      startMonth={new Date(1930, 0)}
      endMonth={new Date()}
    />
  );
}
```

## Disabled days

Any react-day-picker matcher works — here weekends and every day before today.

```tsx
'use client';

import * as React from 'react';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarDisabled() {
  const [date, setDate] = React.useState<Date | undefined>();

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
      disabled={[{ dayOfWeek: [0, 6] }, { before: new Date() }]}
    />
  );
}
```

## Week numbers

```tsx
'use client';

import * as React from 'react';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarWeekNumbers() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());

  return (
    <Calendar mode="single" selected={date} onSelect={setDate} showWeekNumber />
  );
}
```

## Small

```tsx
'use client';

import * as React from 'react';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarSizes() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());

  return <Calendar mode="single" selected={date} onSelect={setDate} size="sm" />;
}
```

## Locale

Pass a `date-fns` locale; weekday names, the caption, and the dropdown labels follow it.

```tsx
'use client';

import * as React from 'react';

import { tr } from 'date-fns/locale';

import { Calendar } from '@/components/ui/calendar';

export default function CalendarLocale() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
      locale={tr}
      weekStartsOn={1}
    />
  );
}
```

## API reference

Built on [react-day-picker](https://daypicker.dev). The table below covers the props this library adds or changes — every other prop (`mode`, `selected`, `onSelect`, `disabled`, `numberOfMonths`, `startMonth`, `locale`, `formatters`, …) is forwarded to `DayPicker`; see the [react-day-picker API reference](https://daypicker.dev/api) for the full list.

### Calendar

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `'sm' \| 'md'` | `'md'` | Day cell size: `md` is 32px cells, `sm` is 28px. |
| `showOutsideDays` | `boolean` | `true` | Changed default — days of the adjacent months fill the grid. |
| `captionLayout` | `'label' \| 'dropdown' \| 'dropdown-months' \| 'dropdown-years'` | `'label'` | Dropdown variants render the month / year pickers as `Select`. |
| `navLayout` | `'around' \| 'after'` | `'around'` | Changed default — each chevron is pinned to the caption row of its own month, so they stay aligned when the months wrap. `'after'` puts both chevrons in a row under the caption. |
| `style` | `StyleXStyles` | — | StyleX styles merged last on the root — always win over the component's own styles. |

Every slot is styled through react-day-picker's `classNames` prop with StyleX classes; your own `classNames` are merged last, so a key you pass replaces ours for that slot. The `nav` key only applies to `navLayout="after"` — the `around` default styles `button_previous` and `button_next` directly.

### Slots

The interactive parts are exported slot components. Pass your own through react-day-picker's `components` prop to replace one; the rest of the calendar keeps its styling.

| Slot | Component | Renders |
| --- | --- | --- |
| `DayButton` | `CalendarDayButton` | The `<button>` in each day cell, styled from the day's modifiers (`selected`, `today`, `outside`, `disabled`, `range_middle`). |
| `Chevron` | `CalendarChevron` | The nav and dropdown chevrons (lucide icons). |
| `WeekNumber` | `CalendarWeekNumber` | The row header when `showWeekNumber` is on. |
| `Dropdown` | `CalendarDropdown` | The month / year picker for the dropdown caption layouts, built on `Select`. |

```tsx
import { Calendar, CalendarDayButton } from '@/components/ui/calendar';

function DayWithTitle(props: React.ComponentProps<typeof CalendarDayButton>) {
  return <CalendarDayButton {...props} title={props.day.date.toDateString()} />;
}

<Calendar components={{ DayButton: DayWithTitle }} />
```

Slot components own their styling, so the `classNames` keys for those slots (`day_button`, `chevron`, `week_number`, `dropdown`) have no effect — override the component instead.

### Styling

`Calendar` accepts `style` (`StyleXStyles`, merged last so caller overrides always win). The slot components take react-day-picker's slot props; they do not accept `style`.
