---
title: Calendar
description: Date selection calendar with single, multiple, and range modes.
icon: calendar
---

import { ComponentPreview } from '/snippets/component-preview.mdx'

The Calendar component renders a month view for selecting dates. It supports single date, multiple date, and date range selection. Selected dates are stored in client state as ISO strings.

## Basic Usage

<ComponentPreview json={{"view":{"type":"Calendar","mode":"single","name":"selectedDate"}}}>
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Calendar

Calendar(name="selectedDate")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "type": "Calendar",
    "mode": "single",
    "name": "selectedDate"
  }
}
```
</CodeGroup>
</ComponentPreview>

## Range Selection

Set `mode="range"` to let users select a start and end date. The selected range is stored as a JSON object with `from` and `to` ISO strings.

<ComponentPreview json={{"view":{"type":"Calendar","mode":"range","name":"dateRange"},"state":{"dateRange":"{\"from\": \"2025-06-10T12:00:00.000Z\", \"to\": \"2025-06-20T12:00:00.000Z\"}"}}}>
<CodeGroup>
```python Python icon="python"
import json
from prefab_ui.app import set_initial_state
from prefab_ui.components import Calendar

set_initial_state(
    dateRange=json.dumps({
        "from": "2025-06-10T12:00:00.000Z",
        "to": "2025-06-20T12:00:00.000Z",
    })
)

Calendar(mode="range", name="dateRange")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "type": "Calendar",
    "mode": "range",
    "name": "dateRange"
  },
  "state": {
    "dateRange": "{\"from\": \"2025-06-10T12:00:00.000Z\", \"to\": \"2025-06-20T12:00:00.000Z\"}"
  }
}
```
</CodeGroup>
</ComponentPreview>

## Multiple Selection

Select multiple individual dates with `mode="multiple"`. Selected dates are stored as a JSON array of ISO strings.

<ComponentPreview json={{"view":{"type":"Calendar","mode":"multiple","name":"selectedDates"},"state":{"selectedDates":"[\"2025-06-10T12:00:00.000Z\", \"2025-06-15T12:00:00.000Z\", \"2025-06-22T12:00:00.000Z\"]"}}}>
<CodeGroup>
```python Python icon="python"
import json
from prefab_ui.app import set_initial_state
from prefab_ui.components import Calendar

set_initial_state(
    selectedDates=json.dumps([
        "2025-06-10T12:00:00.000Z",
        "2025-06-15T12:00:00.000Z",
        "2025-06-22T12:00:00.000Z",
    ])
)

Calendar(mode="multiple", name="selectedDates")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "type": "Calendar",
    "mode": "multiple",
    "name": "selectedDates"
  },
  "state": {
    "selectedDates": "[\"2025-06-10T12:00:00.000Z\", \"2025-06-15T12:00:00.000Z\", \"2025-06-22T12:00:00.000Z\"]"
  }
}
```
</CodeGroup>
</ComponentPreview>

## Displaying the Selection

Bind the calendar's state to a label using `{{ name | date }}` to show a formatted date. Click a date below to see it update:

<ComponentPreview json={{"view":{"cssClass":"gap-6","type":"Row","children":[{"type":"Calendar","mode":"single","name":"selectedDate"},{"cssClass":"gap-2","type":"Column","children":[{"content":"Selected date:","type":"Text"},{"content":"{{ selectedDate | date:long }}","bold":true,"type":"Text"},{"content":"Raw: {{ selectedDate }}","type":"Muted"}]}]},"state":{"selectedDate":"2025-06-15T12:00:00.000Z"}}}>
<CodeGroup>
```python Python icon="python"
from prefab_ui.app import set_initial_state
from prefab_ui.components import (
    Calendar,
    Column,
    Muted,
    Row,
    Text,
)

set_initial_state(selectedDate="2025-06-15T12:00:00.000Z")

with Row(gap=6):
    Calendar(name="selectedDate")
    with Column(gap=2):
        Text("Selected date:")
        Text("{{ selectedDate | date:long }}", bold=True)
        Muted("Raw: {{ selectedDate }}")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-6",
    "type": "Row",
    "children": [
      {
        "type": "Calendar",
        "mode": "single",
        "name": "selectedDate"
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {
            "content": "Selected date:",
            "type": "Text"
          },
          {
            "content": "{{ selectedDate | date:long }}",
            "bold": true,
            "type": "Text"
          },
          {
            "content": "Raw: {{ selectedDate }}",
            "type": "Muted"
          }
        ]
      }
    ]
  },
  "state": {
    "selectedDate": "2025-06-15T12:00:00.000Z"
  }
}
```
</CodeGroup>
</ComponentPreview>

The label updates instantly when the user clicks a date. The `date:long` format turns an ISO string like `"2025-01-15"` into `"January 15, 2025"`.

## API Reference

<Card icon="code" title="Calendar Parameters">
<ParamField body="mode" type="str" default="single">
  Selection mode: `"single"`, `"multiple"`, or `"range"`.
</ParamField>

<ParamField body="name" type="str | None" default="None">
  State key for storing the selected date. Single mode stores an ISO string; range mode stores `{"from": "...", "to": "..."}`.
</ParamField>

<ParamField body="on_change" type="Action | list[Action] | None" default="None">
  Action(s) triggered when the selection changes.
</ParamField>

<ParamField body="css_class" type="str | None" default="None">
  Additional Tailwind CSS classes.
</ParamField>
</Card>

## Protocol Reference

```json Calendar
{
  "type": "Calendar",
  "mode?": "single | multiple | range",
  "name?": "string",
  "onChange?": "Action | Action[]",
  "cssClass?": "string"
}
```

For the complete protocol schema, see [Calendar](/protocol/calendar).
