> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Calendar - Web

> Calendar allows users to view and select a specific date or date range.

> [!NOTE]
>
> For development, import `Calendar` from
> `@servicetitan/anvil2`. For design, find it in the
> [Anvil2 file](https://www.figma.com/design/xaNQsvRKczoxu7pj0M6QT8/Anvil2-v3?node-id=61-5038).

![](https://mintcdn.com/servicetitan/sNURU8g7HcZmaG9s/images/docs/web/components/calendar/overview-image.png?fit=max\&auto=format\&n=sNURU8g7HcZmaG9s\&q=85\&s=57ce4e21f3396a707c4290d392984a2b)

## Anatomy

The Calendar consists of nine primary elements that work together to enable date viewing and selection.

![Anatomy of the Calendar
component](https://mintcdn.com/servicetitan/66tZkkkyD48ugyZL/images/docs/web/components/calendar/design/calendar-anatomy.png?fit=max\&auto=format\&n=66tZkkkyD48ugyZL\&q=85\&s=55d8dcfb34df03dc85d241932eb7a4f9)

1. **Header** - Navigation toolbar containing month and year controls
2. **Month button** - Opens month selection view
3. **Year button** - Opens year selection view
4. **Previous button** - Navigates to the previous month
5. **Next button** - Navigates to the next month
6. **Today button** - Navigates to today's date
7. **Month grid** - Table displaying days in a month
8. **Day cell** - A single cell in the month grid
9. **Selected day** - Selected date

## Options

The Calendar supports the following configurations to accommodate various date selection scenarios.

### Selection Mode

calendar-selection-mode

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-selection-mode?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex, Text } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex direction="row" gap="6" alignItems="start">
      <Flex direction="column" gap="2" alignItems="center">
        <Text size="large">
          <strong>Single Date Selection</strong>
        </Text>
        <Calendar defaultValue="2024-06-15" />
      </Flex>
      <Flex direction="column" gap="2" alignItems="center">
        <Text size="large">
          <strong>Date Range Selection</strong>
        </Text>
        <Calendar
          range
          defaultValue={{
            start: "2024-06-15",
            end: "2024-06-20",
          }}
        />
      </Flex>
    </Flex>
  );
}

export default App;
```

Calendar supports single date selection and date range selection modes. Single date mode allows selecting one date, while range mode enables selecting a start and end date.

### Start Day

calendar-startday

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-startday?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex, Text } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex direction="row" gap="4" alignItems="start">
      <Flex direction="column" gap="2" alignItems="center">
        <Text size="large">
          <strong>Sunday Start (Default)</strong>
        </Text>
        <Calendar defaultValue="2024-06-15" startDay="Sunday" />
      </Flex>
      <Flex direction="column" gap="2" alignItems="center">
        <Text size="large">
          <strong>Monday Start</strong>
        </Text>
        <Calendar defaultValue="2024-06-15" startDay="Monday" />
      </Flex>
    </Flex>
  );
}

export default App;
```

| Start day | Description |
| - | - |
| Sunday | Calendar week begins on Sunday (default) |
| Monday | Calendar week begins on Monday |

### Date Restrictions

calendar-mindatemaxdate

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-mindatemaxdate?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        minDate="2024-06-05"
        maxDate="2024-06-20"
      />
    </Flex>
  );
}

export default App;
```

Calendar supports date restrictions through minimum and maximum date boundaries. Dates outside the specified range are disabled and cannot be selected.

### Unavailable Dates

calendar-unavailabledates

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-unavailabledates?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        unavailable={{
          dates: [
            "2024-06-02",
            "2024-06-04",
            "2024-06-06",
            "2024-06-08",
            "2024-06-10",
          ],
        }}
      />
    </Flex>
  );
}

export default App;
```

Mark specific dates or days of the week as unavailable when they cannot be selected. Unavailable dates are visually distinct and cannot be selected.

### Locale and Timezone

Calendar adapts to different locales for date formatting and week start days. Timezone configuration ensures dates are interpreted correctly across different regions.

