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.
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>
);
}
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>
);
}
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>
);
}
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>
);
}
| 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. |
DateTimePickerProps| Name | Type | Default | Description |
|---|---|---|---|
valuerequired | Date | null | — | The instant; null means none.Shown in: Configurator, Set an instant, With seconds and 3 more |
withSeconds | boolean | false | Show the seconds field. Shown in: Configurator, With seconds |
placeholder | string | — | What stands in the empty field. Shown in: States |
disabled | boolean | false | Locks 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 |
chars | number | — | 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 |
invalid | boolean | — | 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 |
clearable | boolean | false | Shows a cross where a value is set, which fades in on hover/focus and
clears the value. Shown in: Configurator, Set an instant, States |
ref | Ref<HTMLSpanElement> | — | Receives the component's root element. from RefPropShown in: A row that holds still (Sizes), An anchored surface (Popover), Take the width of the trigger (Popover) and 2 more |
| Name | Type | Default | Description |
|---|---|---|---|
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.
What umriss deliberately does not build, and why: ADR-0032.