Components
Date picker
The form-bound date picker — a segmented spinbutton field (type or arrow each part; screen readers announce “month, 06”) in the standard input frame, opening a calendar in a flat, friendly popover. Built on react-aria-components + @internationalized/date, so the library owns the calendar logic, keyboard, a11y, and locale / timezone correctness — we bring the color. Selected dates take a solid gold fill; the focus ring and the “today” marker are gold too. Stores a portable ISO string (2026-06-05).
Live demo
Type into the segments or open the calendar. Submit empty to see the error; pick a date to see the stored ISO value.
How it looks
- field
- The segmented input sits in the standard input frame — a quiet border at rest, gold on focus, red when invalid, green when valid, muted when disabled. The focused segment takes a soft gold tint.
- calendar
- Opens in a flat, opaque popover with a soft warm shadow — no glass here; that treatment belongs to the proposed system. Prev / month-year / next controls up top, a weekday grid below.
- selection
- The selected day takes a solid gold fill with white text (a selection, not a button — same treatment as Checkbox). Today gets a small gold dot; keyboard focus is the gold ring.
- value
- Stored as an ISO date string ("2026-06-05") via @internationalized/date — portable to APIs, locale- and timezone-correct, never hand-rolled date math.
Props
- label: ReactNode
- The field’s label. Required.
- helperText?: ReactNode
- Neutral hint below the field; the error replaces it when invalid.
- showValid?: boolean
- Opt in to the green valid border once touched and valid.
- minValue? / maxValue?: string
- ISO bounds — dates outside the range render disabled in the calendar and fail validation.
- isDisabled?: boolean
- Disable the control (muted and non-interactive).
Usage
import { Form, useHaloForm, DateField, SubmitButton, z } from '@halo-compliance/ui'
const schema = z.object({ effectiveDate: z.string().min(1) })
function Policy() {
const form = useHaloForm({
defaultValues: { effectiveDate: '' },
validators: { onChange: schema },
})
return (
<Form form={form}>
<form.AppField name="effectiveDate">
{() => <DateField label="Effective date" minValue="2026-01-01" />}
</form.AppField>
<form.AppForm><SubmitButton>Save</SubmitButton></form.AppForm>
</Form>
)
}Date range
Start → end in one field, with quick presets beside the calendar — for report periods and audit windows. The middle of the range gets a soft gold tint, the endpoints a solid gold fill. Stores { start, end } ISO strings.
Date + time
Date and time segments shown in your local timezone — but the value is stored as a UTC absolute instant. Timezone is a display concern only; once it's in state it's UTC, so the instant is unambiguous wherever it's read (audit logs, APIs, another viewer's zone). @internationalized/date owns the conversion.
Related
- /text-field — the single-line field these share their input styling and helper / error wiring with.
- /form — the form layer it plugs into.
- /checkbox — the other selection control with the same solid-fill treatment.
- /tokens — the focus-ring / radius / shadow tokens behind the look.