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

# Time Field - Web

> Allows users to enter a time into an input, potentially with predefined stops.

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

![](https://mintcdn.com/servicetitan/uz2PQSvO75TRhQ38/images/docs/web/components/shared/image-of-the-time-field-component-both-with-placeholder-and-the-entered-time-of-1105am.png?fit=max\&auto=format\&n=uz2PQSvO75TRhQ38\&q=85\&s=c717abfc082368523d714cd156c2448e)

## Anatomy

The Time Field consists of nine primary elements that work together to allow users to enter a time into an input.

![Anatomy of the Time Field
component](https://mintcdn.com/servicetitan/ar8TJanaRSxOpbCO/images/docs/web/components/time-field/design/anatomy-of-the-time-field-component.png?fit=max\&auto=format\&n=ar8TJanaRSxOpbCO\&q=85\&s=027e21b9b1bffe01e75daa656c1b44b5)

1. Label
2. Clock icon (permanent)
3. Hours (AM/PM variant)
4. Minutes (AM/PM variant)
5. AM/PM marker
6. Hours (24hr variant)
7. Minutes (24hr variant)
8. Options panel
9. Selected option

## Options

The Time Field supports 12-hour and 24-hour format configurations to accommodate various time entry scenarios.

### 12hr vs. 24 hour

Time Field supports 12-hour and 24-hour formats. 12-hour format is the default.

timefield-format

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

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

function App() {
  return (
    <Grid templateColumns="repeat(2, 1fr)" gap={4}>
      <TimeField
        label="Label"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Field with 24 hour format"
        format={24}
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />
    </Grid>
  );
}

export default App;
```

## Behavior

The Time Field responds to user interaction with distinct visual states, error handling, and min/max constraints.

### Visual States

timefield-data-interactive

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

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

function App() {
  return (
    <Grid templateColumns="repeat(2, 1fr)" gap={4}>
      <TimeField
        label="Label"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Label"
        disabled
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Label"
        data-interactive="focus-visible"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Label"
        description="An example description"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Label"
        error="Time out of bounds"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />
    </Grid>
  );
}

export default App;
```

### Erroring

* Errors occur when the field is required and the developer has added definitions for `isInputInvalid` and `isInputEmpty` properties on blur.
* When auto-rounding is set to `true` and the user enters a non-rounded value, the value updates on blur without erroring.
* When users must enter a time at a particular interval, use an input with suggestions and steps instead of erroring to guide the user.
* Read more about validation in the [code tab](https://anvil.servicetitan.com/docs/components/time-field/code#validation).

### Min/max setting

* Input accepts both min and max values.
* For option time fields, this sets the available options to a min and max based on the increment step.
* Times outside the time frame constraints cannot be entered into the field.
* Read more about min/max setting in the [code tab](https://anvil.servicetitan.com/docs/components/time-field/code#min-and-max-constraints).

## Usage Guidelines

| Standard | Requirement |
| - | - |
| DoInput a time | Use the Time Field when users need to input a time, such as recording when an event occurred or setting an appointment time. |
| DoLimited time frames | Only times within a range are valid, such as business hours set through min and max values. |
| DoFixed intervals | Users must enter times at set intervals, such as every 15 minutes, and options with steps guide the entry. |
| DoProvide an initial value | When possible, provide an initial value in the Time Field. For example, if appointments are only possible on a particular day between noon and 3pm, provide the time "12:00 PM" and allow the user to change it from there. |
| DoProvide min and max values | When possible, provide min and max values in the Time Field. For example, if appointments are only possible during business hours, add the opening and closing times as min and max values, so the user cannot make selections outside of the allotted time frame. |
| DoProvide intelligent time stops | Provide intelligent time stops for the user when selecting time if possible. For example, if the user can only input time(s) in 15 minute intervals, provide the options dropdown with that stop to help the user input their times correctly. |
| Don'tDates | Use a [Date Field Single](https://anvil.servicetitan.com/docs/components/date-field-single/web.md) for a single date or a [Date Field Range](https://anvil.servicetitan.com/docs/components/date-field-range/web.md) for a date span. |
| Don'tDurations | Use a [Number Field](https://anvil.servicetitan.com/docs/components/number-field/web.md) with a suffix such as minutes for an amount of time rather than a time of day. |

### How to Use

When possible, provide an initial value in the Time Field. For example, if appointments are only possible on a particular day between noon and 3pm, provide the time "12:00 PM" and allow the user to change it from there.

timefield-value-do

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

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

function App() {
  return (
    <TimeField
      label="Time Field with Initial Value"
      step={60}
      value="09:00AM"
      onChange={(change) => {
        // change function
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

When possible, provide min and max values in the Time Field. For example, if appointments are only possible during business hours, add the opening and closing times as min and max values, so the user cannot make selections outside of the allotted time frame. Here, the Time Picker displays values between 9am and 5pm.

timefield-minmax-do

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

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

function App() {
  return (
    <TimeField
      label="Field with min/max/autoround"
      min="09:00 AM"
      max="05:00 PM"
      description="Enter a time between 09:00 AM and 05:00 PM."
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

Provide intelligent time stops for the user when selecting time if possible. For example, if the user can only input time(s) in 15 minute intervals, provide the options dropdown with that stop to help the user input their times correctly.

timefield-step-do

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

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

function App() {
  return (
    <TimeField
      label="Field with step suggestions"
      step={30}
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

## Content

Content within the Time Field should clearly communicate the expected time format through labels and placeholder text.

## Keyboard Interaction

Users can navigate the Time Field using standard keyboard controls.

| Key | Action |
| - | - |
| Up and down arrows | Moves up and down between options and the AM/PM in the dropdown |
| Enter | Selects the time and closes the dropdown selector |

## Code

**Implementation**

timefield-playground

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

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

function App() {
  return (
    <TimeField
      label="Label"
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

## Common Examples

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

function ExampleComponent() {
  return (
    <TimeField
      label="Label Text"
      step={60}
      onChange={(change) => {
        // change function
      }}
    />
  );
}
```

### With Suggestions Enabled (Default)

By default, time fields use a 12-hour format and present suggested times in a dropdown based on the `step` prop. The dropdown is only present if there is more than one valid option to select from. Whether the dropdown is present or not, the input allows typing in the field itself to get to your desired time.

There is autocomplete for best guess assumptions of the time you might be going for based on a partial input value. If both AM and PM times both are possible options, AM takes precedence over PM for autocomplete.

timefield-playground

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

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

function App() {
  return (
    <TimeField
      label="Label"
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

### Without Suggestions

When `disableSuggestions` is set to true, the suggestions dropdown will no longer appear. All other features, including autocomplete, will continue to work as the user types.

timefield-disablesuggestions

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

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

function App() {
  return (
    <TimeField
      label="Field without suggestions"
      disableSuggestions
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

### Auto-Rounding

If the `autoround` prop is set to true, the time field will attempt to round to the next valid time on blur based on the `step` and `max` props. Note: rounding will always go to the future, never the past.

If suggestions are enabled, the suggestions will display the auto rounded options available, even if the time currently typed in the input is not yet rounded.

Add a `description` to allow users to know auto rounding is enabled for the field.

timefield-autoround

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

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

function App() {
  return (
    <TimeField
      label="Autorounding field"
      autoround
      description="Autorounding is enabled for this field"
      onChange={(change) => {
        console.log("Time changed:", change.time);
      }}
    />
  );
}

export default App;
```

### Min and Max Constraints

Use the `min` and `max` props to set a time frame constraint. When the props are present, a time outside the time frame can not be entered into the field.

Autocomplete will adjust to a time within the time frame if the partial value can fall within the constraint. For example, 02:-- will autocomplete to 02:00 PM for a 09:00 AM - 05:00 PM time frame instead of the default 02:00 AM since 02:00 AM does not fall between 09:00 AM and 05:00 PM.

`autoround` will cap at the max time even if it doesn't fully align with the step prop. For example: In a field with a 09:00 AM - 05:00 PM time frame and a step of 30 minutes, if 4:45 is entered it will round to 5:00 PM.

Add a `description` to allow users to know there is a time constraint.

timefield-minmax

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

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

function App() {
  return (
    <Grid templateColumns="repeat(2, 1fr)" gap={4}>
      <TimeField
        label="Field with min/max"
        min="09:00 AM"
        max="05:00 PM"
        description="Enter a time between 09:00 AM and 05:00 PM"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Field with min/max/autoround"
        min="09:00 AM"
        max="05:00 PM"
        autoround
        description="Enter a time between 09:00 AM and 05:00 PM. Autorounding is enabled."
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />
    </Grid>
  );
}

export default App;
```

### 24 Hour Format

Set the `format` prop to 24 to change to the time format. When using this format, ensure `min` and `max` times are also set to 24 hour format.

timefield-format-24

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

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

function App() {
  return (
    <Grid templateColumns="repeat(2, 1fr)" gap={4}>
      <TimeField
        label="Field with 24 hour format"
        format={24}
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />

      <TimeField
        label="Field with 24 hour format/min/max"
        format={24}
        min="09:00"
        max="17:00"
        description="Please enter a time between 09:00 AM and 17:00 PM"
        onChange={(change) => {
          console.log("Time changed:", change.time);
        }}
      />
    </Grid>
  );
}

export default App;
```

### Validation

Validation needs to be handled with the onChange. `isInputValid` and `isInputEmpty` are boolean props returned with the time so that custom validation can be applied. Note: Because of the use of the mask acts as a value for the input, native html validation will not occur.

timefield-isinputempty

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

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

function App() {
  const [, setTime] = useState<string | null>(null);
  const [error, setError] = useState<string>("");

  return (
    <TimeField
      label="Required field"
      required
      error={error}
      onChange={(change) => {
        setTime(change.time);

        if (change.isInputEmpty) {
          setError("Time is required");
        } else {
          setError("");
        }
      }}
    />
  );
}

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` ``).

timefield-markdownlabel

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

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

function App() {
  return (
    <Flex direction="column" gap="4" style={{ maxWidth: 400 }}>
      <TimeField label="**Bold** label" />
      <TimeField label="*Italic* label" />
      <TimeField label="***Bold and italic*** label" />
      <TimeField label="==Highlight== label" />
      <TimeField 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.

timefield-hidelabel

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

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

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

export default App;
```

**TimeField Props**

```tsx theme={null}
<TimeField
  label="Label Text"
  autoround={false}
  defaultValue="09:00 AM"
  disableSuggestions={false}
  format="12"
  max="05:00 PM"
  min="09:00 AM"
  step={30}
  value="10:30 AM"
  onChange={(change) => console.log(change)}
/>
```

## `TimeField` Props

In addition to the props listed below, the `TimeField` accepts most [TextField](https://anvil.servicetitan.com/docs/components/text-field/design) props with the exception of `type`, `placeholder`, `showCounter` and `maxLength`. This includes `label` (supports inline markdown; omitting is deprecated) and `hideLabel`.

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

If true, value will round to nearest future step. If there is a defined time
frame, the ceiling for rounding is the max time.

**defaultValue** `string | null`

Uncontrolled initial value for the component.

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

If true, the dropdown with suggested time options is not present.

**format** `"12" | "24"` (default: 12)

Time format for the component.

**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).

**max** `string`

Maximum allowed time for a time frame. Must be paired with `min`. String must
match the format set for the component.

**min** `string`

Minimum allowed time for a time frame. Must be paired with `max`. String must
match format set for the component.

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

Callback fired on blur or after a time is selected from the selection list.

**step** `number` (default: 30)

Time increments for the time suggestions and auto rounding.

**value** `string | null`

Controlled value for the component.

**TimeFieldChange Props**

```tsx theme={null}
// TimeFieldChange is returned by the onChange callback
const handleChange = (change: TimeFieldChange) => {
  console.log(change.isInputEmpty, change.isInputValid, change.time);
};
```

## `TimeFieldChange` Props

The onChange callback receives a TimeFieldChange object with the following properties:

**isInputEmpty** `boolean`

Whether the input is empty.

**isInputValid** `boolean`

Whether there is a validation issue aside from empty value with the input.

**time** `string | null`

The returned time string.


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