DateTimePicker

One moment, day and time of day in one field (date-time field): when an incident began, when an alert fired.

import { DateTimePicker } from "@umriss-ui/core";

It reports only on Apply, Now or Clear, never with a day that has no time yet. The value contract of the pickers stands on DatePicker.

Around a clock change the panel names a skipped hour and asks which of a doubled hour is meant, for example 02:30 on 25 October 2026.

Examples

Set an instant

Choose the day, type the time, then Apply; onChange runs only then, never with a day that has no time.

import { useState } from "react";
import { DateTimePicker, FormField, Stack, Text, useFormats } from "@umriss-ui/core";

export default function SetAnInstant() {
  const formats = useFormats();
  const [started, setStarted] = useState<Date | null>(null);

  return (
    <Stack gap={3} style={{ maxWidth: 320 }}>
      <FormField label="Customer impact began">
        <DateTimePicker value={started} onChange={setStarted} clearable />
      </FormField>
      <Text size="xs" tone="muted" mono>
        value: {started === null ? "null" : `${formats.dateTime(started, false)} ${formats.offset(started)}`}
      </Text>
    </Stack>
  );
}

With seconds

Set withSeconds where the second is part of the value, such as the moment an alert fired.

import { useState } from "react";
import { DateTimePicker, FormField } from "@umriss-ui/core";

export default function WithSeconds() {
  const [fired, setFired] = useState<Date | null>(new Date(2026, 2, 17, 9, 41, 27));

  return (
    <FormField label="Alert fired" style={{ maxWidth: 320 }}>
      <DateTimePicker value={fired} onChange={setFired} withSeconds />
    </FormField>
  );
}

States

size="sm" suits dense forms; errors come from the FormField, and disabled locks field and panel.

import { useState } from "react";
import { DateTimePicker, FormField, Grid } from "@umriss-ui/core";

export default function States() {
  const [acknowledged, setAcknowledged] = useState<Date | null>(new Date(2026, 2, 17, 9, 46));
  const [resolved, setResolved] = useState<Date | null>(new Date(2026, 2, 17, 9, 30));

  return (
    <Grid minItemWidth="240px" gap={4}>
      <FormField label="Acknowledged" hint="Small size.">
        <DateTimePicker size="sm" value={acknowledged} onChange={setAcknowledged} clearable />
      </FormField>
      <FormField label="Resolved" error="Resolved lies before the incident was opened at 09:42.">
        <DateTimePicker value={resolved} onChange={setResolved} clearable />
      </FormField>
      <FormField label="Closed" hint="Empty, with its own placeholder.">
        <DateTimePicker value={null} onChange={() => {}} placeholder="Still open" />
      </FormField>
      <FormField label="Opened" hint="Set by the alert.">
        <DateTimePicker value={new Date(2026, 2, 17, 9, 42)} onChange={() => {}} disabled />
      </FormField>
    </Grid>
  );
}

With an error

A FormField with an error marks the field invalid by itself. Without one, set invalid and tie your message to the field with aria-describedby.

import { useId, useState } from "react";
import { DateTimePicker, Stack, Text } from "@umriss-ui/core";

/* INC-1048 was opened by the alert at 09:42. */
const OPENED = new Date(2026, 2, 17, 9, 42);

export default function WithAnError() {
  const [resolved, setResolved] = useState<Date | null>(new Date(2026, 2, 17, 9, 30));
  const messageId = useId();
  const error = resolved !== null && resolved < OPENED ? "Resolved lies before the incident was opened at 09:42." : undefined;

  return (
    <Stack gap={1} style={{ maxWidth: 320 }}>
      <DateTimePicker
        aria-label="Resolved"
        value={resolved}
        onChange={setResolved}
        invalid={error !== undefined}
        aria-describedby={error ? messageId : undefined}
      />
      {error && (
        <Text id={messageId} size="xs" style={{ color: "var(--u-color-danger-text)" }}>
          {error}
        </Text>
      )}
    </Stack>
  );
}

When to use something else

Keyboard

Key Action
Arrow keys In the calendar, move a day or a week.
Enter or Space On a day, chooses it and moves on to the hour.
Arrow Up / Arrow Down In a time field, steps the hour, minute or second.
Enter In a time field, applies the value.
Escape Closes the panel without a change.

API

DateTimePickerProps

NameTypeDefaultDescription
valuerequiredDate | null—The instant; null means none.

Shown in: Configurator, Set an instant, With seconds and 3 more

withSecondsbooleanfalseShow the seconds field.

Shown in: Configurator, With seconds

placeholderstring—What stands in the empty field.

Shown in: States

disabledbooleanfalseLocks the field and the panel.

Shown in: Configurator, States

size"sm" | "md"the size of a ControlSizeProvider around it, else "md"sm for a toolbar and dense forms, md otherwise.

Shown in: Configurator, States

charsnumber—The width in characters - room for the value; the field adds its own padding, glyph and cross. Given, the field is that wide wherever it stands, and never wider than its place. Without it the field fills its place, and where the place asks - in a toolbar or a row - it is as wide as its longest value in the formats in use, so a date never truncates.

Shown in: Configurator

invalidboolean—Marks the field as invalid. FormField sets it itself as soon as it carries an error - by hand only necessary without FormField.

Shown in: Configurator, With an error

clearablebooleanfalseShows a cross where a value is set, which fades in on hover/focus and clears the value.

Shown in: Configurator, Set an instant, States

refRef<HTMLSpanElement>—Receives the component's root element. from RefProp

Shown in: A row that holds still (Sizes), An anchored surface (Popover), Take the width of the trigger (Popover) and 2 more

Events

NameTypeDefaultDescription
onChangerequired(date: Date | null) => void—Runs only on completion - "Apply", "Now" or "Clear" - and not already on the click on a day: a day without a time would be a half-set value here, and a half value is no value.

Shown in: Configurator, Set an instant, With seconds and 3 more

Also takes every attribute of <span> – without defaultValue, onChange.

Known limits

What umriss deliberately does not build, and why: ADR-0032.

Every page of @umriss-ui/core

Getting started

Customising

Layout

Typography

Actions

Forms

Choosing

Dates and times

Feedback

Overlays

Navigation

Data display

API index