## Behavior

The Calendar responds to user interaction with distinct visual states and navigation patterns.

### Selection States

Selected dates display with distinct visual styling. In range mode, the start date, end date, and dates within the range are visually indicated. Hover states provide feedback during date selection.

### Navigation

Users navigate between months using Previous and Next buttons. Month and Year buttons switch to selection views for faster navigation across longer time periods. The Today button quickly returns focus to the current date.

### View Transitions

Calendar transitions between day, month, and year selection views. The header controls adapt based on the current view, showing relevant navigation options for each context.

### Date Constraints

When date restrictions or unavailable dates are configured, disabled dates are visually distinct and cannot receive focus or selection. Navigation automatically skips unavailable dates when using keyboard controls.

## Usage Guidelines

| Standard | Requirement |
| - | - |
| DoSelecting a single date | Allow users to select a single date for scheduling, filtering, or data entry |
| DoSelecting a date range | Enable date range selection for filtering data or scheduling periods |
| DoDisplaying a calendar grid | Display dates in a familiar calendar grid format |
| DoSelecting dates within forms | Provide date selection within forms or date input fields |
| DoSet date boundaries | Set minimum and maximum date boundaries when business rules or data availability create constraints; see [Set date boundaries to guide user choices](#set-date-boundaries-to-guide-user-choices). |
| DoMark unavailable dates | Mark specific dates or recurring days as unavailable when they cannot be selected; see [Mark unavailable dates to communicate constraints](#mark-unavailable-dates-to-communicate-constraints). |
| Don'tSimple date input | Use [DateField](https://anvil.servicetitan.com/docs/components/date-field-single/web.md) for text-based date entry when users prefer typing dates |
| Don'tTime selection | Calendar focuses on dates only; use [TimeField](https://anvil.servicetitan.com/docs/components/time-field/web.md) for time selection |
| Don'tDisplay-only dates | Use text or other display components when dates are not selectable |

### Alternatives

#### Calendar vs DateField

DateField provides text-based date input with calendar popover support. Use DateField when space is limited or users prefer typing dates. Use Calendar when you need a persistent calendar view or when date selection is the primary interaction.

### How to Use

#### Choose single or range selection based on user needs

Use single date selection when users need to pick one specific date, such as a deadline, appointment date, or event date. Single selection provides clear focus and reduces cognitive load for straightforward date choices.

Use date range selection when users need to define a period, such as vacation dates, report date ranges, or filtering time periods. Range selection helps users visualize the span and understand the relationship between start and end dates.

calendar-uncontrolled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-uncontrolled?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex justifyContent="center">
      <Calendar defaultValue="2024-03-14" />
    </Flex>
  );
}

export default App;
```

**Do**

Use single date selection for specific point-in-time selections. This pattern works well for scheduling, deadlines, and one-time events where users need clarity about a single date.

calendar-range

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-range?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex justifyContent="center">
      <Calendar
        range
        defaultValue={{
          start: new Date().toISOString(),
          end: new Date(
            new Date().setDate(new Date().getDate() + 5),
          ).toISOString(),
        }}
      />
    </Flex>
  );
}

export default App;
```

**Do**

Use date range selection when users need to define periods or spans. This pattern helps users understand duration and relationships between dates, making it ideal for filtering, reporting, and multi-day activities.

#### Set date boundaries to guide user choices

Use minimum and maximum date boundaries to prevent invalid selections and guide users toward appropriate date choices. Boundaries help users understand constraints before they attempt invalid selections, reducing errors and frustration.

calendar-mindatemaxdate

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-mindatemaxdate?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        minDate="2024-06-05"
        maxDate="2024-06-20"
      />
    </Flex>
  );
}

