> ## 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 – Code

> Calendar allows a user to pick a specific date or date range.

export const component_0 = "Calendar"

export const LiveCode = ({children, customHeight, clickToLoad, example, fullWidth, fullHeight, hideCodeInLiveCode, screenshot, screenshotOnly, showCode: showCodeProp}) => {
  const SCREENSHOTS_BASE = "https://servicetitan.github.io/anvil2-docs-live-code/screenshots";
  const STACKBLITZ_BASE = "https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples";
  const [showCodeBlock, setShowCodeBlock] = useState(showCodeProp ?? false);
  const [isLocalOverride, setIsLocalOverride] = useState(false);
  useEffect(() => {
    const examplePath = `/images/live-code-screenshots-tmp/${example}.png`;
    fetch(examplePath, {
      method: "HEAD"
    }).then(r => {
      if (r.ok) setIsLocalOverride(true);
    }).catch(() => {});
  }, [example]);
  const screenshotBase = isLocalOverride ? "/images/live-code-screenshots-tmp" : SCREENSHOTS_BASE;
  if (screenshotOnly) {
    return <Frame className="flex flex-col">
        <div className="flex dark:hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#FFFFFF"
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>
        <div className="hidden dark:flex" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#141414"
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>
      </Frame>;
  }
  if (screenshot) {
    return <Frame className="flex flex-col -mb-2">
        <div className="flex dark:hidden bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>

        <div className="hidden dark:flex bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      background: "#141414",
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>

        <div className="flex justify-end items-center text-xs py-2 px-1 gap-4">
          {!showCodeProp ? <button className="inline-flex justify-end items-center text-gray-700 dark:text-gray-50 hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1 cursor-pointer" onClick={() => setShowCodeBlock(!showCodeBlock)} style={{
      appearance: "none"
    }}>
              <Icon icon="code" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
              <span>{showCodeBlock ? "Hide code" : "Show code"}</span>
            </button> : null}

          <a className="inline-flex justify-end items-center hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1" href={`${STACKBLITZ_BASE}/${example}?file=src/App.tsx`} target="_blank" rel="noreferrer">
            <Icon icon="bolt" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
            <span>StackBlitz demo</span>
          </a>
        </div>

        <div className="grid transition-[grid-template-rows] duration-300 ease-in-out overflow-auto overflow-y-hidden overflow-x-auto" style={showCodeBlock ? {
      gridTemplateRows: "1fr"
    } : {
      gridTemplateRows: "0fr"
    }}>
          <div style={{
      minHeight: 0,
      overflowX: "auto",
      overflowY: "hidden",
      marginBlockStart: "-1.25rem",
      marginBlockEnd: "-1.5rem"
    }}>
            {children}
          </div>
        </div>
      </Frame>;
  } else {
    return <div style={{
      display: "flex",
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px",
      resize: "vertical",
      overflow: "auto"
    }}>
        <iframe title={example} style={{
      flex: 1,
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px"
    }} src={`${STACKBLITZ_BASE}/${example}?embed=1&hideNavigation=1&hideExplorer=1&terminalHeight=0&file=src/App.tsx${clickToLoad ? "&ctl=1" : ""}${hideCodeInLiveCode ? "&view=preview" : ""}`} allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" />
      </div>;
  }
};

<Tabs>
  <Tab title="Implementation">
    ## Live Component Playground

    <LiveCode showCode example="calendar-playground" fullWidth screenshot>
      ```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}
              focusedDate={new Date().toISOString()}
              onSelection={(date) => setDate(date.value)}
            />
            {date && `Selected Date: ${date}`}
          </Flex>
        );
      }

      export default App;
      ```
    </LiveCode>

    ## Common Examples

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

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

    ### Date Format

    To follow the [international standard](https://www.iso.org/iso-8601-date-and-time-format.html), the Anvil2 `Calendar` component uses ISO 8601 for date-time format. ISO date format strings should always be used when passing a date-time value to a `Calendar`. The same format is also returned by the `onSelection` callback.

    #### Example with new Date()

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

    ### Controlling calendar state

    <LiveCode showCode example="calendar-controlled" screenshot fullWidth>
      ```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;
      ```
    </LiveCode>

    #### Uncontrolled calendars

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

    <LiveCode showCode example="calendar-uncontrolled" screenshot fullWidth>
      ```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;
      ```
    </LiveCode>

    #### 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.

    <LiveCode showCode example="calendar-range" screenshot fullWidth>
      ```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;
      ```
    </LiveCode>

    ### 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 `focusedDate="2024-06-06"`.

    <LiveCode showCode example="calendar-focuseddate" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Calendar, Flex } from "@servicetitan/anvil2";

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

      export default App;
      ```
    </LiveCode>

    ### Calendar Timezone

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

    <LiveCode showCode example="calendar-defaulttimezone" screenshot fullWidth>
      ```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;
      ```
    </LiveCode>

    ### Scoping calendar dates

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

    <LiveCode showCode example="calendar-unavailabledates" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Calendar, Flex } from "@servicetitan/anvil2";

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

      export default App;
      ```
    </LiveCode>

    #### Min and Max

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

    <LiveCode showCode example="calendar-mindatemaxdate" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Calendar, Flex } from "@servicetitan/anvil2";

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

      export default App;
      ```
    </LiveCode>

    #### Unavailable dates

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

  <Tab title="Calendar Props">
    ```tsx theme={null}
    <Calendar
      defaultValue="2024-01-15"
      defaultFocusedDate="2024-01-01"
      defaultTimeZone="America/New_York"
      focusedDate="2024-01-15"
      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 <Badge color="blue">BETA</Badge> are currently only available if you import <code>{component_0}</code> from `@servicetitan/anvil2/beta`.
    </Note>

    <ParamField path="dateMetaData" type="{ date: string, context: string }[]">
      <Badge color="blue">BETA</Badge> Array of date metadata objects to display pips and provide context.
    </ParamField>

    <ParamField path="defaultFocusedDate" type="string">
      Uncontrolled focus date.
    </ParamField>

    <ParamField path="defaultTimeZone" type="IanaZone" default="Local browser timezone" />

    <ParamField path="defaultValue" type={`string | { start?: string; end?: string }`}>
      Uncontrolled date value. Object is only accepted when `range={true}`.
    </ParamField>

    <ParamField path="focusedDate" type="string">
      Controlled focus date.
    </ParamField>

    <ParamField path="locale" type="Locale" default="Browser locale">
      The locale to use for the calendar.
    </ParamField>

    <ParamField path="maxDate" type="string" />

    <ParamField path="minDate" type="string" />

    <ParamField path="onMonthView" type="({ month, year }: { month: number, year: number }) => void">
      <Badge color="blue">BETA</Badge> Callback when the visible month changes.
    </ParamField>

    <ParamField path="onSelection" type="(data: { value }) => void">
      Callback when a date is selected.
    </ParamField>

    <ParamField path="range" type="boolean">
      Enable date range selection mode. When `true`, `value` and `defaultValue` accept objects with `start` and `end` properties.
    </ParamField>

    <ParamField path="startDay" type={`"Sunday" | "Monday"`} default="Sunday">
      The day of the week to start the calendar on.
    </ParamField>

    <ParamField path="unavailable" type="{ daysOfWeek?: WeekdayNumbers[]; dates?: string[] }">
      The days of the week and specific dates that are unavailable.
    </ParamField>

    <ParamField path="value" type={`string | { start?: string; end?: string }`}>
      Controlled date value. Object is only accepted when `range={true}`.
    </ParamField>
  </Tab>
</Tabs>
