Back to Heroui

TimeField

apps/docs/content/docs/en/react/components/(date-and-time)/time-field.mdx

3.2.314.7 KB
Original Source

Usage

tsx
import { TimeField } from '@heroui/react';
<ComponentPreview name="time-field-basic" />

Anatomy

tsx
import {TimeField, Label, Description, FieldError} from '@heroui/react';

export default () => (
  <TimeField>
    <Label />
    <TimeField.Group>
      <TimeField.Input>
        {(segment) => <TimeField.Segment segment={segment} />}
      </TimeField.Input>
    </TimeField.Group>
    <Description />
    <FieldError />
  </TimeField>
)

TimeField combines label, time input, description, and error into a single accessible component.

Examples

With Icons

Add prefix or suffix icons to enhance the time field.

<ComponentPreview name="time-field-with-prefix-icon" /> <ComponentPreview name="time-field-with-suffix-icon" /> <ComponentPreview name="time-field-with-prefix-and-suffix" />

On Surface

When used inside a Surface component, use variant="secondary" on TimeField.Group to apply the lower emphasis variant suitable for surface backgrounds.

<ComponentPreview name="time-field-on-surface" />

With Description

<ComponentPreview name="time-field-with-description" />

Required Field

<ComponentPreview name="time-field-required" />

Disabled State

<ComponentPreview name="time-field-disabled" />

Full Width

<ComponentPreview name="time-field-full-width" />

Validation

Use isInvalid together with FieldError to surface validation messages.

<ComponentPreview name="time-field-invalid" />

Controlled

Control the value to synchronize with other components or state management.

<ComponentPreview name="time-field-controlled" />

Form Example

Complete form example with validation and submission handling.

<ComponentPreview name="time-field-form-example" />

With Validation

TimeField supports validation with minValue, maxValue, and custom validation logic.

<ComponentPreview name="time-field-with-validation" />

Render Function

<ComponentPreview name="time-field-render-function" />

Customization

Tailwind CSS

<ComponentPreview name="time-field-custom-styles" />

Global CSS

TimeField has minimal default styling. Override the .time-field class to customize the container styling.

css
@layer components {
  .time-field {
    @apply flex flex-col gap-1;

    &[data-invalid="true"],
    &[aria-invalid="true"] {
      [data-slot="description"] {
        @apply hidden;
      }
    }

    [data-slot="label"] {
      @apply w-fit;
    }

    [data-slot="description"] {
      @apply px-1;
    }
  }
}

Styling Reference

HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.

CSS Classes

  • .time-field – Root container with minimal styling (flex flex-col gap-1)

Note: Child components (Label, Description, FieldError) have their own CSS classes and styling. See their respective documentation for customization options. TimeField.Group styling is documented below in the API Reference section.

Interactive States

TimeField automatically manages these data attributes based on its state:

  • Invalid: [data-invalid="true"] or [aria-invalid="true"] - Automatically hides the description slot when invalid
  • Required: [data-required="true"] - Applied when isRequired is true
  • Disabled: [data-disabled="true"] - Applied when isDisabled is true
  • Focus Within: [data-focus-within="true"] - Applied when any child input is focused

API Reference

TimeField

TimeField inherits all props from React Aria's TimeField component.

Base Props

PropTypeDefaultDescription
childrenReact.ReactNode | (values: TimeFieldRenderProps) => React.ReactNode-Child components (Label, TimeField.Group, etc.) or render function.
classNamestring | (values: TimeFieldRenderProps) => string-CSS classes for styling, supports render props.
styleReact.CSSProperties | (values: TimeFieldRenderProps) => React.CSSProperties-Inline styles, supports render props.
fullWidthbooleanfalseWhether the time field should take full width of its container
idstring-The element's unique identifier.
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, TimeFieldRenderProps>-Overrides the default DOM element with a custom render function.

Value Props

PropTypeDefaultDescription
valueTimeValue | null-Current value (controlled). Uses @internationalized/date types.
defaultValueTimeValue | null-Default value (uncontrolled). Uses @internationalized/date types.
onChange(value: TimeValue | null) => void-Handler called when the value changes.
placeholderValueTimeValue | null-Placeholder time that influences the format of the placeholder. Defaults to 12:00 AM or 00:00 depending on the hour cycle.

Validation Props

PropTypeDefaultDescription
isRequiredbooleanfalseWhether user input is required before form submission.
isInvalidboolean-Whether the value is invalid.
minValueTimeValue | null-The minimum allowed time that a user may select. Uses @internationalized/date types.
maxValueTimeValue | null-The maximum allowed time that a user may select. Uses @internationalized/date types.
validate(value: TimeValue) => ValidationError | true | null | undefined-Custom validation function.
validationBehavior'native' | 'aria''native'Whether to use native HTML form validation or ARIA attributes.

Format Props

PropTypeDefaultDescription
granularity'hour' | 'minute' | 'second''minute'Determines the smallest unit displayed in the time picker.
hourCycle12 | 24-Whether to display time in 12 or 24 hour format. By default, determined by locale.
hideTimeZonebooleanfalseWhether to hide the time zone abbreviation.
shouldForceLeadingZerosboolean-Whether to always show leading zeros in the hour field. By default, determined by locale.

State Props

PropTypeDefaultDescription
isDisabledboolean-Whether the input is disabled.
isReadOnlyboolean-Whether the input can be selected but not changed.

Form Props

PropTypeDefaultDescription
namestring-Name of the input element, for HTML form submission. Submits as ISO 8601 string.
autoFocusboolean-Whether the element should receive focus on render.

Accessibility Props

PropTypeDefaultDescription
aria-labelstring-Accessibility label when no visible label is present.
aria-labelledbystring-ID of elements that label this field.
aria-describedbystring-ID of elements that describe this field.
aria-detailsstring-ID of elements with additional details.