export default App;
```

**Do**

Set date boundaries when business rules or data availability create constraints. Clear boundaries help users understand what dates are valid, preventing errors and reducing support requests.

#### Mark unavailable dates to communicate constraints

Mark specific dates or recurring days as unavailable when they cannot be selected due to business rules, holidays, or system constraints. Visual distinction helps users understand why certain dates aren't selectable and prevents confusion.

calendar-unavailabledates

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-unavailabledates?file=src/App.tsx)

```tsx lines theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        unavailable={{
          dates: [
            "2024-06-02",
            "2024-06-04",
            "2024-06-06",
            "2024-06-08",
            "2024-06-10",
          ],
        }}
      />
    </Flex>
  );
}

export default App;
```

**Do**

Mark unavailable dates clearly to communicate constraints to users. This helps users understand why certain dates aren't selectable and prevents frustration from attempting invalid selections.

## Content

Content within the Calendar should be clear and accessible, helping users understand date availability and navigate efficiently.

* Use appropriate locale settings to format dates according to user expectations
* Ensure date restrictions are clearly communicated through visual styling
* Provide clear visual feedback for selected dates and date ranges
* Maintain consistent date formatting throughout the calendar interface

## Keyboard Interaction

Users can navigate the Calendar using standard keyboard controls.

| Key | Description |
| - | - |
| Tab | Move focus between header controls |
| Arrow Left | Move focus to the previous day |
| Arrow Right | Move focus to the next day |
| Arrow Up | Move focus to the same day in the previous week |
| Arrow Down | Move focus to the same day in the next week |
| Home | Move focus to the first day of the current week |
| End | Move focus to the last day of the current week |
| Page Up | Move focus to the same day in the previous month |
| Page Down | Move focus to the same day in the next month |
| Enter | Select the focused date |
| Space | Select the focused date |
| Escape | Close month or year selection views |

## Code

**Implementation**

## Live Component Playground

calendar-playground

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-playground?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [date, setDate] = useState<string>();

  return (
    <Flex direction="column" gap="3" alignItems="center">
      <Calendar
        defaultValue={date}
        onSelection={(date) => setDate(date.value)}
      />
      {date && `Selected Date: ${date}`}
    </Flex>
  );
}

export default App;
```

## Common Examples

```tsx theme={null}
import { Calendar } from "@servicetitan/anvil2";

function ExampleComponent() {
  return <Calendar defaultValue={new Date().toISOFormat()} />;
}
```

### Date Format

The `Calendar` component accepts [ISO 8601 date strings](https://anvil.servicetitan.com/docs/utilities/web/date-values.md) for `value` and `defaultValue`. Prefer date-only strings (for example, `"2025-07-02"`) for predictable calendar date selection.

`onSelection` returns a full ISO datetime string with timezone offset (for example, "2025-07-02T00:00:00.000-07:00"), or `undefined` when the selection is cleared.

Convert to a date-only string (for example, `const dateOnly = value?.split("T")[0];`) before passing the value to date fields or APIs that expect `YYYY-MM-DD`.

#### Example with new Date()

```tsx theme={null}
<Calendar defaultValue={new Date().toISOString()} />
```

### Controlling calendar state

calendar-controlled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-controlled?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex, Button } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [date, setDate] = useState<string | undefined>(
    new Date().toISOString(),
  );

  return (
    <Flex direction="column" gap={1} alignItems="center">
      <Calendar value={date} onSelection={({ value }) => setDate(value)} />
      <Button onClick={() => setDate("2000-01-01")} size="small">
        Go to millenium
      </Button>
    </Flex>
  );
}

export default App;
```

#### Uncontrolled calendars

By default, calendars handle their own state. Use the `defaultValue` prop to set the initial value of an uncontrolled calendar.

calendar-uncontrolled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-uncontrolled?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex justifyContent="center">
      <Calendar defaultValue="2024-03-14" />
    </Flex>
  );
}

export default App;
```

#### Controlled calendars

Use the `value` prop to manually control the state of a calendar.

### Selecting a date range

Calendar can also be used to select range of dates using `range` prop.

calendar-range

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-range?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex justifyContent="center">
      <Calendar
        range
        defaultValue={{
          start: new Date().toISOString(),
          end: new Date(
            new Date().setDate(new Date().getDate() + 5),
          ).toISOString(),
        }}
      />
    </Flex>
  );
}

