Components / Forms
Date Input
Text fields for dates and times that open the Calendar in a dropdown. Users can type the value or pick it. Every variant separates the human-readable displayFormat from the machine-readable valueFormat it emits.
Installation
npx shadcn add https://raw.githubusercontent.com/levi-putna/elements/main/registry/date-input/registry.jsonDisplay format vs value format
Show people a friendly, unambiguous date while storing a machine-friendly one. The field renders displayFormat; onValueChange emits valueFormat. Pick a date below and watch both update.
——{/* The field shows displayFormat; onValueChange emits valueFormat. */}
<DateInput
displayFormat="EEEE, do MMMM yyyy" // "Tuesday, 16th June 2026"
valueFormat="dd/MM/yyyy" // "16/06/2026"
/>Common format tokens
Any date-fns format pattern works. The left column is the token; the right is what it renders for 16 June 2026.
| Prop | Type | Default | Description |
|---|---|---|---|
| d MMM yyyy | 16 Jun 2026 | - | Compact, unambiguous — the default display format. |
| PPP | June 16th, 2026 | - | Localized long date (date-fns shorthand). |
| EEEE, do MMMM yyyy | Tuesday, 16th June 2026 | - | Full weekday and month. |
| dd/MM/yyyy | 16/06/2026 | - | Day-first numeric (most of the world). |
| MM/dd/yyyy | 06/16/2026 | - | Month-first numeric (US). |
| yyyy-MM-dd | 2026-06-16 | - | ISO 8601 — the recommended value format for storage/APIs. |
| h:mm a | 9:00 AM | - | 12-hour time with meridiem. |
| HH:mm | 09:00 | - | 24-hour time. |
| yyyy-MM-dd'T'HH:mm | 2026-06-16T09:00 | - | ISO date-time (literals wrapped in single quotes). |
DateInput
A single date. Type it (parsed against displayFormat on blur or Enter) or open the calendar. Unparseable text flags the field invalid instead of being silently dropped.
2026-06-16import { DateInput } from "@/components/ui/date-input"
export function Example() {
const [value, setValue] = React.useState("")
return (
<DateInput
value={value}
onValueChange={setValue}
displayFormat="d MMM yyyy" // shown in the field → "16 Jun 2026"
valueFormat="yyyy-MM-dd" // emitted to onValueChange → "2026-06-16"
/>
)
}TimeInput
A time of day. The dropdown lists options every stepminutes, and the field still accepts free typing like “2:15 PM”.
09:00import { TimeInput } from "@/components/ui/date-input"
<TimeInput
defaultValue="09:00"
displayFormat="h:mm a" // "9:00 AM"
valueFormat="HH:mm" // "09:00"
step={30} // minutes between suggestions
/>DateTimeInput
Date and time together. The calendar and a time list share one dropdown; picking a day keeps the chosen time.
—import { DateTimeInput } from "@/components/ui/date-input"
<DateTimeInput
displayFormat="d MMM yyyy, h:mm a" // "16 Jun 2026, 9:00 AM"
valueFormat="yyyy-MM-dd'T'HH:mm" // "2026-06-16T09:00"
/>DateRangeInput
A start and end date. The trigger reads start – end and opens a two-month calendar in range mode. onValueChange emits { from, to }.
——import { DateRangeInput, type DateRangeValue } from "@/components/ui/date-input"
export function Example() {
const [range, setRange] = React.useState<DateRangeValue>({})
return (
<DateRangeInput
value={range}
onValueChange={setRange}
displayFormat="d MMM yyyy"
valueFormat="yyyy-MM-dd"
/>
)
// range → { from: "2026-06-16", to: "2026-06-20" }
}Displaying dates
For read-only output — tables, activity feeds, audit logs — use DateBadge and DateTag. Both take the same displayFormat and an optional timeZone.
DateBadge
A compact, non-interactive badge. Optionally pin it to a time zone and show the zone label.
import { DateBadge } from "@/components/ui/date-display"
<DateBadge date="2026-06-16T09:47:29Z" displayFormat="d MMM yyyy" />
{/* Pin to a zone and show its label */}
<DateBadge
date="2026-06-16T09:47:29Z"
displayFormat="MMMM d, yyyy h:mm:ss a"
timeZone="Australia/Sydney"
showZone
/>DateTag
An inline date with a dashed underline. Hover (or focus) it to reveal how long ago it was and the time in both the displayed zone and your local zone — so a reader in another country always knows what the timestamp means for them.
Report generated 16 Jun 2026, 9:47 AM — hover to see it in your local time.
import { DateTag } from "@/components/ui/date-display"
{/* Displayed in UTC; hovering reveals the viewer's local zone + "x ago". */}
<DateTag
date="2026-06-16T09:47:29Z"
displayFormat="d MMM yyyy, h:mm a"
detailFormat="d MMM yyyy, h:mm:ss a"
timeZone="UTC"
/>Props
Shared (DateInput, TimeInput, DateTimeInput)
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | Controlled value, a string in valueFormat. |
| defaultValue | string | - | Uncontrolled initial value, a string in valueFormat. |
| onValueChange | (value: string) => void | - | Fires with the value formatted by valueFormat ("" when cleared). |
| onDateChange | (date: Date | undefined) => void | - | Escape hatch — fires with the raw Date. |
| displayFormat | string | - | date-fns pattern shown in the field. |
| valueFormat | string | - | date-fns pattern emitted by onValueChange and the hidden form input. |
| name | string | - | Renders a hidden input with the valueFormat string for native form submission. |
| disabled | boolean | - | Disables the field and trigger. |
TimeInput
| Prop | Type | Default | Description |
|---|---|---|---|
| step | number | 30 | Minutes between suggested options in the dropdown list. |
DateTimeInput
| Prop | Type | Default | Description |
|---|---|---|---|
| step | number | 30 | Minutes between suggested time options. |
| timeFormat | string | "h:mm a" | date-fns pattern for the time-list labels. |
| calendarProps | Partial<CalendarProps> | - | Forwarded to the underlying Calendar (e.g. disabled dates, captionLayout). |
DateRangeInput
| Prop | Type | Default | Description |
|---|---|---|---|
| value | { from?: string; to?: string } | - | Controlled range, strings in valueFormat. |
| onValueChange | (value: { from?, to? }) => void | - | Fires with the formatted range. |
| onRangeChange | (range: DateRange) => void | - | Escape hatch — fires with the raw DateRange. |
| numberOfMonths | number | 2 | Months rendered side by side. |
DateBadge
| Prop | Type | Default | Description |
|---|---|---|---|
| date | Date | string | number | - | The value to display (Date, ISO string, or epoch ms). |
| displayFormat | string | "d MMM yyyy" | date-fns pattern used to render the date. |
| timeZone | string | - | IANA zone to render in (e.g. "Australia/Sydney"). Defaults to local. |
| showZone | boolean | false | Show a leading zone-label chip (e.g. "GMT+10"). |
| variant | BadgeVariant | "outline" | Forwarded to the underlying Badge. |
DateTag
| Prop | Type | Default | Description |
|---|---|---|---|
| date | Date | string | number | - | The value to display. |
| displayFormat | string | "d MMM yyyy" | Pattern for the inline trigger text. |
| detailFormat | string | "d MMM yyyy, h:mm:ss a" | Pattern for the rows inside the hover card. |
| timeZone | string | - | Zone the value is shown in; the hover compares it to the viewer's local zone. |
| timeZoneLabel | string | - | Override the displayed zone's label. |
| relative | boolean | true | Show the "x ago" header. |