Composition Components

TimeField works with these separate components that should be imported and used directly:

  • Label - Field label component from @heroui/react
  • TimeField.Group - Time input group component (documented below)
  • TimeField.Input - Input component with segmented editing from @heroui/react
  • TimeField.Segment - Individual time segment (hour, minute, second, etc.)
  • TimeField.Prefix / TimeField.Suffix - Prefix and suffix slots for the input group
  • Description - Helper text component from @heroui/react
  • FieldError - Validation error message from @heroui/react

Each of these components has its own props API. Use them directly within TimeField for composition:

tsx
import {parseTime} from '@internationalized/date';
import {TimeField, Label, Description, FieldError} from '@heroui/react';

<TimeField
  isRequired
  isInvalid={hasError}
  minValue={parseTime('09:00')}
  maxValue={parseTime('17:00')}
  value={time}
  onChange={setTime}
>
  <Label>Appointment Time</Label>
  <TimeField.Group>
    <TimeField.Input>
      {(segment) => <TimeField.Segment segment={segment} />}
    </TimeField.Input>
  </TimeField.Group>
  <Description>Select a time between 9:00 AM and 5:00 PM.</Description>
  <FieldError>Please select a valid time.</FieldError>
</TimeField>

TimeValue Types

TimeField uses types from @internationalized/date:

  • Time - Time only (hour, minute, second)
  • CalendarDateTime - Date with time but no timezone (TimeField displays only the time portion)
  • ZonedDateTime - Date with time and timezone (TimeField displays only the time portion)

Example:

tsx
import {parseTime, Time, getLocalTimeZone, now} from '@internationalized/date';

// Parse from string
const time = parseTime('14:30');

// Create from current time
const currentTime = now(getLocalTimeZone());
const timeValue = new Time(currentTime.hour, currentTime.minute, currentTime.second);

// Use in TimeField
<TimeField value={time} onChange={setTime}>
</TimeField>

Note: TimeField uses the @internationalized/date package for time manipulation, parsing, and type definitions. See the Internationalized Date documentation for more information about available types and functions.

Render Props

When using render props with className, style, or children, these values are available:

PropTypeDescription
isDisabledbooleanWhether the field is disabled.
isInvalidbooleanWhether the field is currently invalid.
isReadOnlybooleanWhether the field is read-only.
isRequiredbooleanWhether the field is required.
isFocusedbooleanWhether the field is currently focused.
isFocusWithinbooleanWhether any child element is focused.
isFocusVisiblebooleanWhether focus is visible (keyboard navigation).

TimeField.Group

TimeField.Group accepts all props from React Aria's Group component plus the following:

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component styles.
variant"primary" | "secondary""primary"Visual variant of the component. primary is the default style with shadow. secondary is a lower emphasis variant without shadow, suitable for use in surfaces.

TimeField.Input

TimeField.Input accepts all props from React Aria's DateInput component plus the following:

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component styles.
variant"primary" | "secondary""primary"Visual variant of the input. primary is the default style with shadow. secondary is a lower emphasis variant without shadow, suitable for use in surfaces.

The TimeField.Input component accepts a render prop function that receives date segments. Each segment represents a part of the time (hour, minute, second, etc.).

TimeField.Segment

TimeField.Segment accepts all props from React Aria's DateSegment component:

PropTypeDefaultDescription
segmentDateSegment-The date segment object from the TimeField.Input render prop.
classNamestring-Tailwind classes merged with the component styles.

TimeField.Prefix

TimeField.Prefix accepts standard HTML div attributes:

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component styles.
childrenReactNode-Content to display in the prefix slot.

TimeField.Suffix

TimeField.Suffix accepts standard HTML div attributes:

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component styles.
childrenReactNode-Content to display in the suffix slot.

TimeField.Group Styling

Customizing the component classes

The base classes power every instance. Override them once with @layer components.

css
@layer components {
  .date-input-group {
    @apply inline-flex h-9 items-center overflow-hidden rounded-field border bg-field text-sm text-field-foreground shadow-field outline-none;

    &:hover,
    &[data-hovered="true"] {
      @apply bg-field-hover;
    }

    &[data-focus-within="true"],
    &:focus-within {
      @apply status-focused-field;
    }

    &[data-invalid="true"] {
      @apply status-invalid-field;
    }

    &[data-disabled="true"],
    &[aria-disabled="true"] {
      @apply status-disabled;
    }
  }

  .date-input-group__input {
    @apply flex flex-1 items-center gap-px rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
  }

  .date-input-group__segment {
    @apply inline-block rounded-md px-0.5 text-end tabular-nums outline-none;

    &:focus,
    &[data-focused="true"] {
      @apply bg-accent-soft text-accent-soft-foreground;
    }
  }

  .date-input-group__prefix,
  .date-input-group__suffix {
    @apply pointer-events-none shrink-0 text-field-placeholder flex items-center;
  }
}

TimeField.Group CSS Classes

  • .date-input-group – Root container styling
  • .date-input-group__input – Input wrapper styling
  • .date-input-group__segment – Individual time segment styling
  • .date-input-group__prefix – Prefix element styling
  • .date-input-group__suffix – Suffix element styling

TimeField.Group Interactive States

  • Hover: :hover or [data-hovered="true"]
  • Focus Within: [data-focus-within="true"] or :focus-within
  • Invalid: [data-invalid="true"] (also syncs with aria-invalid)
  • Disabled: [data-disabled="true"] or [aria-disabled="true"]
  • Segment Focus: :focus or [data-focused="true"] on segment elements
  • Segment Placeholder: [data-placeholder="true"] on segment elements
<RelatedComponents component="timefield" />