export default App;
```

### Calendar focus

By default, the month of selected date or today is shown.

#### Overriding calendar focus

In the example below, `2024-07-07` is the selected date but June is showing on initial render because of `defaultFocusedDate="2024-06-06"`.

calendar-focuseddate

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-focuseddate?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex justifyContent="center">
      <Calendar defaultValue="2024-07-07" defaultFocusedDate="2024-06-06" />
    </Flex>
  );
}

export default App;
```

### Calendar Timezone

By default, local browser timezone is used. To override local system timezone, `defaultTimezone` can be used.

calendar-defaulttimezone

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-defaulttimezone?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [date, setDate] = useState<string>();

  return (
    <Flex direction="column" gap="3" alignItems="center">
      <Calendar
        onSelection={(date) => setDate(date.value)}
        defaultTimeZone="America/New_York"
      />
      {date && `Selected Date: ${date}`}
    </Flex>
  );
}

export default App;
```

### Scoping calendar dates

There are two different ways to limit the scope of selectable dates within a calendar.

calendar-unavailabledates

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-unavailabledates?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        unavailable={{
          dates: [
            "2024-06-02",
            "2024-06-04",
            "2024-06-06",
            "2024-06-08",
            "2024-06-10",
          ],
        }}
      />
    </Flex>
  );
}

export default App;
```

#### Min and Max

The `minDate` and `maxDate` props can be used to scope the date range selection.

calendar-mindatemaxdate

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/calendar-mindatemaxdate?file=src/App.tsx)

```tsx lines expandable theme={null}
import { Calendar, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex alignItems="center" direction="column">
      <Calendar
        defaultFocusedDate="2024-06-01"
        minDate="2024-06-05"
        maxDate="2024-06-20"
      />
    </Flex>
  );
}

export default App;
```

#### Unavailable dates

You can also pass an array of dates to the `unavailable.dates` prop to disable selecting specific dates.

**Calendar Props**

```tsx theme={null}
<Calendar
  defaultValue="2024-01-15"
  defaultFocusedDate="2024-01-01"
  defaultTimeZone="America/New_York"
  maxDate="2024-12-31"
  minDate="2024-01-01"
  unavailable={{ dates: ["2024-01-20", "2024-01-21"]}}
  value="2024-01-15"
/>
```

## `Calendar` Props

> [!NOTE]
>
> Props marked as BETA are currently only available if you import `Calendar` from `@servicetitan/anvil2/beta`.

**dateMetaData** `\{ date: string, context: string \}[]`

BETA Array of date metadata objects to display pips and provide context.

**defaultFocusedDate** `string | null`

Uncontrolled focus date. Sets the initially visible month and year.

**defaultTimeZone** `IanaZone` (default: Local browser timezone)

**defaultValue** `string | \{ start?: string; end?: string \}`

Uncontrolled date value. Object is only accepted when `range={true}`.

**focusedDate** `string | null` *deprecated*

Use `defaultFocusedDate` instead. `focusedDate` does not reliably control the initial view and will be removed in a future major release.

**locale** `Locale` (default: Browser locale)

The locale to use for the calendar.

**maxDate** `string`

**minDate** `string`

**onMonthView** `(\{ month, year \}: \{ month: number, year: number \}) =\> void`

BETA Callback when the visible month changes.

**onSelection** `(data: \{ value \}) =\> void`

Callback when a date is selected.

**range** `boolean`

Enable date range selection mode. When `true`, `value` and `defaultValue` accept objects with `start` and `end` properties.

**startDay** `"Sunday" | "Monday"` (default: Sunday)

The day of the week to start the calendar on.

**unavailable** `\{ daysOfWeek?: WeekdayNumbers[]; dates?: string[] \}`

The days of the week and specific dates that are unavailable.

**value** `string | \{ start?: string; end?: string \}`

Controlled date value. Object is only accepted when `range={true}`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.