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

# Date Field Single - Web

> A form field for selecting a single date with calendar picker support.

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

![](https://mintcdn.com/servicetitan/66tZkkkyD48ugyZL/images/docs/web/components/date-field-single/overview-image.png?fit=max\&auto=format\&n=66tZkkkyD48ugyZL\&q=85\&s=5f8f2c2b9297e5c0e9db8390bbb3ec6f)

## Anatomy

Date Field Single consists of five primary elements that enable users to select a single date through text input or a calendar picker.

![Anatomy of the Date Field Single component](https://mintcdn.com/servicetitan/66tZkkkyD48ugyZL/images/docs/web/components/date-field-single/design/date-field-single-anatomy.png?fit=max\&auto=format\&n=66tZkkkyD48ugyZL\&q=85\&s=088296ad3ffb538b1e0a4c94ccdf3139)

1. **Label** - Identifies the field and its purpose
2. **Input field** - Text input for manual date entry with format mask
3. **Helper text** (Optional) - Description, format hint or error message

## Options

Date Field Single supports the following configurations to accommodate different use cases and regional preferences.

### Date Format Modes

datefieldsingle-mode

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

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

function App() {
  return (
    <Flex direction="column" gap="4" style={{ minWidth: "384px" }}>
      {/** US format (default) */}
      <DateFieldSingle label="US Format" mode="mm/dd/yyyy" />

      {/** International format */}
      <DateFieldSingle label="International Format" mode="dd/mm/yyyy" />
    </Flex>
  );
}

export default App;
```

Date Field Single supports two date format modes to match regional conventions. The default format is `mm/dd/yyyy` for US audiences, while `dd/mm/yyyy` is available for international users.

| Mode | Format | Use Case |
| - | - | - |
| mm/dd/yyyy | Default | US date format |
| dd/mm/yyyy | Optional | International date format |

### Sizes

datefieldsingle-size

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

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

function App() {
  return (
    <Flex direction="column" gap="4" style={{ minWidth: "384px" }}>
      <DateFieldSingle label="Small" size="small" />
      <DateFieldSingle label="Medium" size="medium" />
      <DateFieldSingle label="Large" size="large" />
    </Flex>
  );
}

export default App;
```

Three size options accommodate different layout densities and visual hierarchies.

| Size | Height |
| - | - |
| Small | 32px |
| Medium | 40px |
| Large | 48px |

### Calendar Picker

datefieldsingle-disablecalendar

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

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

function App() {
  return <DateFieldSingle disableCalendar />;
}

export default App;
```

The calendar picker can be disabled when manual text entry is preferred or when the calendar interface is not suitable for the use case.

## Behavior

Date Field Single responds to user interaction with distinct visual states and validation feedback.

### Visual States

datefieldsingle-visual-states

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

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

function App() {
  return (
    <Grid gap="6">
      <DateFieldSingle
        label="Appointment Date"
        defaultValue="2025-07-15"
        required
      />
      <DateFieldSingle
        label="Appointment Date"
        defaultValue="2025-07-15"
        required
        disabled
      />
      <DateFieldSingle
        label="Appointment Date"
        defaultValue="2025-07-15"
        required
        error="This date is unavailable"
      />
    </Grid>
  );
}

export default App;
```

The component displays different visual states to communicate field status and interactivity. Default state shows the field ready for input. Focus state highlights the active field. Error state displays validation messages when dates are invalid or required fields are empty. Disabled state prevents interaction while maintaining visual context.

### Calendar Interaction

Clicking the input field opens a popover calendar. Users can navigate months and select dates directly from the calendar. The calendar closes automatically after selection, and the selected date populates the input field.

### Validation

datefieldsingle-isdatevalid

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

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

function App() {
  const [value, setValue] = useState<string | null>();
  const [latestEvent, setLatestEvent] = useState<DateFieldSingleChange>();
  const [errorMessage, setErrorMessage] = useState("");

  const handleChange = (change: DateFieldSingleChange) => {
    setValue(change.date);
    setLatestEvent(change);
    if (change.isDateValid) setErrorMessage("");
  };

  const handleBlur = () => {
    if (!latestEvent) return;
    if (!latestEvent.isDateValid) return setErrorMessage("Invalid date");
    if (!latestEvent.isInputValid && !latestEvent.isInputEmpty)
      return setErrorMessage("Valid date, but input isn't fully filled");
  };
  return (
    <Flex direction="column">
      <DateFieldSingle
        label="Weekdays Only"
        description="Type a date falling on a weekend to see an error"
        value={value}
        onChange={handleChange}
        onBlur={handleBlur}
        error={errorMessage}
        unavailable={{ daysOfWeek: [6, 7] }}
      />
      <pre>{JSON.stringify(latestEvent, null, 2)}</pre>
    </Flex>
  );
}

export default App;
```

Date Field Single validates input in real time. The component checks for parseable dates, required field completion, date constraints (min/max dates), and unavailable dates or days of the week. Error messages appear below the field when validation fails.

## Usage Guidelines

| Standard | Requirement |
| - | - |
| DoCapturing a single date | Capture a single, specific date |
| DoProviding calendar context | Provide calendar visual context for date selection |
| DoSupporting manual and visual entry | Support both manual entry and visual selection |
| DoValidating dates | Validate dates against constraints like minimum or maximum dates |
| DoLabel dates clearly | Write labels that clearly communicate the purpose of the date selection, include format hints, set date constraints, and show validation errors immediately; see [Labeling and Context](#labeling-and-context). |
| Don'tDate ranges | Use [Date Field Range](https://anvil.servicetitan.com/docs/components/date-field-range/web.md) instead |
| Don'tRecurring dates without year | Use [Date Field Yearless](https://anvil.servicetitan.com/docs/components/date-field-yearless/web.md) for birthdays, anniversaries, or seasonal dates |
| Don'tTime selection | Use [Time Field](https://anvil.servicetitan.com/docs/components/time-field/web.md) for time-only inputs |
| Don'tAmbiguous context or format | Don't omit format guidance or use Date Field Single for dates where year information is irrelevant; see [Anti-pattern: Ambiguous Context and Format](#anti-pattern%3A-ambiguous-context-and-format). |

### Alternatives

#### Date Field Single vs Date Field Yearless

Use Date Field Single when the year is essential to the date selection, such as appointment scheduling or deadline setting. Use Date Field Yearless when the year is irrelevant, such as recurring annual events or template dates.

### How to Use

#### Labeling and Context

Provide clear, descriptive labels that communicate the purpose of the date selection. Labels should indicate what the date represents and why it's needed. Use helper text or descriptions when additional context helps users understand constraints or requirements.

datefieldsingle-appointment-scheduling

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

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

function App() {
  return (
    <DateFieldSingle
      label="Event Date"
      description="Select the date when this event occurs"
      minDate={new Date().toISOString()}
      required
    />
  );
}

export default App;
```

**Do**

* Write labels that clearly communicate the purpose of the date selection
* Include format hints to guide users on expected input format
* Set appropriate date constraints (min/max dates) to prevent invalid selections
* Display validation errors immediately when they occur
* Use the calendar picker to provide visual date selection when helpful

#### Anti-pattern: Ambiguous Context and Format

Avoid creating confusion by omitting format guidance or using Date Field Single for dates where year information is irrelevant.

datefieldsingle-recurring-events-dont

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

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

function App() {
  return <DateFieldSingle label="Date" required />;
}

export default App;
```

**Don’t**

* Use Date Field Single for recurring annual events where year doesn't matter
* Omit format hints when the date format might be ambiguous to users
* Hide validation errors until form submission
* Use placeholder text to communicate date format instead of format hints
* Create labels that don't clearly indicate what date is being selected

## Content

Content within Date Field Single should be clear, concise, and actionable.

* Labels should clearly indicate what date is being selected
* Error messages should explain why a date is invalid and how to fix it
* Format hints should match the selected mode (mm/dd/yyyy or dd/mm/yyyy)
* Descriptions should provide context without overwhelming the user

## Keyboard Interaction

Users can navigate Date Field Single using standard keyboard controls.

### Input Field

| Key | Description |
| - | - |
| Tab | Moves focus to the next element |
| Shift + Tab | Moves focus to the previous element |
| Arrow Down | Opens the calendar picker when focused |
| Esc | Closes the calendar picker |

### Calendar Picker

| Key | Description |
| - | - |
| Arrow Left | Moves focus to the previous day |
| Arrow Right | Moves focus to the next day |
| Arrow Up | Moves focus to the same day in the previous week |
| Arrow Down | Moves focus to the same day in the next week |
| Page Up | Moves focus to the same day in the previous month |
| Page Down | Moves focus to the same day in the next month |
| Shift + Page Up | Moves focus to the same day in the previous year |
| Shift + Page Down | Moves focus to the same day in the next year |
| Enter | Selects the focused date |
| Space | Selects the focused date |
| Esc | Closes the calendar picker |

### Accessibility

Date Field Single includes built-in accessibility features. The component supports full keyboard navigation and screen reader compatibility. Ensure labels are descriptive and error messages are clear for assistive technology users.

For more guidance on form field labels and context, see [input field context association best practices](https://anvil.servicetitan.com/docs/accessibility/labels-and-ctas.md#input-field-context-association).

## Code

**Implementation**

datefieldsingle-playground

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

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

function App() {
  return <DateFieldSingle />;
}

export default App;
```

## Common Examples

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

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

### Date string values

`DateFieldSingle` accepts and returns [ISO 8601 date strings](https://anvil.servicetitan.com/docs/utilities/web/date-values.md) (for example, `"2025-07-02"`) rather than JavaScript `Date` objects. Convert `Date` values from API clients or Anvil1 Date Picker before passing them to the component.

### Default values

Default values can be included in `DateFieldSingle` to use the field in an uncontrolled mode.

datefieldsingle-defaultvalue

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

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

function App() {
  return <DateFieldSingle defaultValue={new Date().toISOString()} />;
}

export default App;
```

### Controlled usage

The `DateFieldSingle` can be controlled. This means you can maintain the state outside the component. Listen for new dates with `onChange` and supply a date into the `value` prop.

datefieldsingle-controlled

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

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

function App() {
  const [value, setValue] = useState<string | null>();

  return (
    <Flex gap={4}>
      <DateFieldSingle
        value={value}
        onChange={(change) => setValue(change.date)}
      />
      <Button
        onClick={() => {
          setValue(new Date().toISOString());
        }}
      >
        Set to today
      </Button>
    </Flex>
  );
}

export default App;
```

### Validation

Understanding the object passed back in `onChange` is key to understanding how to validate this field.

`isDateValid` will tell you if the *last entered date* is valid according to the props you've supplied (e.g. `required`, `minDate`, `maxDate`, and `unavailable`).

`isInputValid` will tell you only if the underlying `input` is a parseable date -- this does not consider whether the date is good according the other props.

`isInputEmpty` will tell you if the underlying `input` has no digits entered.

Typically, you will want to use these values together to determine the overall validity of the field. Though the simplest implementation may likely suffice to use only `isDateValid`.

datefieldsingle-isdatevalid

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

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

function App() {
  const [value, setValue] = useState<string | null>();
  const [latestEvent, setLatestEvent] = useState<DateFieldSingleChange>();
  const [errorMessage, setErrorMessage] = useState("");

  const handleChange = (change: DateFieldSingleChange) => {
    setValue(change.date);
    setLatestEvent(change);
    if (change.isDateValid) setErrorMessage("");
  };

  const handleBlur = () => {
    if (!latestEvent) return;
    if (!latestEvent.isDateValid) return setErrorMessage("Invalid date");
    if (!latestEvent.isInputValid && !latestEvent.isInputEmpty)
      return setErrorMessage("Valid date, but input isn't fully filled");
  };
  return (
    <Flex direction="column">
      <DateFieldSingle
        label="Weekdays Only"
        description="Type a date falling on a weekend to see an error"
        value={value}
        onChange={handleChange}
        onBlur={handleBlur}
        error={errorMessage}
        unavailable={{ daysOfWeek: [6, 7] }}
      />
      <pre>{JSON.stringify(latestEvent, null, 2)}</pre>
    </Flex>
  );
}

export default App;
```

### Disabled hint text

The hint text can be disabled. If the hint text is disabled, ensure that the date format is displayed on the page.

datefieldsingle-disablehint

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

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

function App() {
  return <DateFieldSingle disableHint />;
}

export default App;
```

### Timezone

The `timezone` prop controls the meaning of the "Today" button and which month-year the calendar initially displays. When the timezone differs from the user's locale, a disambiguation message appears below the calendar.

datefieldsingle-timezone

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

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

function App() {
  const [value, setValue] = useState<string | null>(null);

  return (
    <DateFieldSingle
      label="Appointment Date"
      timezone="Australia/Sydney"
      value={value}
      onChange={(change) => setValue(change.date)}
    />
  );
}

export default App;
```

### Disable calendar popover

The display of the `Calendar` can be prevented by passing `disableCalendar`.

datefieldsingle-disablecalendar

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

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

function App() {
  return <DateFieldSingle disableCalendar />;
}

export default App;
```

### Markdown in labels

The `label` prop supports inline markdown: bold (`**text**`), italic (`*text*`), bold and italic (`***text***`), highlight (`==text==`), and code (`` `text` ``).

datefieldsingle-markdownlabel

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

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

function App() {
  return (
    <Flex direction="column" gap="4" style={{ maxWidth: 400 }}>
      <DateFieldSingle label="**Bold** label" />
      <DateFieldSingle label="*Italic* label" />
      <DateFieldSingle label="***Bold and italic*** label" />
      <DateFieldSingle label="==Highlight== label" />
      <DateFieldSingle label="`Code` label" />
    </Flex>
  );
}

export default App;
```

### Hide the label

Use `hideLabel` to visually hide the label. The `label` string is converted to an `aria-label` on the input so it remains accessible to screen readers — any inline markdown is stripped to plain text.

datefieldsingle-hidelabel

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

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

function App() {
  return <DateFieldSingle label="Start date" hideLabel />;
}

export default App;
```

## Testing

The field's interactive sub-elements carry a stable `data-anv-part` attribute so end-to-end tests can target them directly. The library owns the part names; you supply the instance identifier.

Attach your own `data-*` attribute (such as `data-cy` or `data-testid`) to the field. It is forwarded to the masked text input — the one element present in every mode, including `disableCalendar`:

```tsx theme={null}
<DateFieldSingle data-cy="start-date" label="Start date" />
```

```ts theme={null}
cy.get('[data-cy="start-date"]').type("06/15/2025");
```

| `data-anv-part` | Element |
| - | - |
| `date-input` | Masked text input |
| `popover` | Calendar popover container |
| `date-calendar` | Calendar surface inside the popover |

> [!NOTE]
>
> The popover and calendar render in the browser's top layer, outside the input's subtree, so a descendant query scoped to your `data-cy` on the input will not reach them. Target them by their part attribute directly (`[data-anv-part="date-calendar"]`) or by the popover's `data-testid="calendar-popover"`. Only one calendar is open at a time.

**DateFieldSingle Props**

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

function ExampleComponent() {
return (

<DateFieldSingle
  defaultValue={new Date().toISOString()}
  mode="mm/dd/yyyy"
  disableHint={false}
  disableCalendar={false}
  required={false}
/>
); }

```

## `DateFieldSingle` Props

**defaultValue** `string | null`

Uncontrolled initial value for the date range.

**onChange** `(change: DateFieldSingleChange) =\> void`

Callback fired when the value changes.

**value** `string | null`

Controlled value for the date range (ISO 8601 strings).

**disableCalendar** `boolean` (default: false)

If true, disables the calendar popover.

**disableHint** `boolean` (default: false)

If true, disables the format hint below the field.

**maxDate** `string`

Maximum selectable date (ISO 8601).

**minDate** `string`

Minimum selectable date (ISO 8601).

**mode** `"mm/dd/yyyy" | "dd/mm/yyyy"` (default: mm/dd/yyyy)

Date input format.

**required** `boolean` (default: false)

If true, the field is required.

**timezone** `IanaZone`

IANA timezone identifier (e.g., "America/Los\_Angeles"). Controls the "Today" button behavior and initial calendar display. Shows a disambiguation message when different from the user's locale timezone.

**unavailable** `\{ dates?: string[]; daysOfWeek?: (1 | 2 | 3 | 4 | 5 | 6 | 7)[] \}`

Dates or days of week that are unavailable for selection.

### Additional field props

**description** `string`

Additional description below the field.

**disabled** `boolean` (default: false)

If true, disables the field.

**error** `ReactElement | string | boolean`

Error message or state.

**errorAriaLive** `"off" | "polite" | "assertive"` (default: assertive)

ARIA live region setting for error messages.

**hideLabel** `boolean` (default: false)

Visually hides the label while keeping it accessible to screen readers via `aria-label`.

**label** `ReactNode`

Label for the field. Supports inline markdown formatting.

> [!WARNING]
>
> Omitting `label` is deprecated and will be required in v4.0.0. Use `hideLabel` to visually hide it. Passing `ReactNode` is also deprecated — use a plain string with inline markdown instead.

**labelProps** `Omit\<FieldLabelProps, "children" | "id" | "htmlFor"\>`

Additional props passed to the [FieldLabel](https://anvil.servicetitan.com/docs/components/field-label/code) component. Supports the `aiMark` prop for displaying [AI-powered field indicators](https://anvil.servicetitan.com/docs/utilities/web/ai-marks.md).

**loading** `boolean` (default: false)

If true, shows a loading spinner.

**moreInfo** `ReactNode`

Additional info icon or content for the label.

**placeholder** `string`

Placeholder text.

**size** `"small" | "medium" | "large"` (default: medium)

Input size.

**suffix** `string | ReactElement`

Suffix element to display inside the input.

**type** `"text" | "email" | "tel" | "url" | "password" | "number"` (default: text)

Input type.

**DateFieldSingleChange**

## DateFieldSingleChange

The `onChange` callback receives a `DateFieldSingleChange` object with the following properties:

**date** `string | null`

The date in ISO 8601 format (e.g., "2025-07-02").

**isDateValid** `boolean`

Whether the date is valid according to all constraints (required, unavailable
dates/days, min/max date, etc.).

**isInputEmpty** `boolean`

Whether the input is empty.

**isInputValid** `boolean`

Whether the input matches the format and is not empty.


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