RoadieRoadie
  • Home
  • Brand
  • Foundations
  • Content
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeBrandFoundations
Appearance

Components

  • Navigation

    • Breadcrumb
    • LinkBeta
    • NavigatorAlpha
    • Steps
    • Tabs
  • Layout

    • Accordion
    • CollapsibleBeta
    • PaneAlpha
    • ScrollArea
    • Separator
  • Actions

    • Button
    • IconButton
    • ToggleBeta
    • Toggle groupBeta
    • ToolbarBeta
  • Fields

    • EditorAlpha
    • Field
    • Fieldset
    • Input
    • Label
    • Number fieldBeta
    • OTP fieldBeta
    • Query fieldAlpha
    • Textarea
  • Choices

    • Autocomplete
    • CheckboxBeta
    • Combobox
    • Radio group
    • Select
    • SliderBeta
    • SwitchBeta
  • Date and time

    • CalendarBeta
    • CalendarTile
    • Countdown
    • Dashboard periodBeta
    • Date fieldBeta
    • Date pickerBeta
    • Date range pickerBeta
    • DateTime
    • Duration
    • Time fieldBeta
  • Collections

    • Card
    • Carousel
    • DataTableBeta
    • ListAlpha
    • Marquee
    • RecordGridAlpha
    • RecordTableAlpha
    • SortableAlpha
    • TableBeta
  • Overlays

    • Dialog
    • Drawer
    • MenuBeta
    • Popover
    • ToastBeta
    • Tooltip
  • Status

    • Badge
    • CalloutBeta
    • DeltaBeta
    • Empty state
    • MeterBeta
    • ProgressBeta
    • SkeletonBeta
    • SparklineBeta
    • StatTileBeta
  • Media & brand

    • AvatarBeta
    • Icon Tile
    • Image
    • Logo
    • PatternBeta
    • QR codeBeta
    • SpotIllustration
  • Text

    • Code
    • Highlight
    • KbdBeta
    • Mark
    • Prose

Date picker

Status
Beta
Added
Components 2.16.020 Oct 2026
Docs updated
10 Oct 2026

A typed date field with a calendar to choose from, and a time when needed.

Import

import { DatePicker } from '@oztix/roadie-components/date-picker'

Examples

Default

Type a date, as in DateField, or press the calendar button and choose a day. Focus the empty field for hints at what can be typed, such as Tomorrow or In 2 weeks, and as you type, the first suggestion is highlighted so Enter takes it. The calendar opens on the chosen day, or on today, with focus on it. Choosing a day closes it and puts focus back on the button. The value is a plain ISO date such as '2026-11-27', or null.

function Default() {
const [date, setDate] = useState(null)
return (
<>
<DatePicker aria-label='Show date' value={date} onValueChange={setDate} />
<p className='text-sm text-subtle'>Value: {date ?? 'none'}</p>

Variants

granularity='minute' adds a TimeField beside the date. The value is then the instant the date and time name in timeZone, with its offset, such as '2026-11-27T19:30:00+11:00', and it stays null until both are filled in. Pass the venue's zone, so a Perth organiser setting doors for a Melbourne show sets them on Melbourne's clock. A time that daylight saving skips, such as 2:30am on the morning the clocks go forward, moves to where it lands, 3:30am, and the field shows it.

function Doors() {
const [doors, setDoors] = useState('2026-11-27T19:30:00+11:00')
return (
<>
<Field>
<Field.Label>Doors, Melbourne time</Field.Label>

Emphasis

<DatePicker aria-label='Normal' defaultValue='2026-11-27' />
<DatePicker aria-label='Subtle' emphasis='subtle' defaultValue='2026-11-27' />

Sizes

The calendar button shrinks with the field, so it always sits inside it.

<DatePicker aria-label='Small' size='sm' defaultValue='2026-11-27' />
<DatePicker aria-label='Medium' size='md' defaultValue='2026-11-27' />
<DatePicker aria-label='Large' size='lg' defaultValue='2026-11-27' />

States

readOnly shows the date and turns off the calendar button. disabled turns off both.

{/* Default */}
<DatePicker aria-label='Default' defaultValue='2026-11-27' />
{/* Invalid */}
<DatePicker aria-label='Invalid' defaultValue='2026-11-27' invalid />
{/* Read only */}
<DatePicker aria-label='Read only' defaultValue='2026-11-27' readOnly />

Composition

With Field

Wrap it in Field. The label points at the date input, and Field.ErrorText says why typed text isn't a date or a time. At minute granularity the date and time sit in a group named by the label.

<Field required className='max-w-64'>
<Field.Label showIndicator>Show date</Field.Label>
<DatePicker placeholder='14 Mar or next Fri' />
<Field.HelperText>Type a date or choose one</Field.HelperText>
<Field.ErrorText />
</Field>

With disabled days

disabled takes the same matchers as Calendar. Matched days are disabled in the calendar and refused when typed. Here Raffia Spaceship runs on Fridays and Saturdays in November.

<Field className='max-w-64'>
<Field.Label>Raffia Spaceship night</Field.Label>
<DatePicker
disabled={[
{ before: '2026-11-01' },
{ after: '2026-11-30' },

With a date of birth

captionLayout='dropdown' swaps the month name for month and year selects, for dates far from today. Most people will type a date of birth, but the selects help those who don't.

<Field className='max-w-64'>
<Field.Label>Date of birth</Field.Label>
<DatePicker
captionLayout='dropdown'
startMonth='1920-01-01'
endMonth='2012-12-31'

Guidelines

Use DateRangePicker for a range

Do

Choose a start and an end with DateRangePicker, which keeps them in order and offers presets.

Don’t

Don't put two DatePickers side by side for a range. Nothing stops the end coming before the start.

Pass the zone the moment belongs to

<DatePicker
granularity='minute'
timeZone={venue.timeZone}
/>

Do

Event times are read on the venue's clock. Say so in the label, such as "Doors, Melbourne time".

<DatePicker granularity='minute' />

Don’t

Don't lean on the browser's zone for an event time. An organiser in another state sets the wrong moment.

Disable days, rather than hide them

Do

Disable days that can't be chosen. They stay in the grid for keyboard users and are refused when typed.

Don’t

Don't check the date only after the form is sent. Say what's wrong as soon as it's chosen.

Accessibility

  • The date is a combobox, a text input with suggestions, labelled by Field.Label or aria-label. The calendar button is named after the picker and its date, such as "Choose date, Fri 27 Nov 2026, Doors", and the popup "Choose date, Doors", so pickers side by side stay apart.
  • On a screen narrower than 48rem, the calendar opens in a bottom Drawer instead of a popover. Screen readers announce a dialog with the same name. Its title is the picker's label, days grow to fill the width up to 48px, a swipe sideways over the days turns the month, and Close, Escape, a tap outside or a swipe down closes it.
  • At minute granularity the date and the time are a group named by the label, with inputs named "Date" and "Time".
  • Opening the calendar moves focus to the chosen day, or to today. Arrow keys, Page Up, Page Down, Home and End move as in Calendar. Enter or Space chooses the focused day and closes it. Escape closes it without a change. Either way focus goes back to the button, so on a phone the keyboard doesn't open.
  • Focusing the empty date opens hints with nothing highlighted, so Enter still submits the form. Once you type, the first suggestion is highlighted and Enter takes it. The arrow keys move through the list, and Escape closes it and keeps the text. On a phone the list opens under the field, above the page.
  • With no suggestion highlighted, Enter commits typed text instead of submitting the form, and Escape puts back the last date.
  • With a name, a hidden input submits the value, so a form never receives the formatted text. A disabled picker submits nothing.

API reference

DatePicker

A typed date field with a calendar to choose from, and a time when needed.

valuestring | null

An ISO date such as `'2026-11-27'` at `day` granularity. At `minute`, an ISO date-time; one with an offset is shown on the wall clock of `timeZone`. Pair with `onValueChange`.

defaultValuestring | null

The value to start from when uncontrolled.

onValueChange((value: string | null) => void)

Called with an ISO date at `day` granularity. At `minute`, with the instant the date and time name in `timeZone`, with its offset, such as `'2026-11-27T19:30:00+11:00'`, or null until both are known.

granularity"day" | "minute"

`minute` adds a time field beside the date.

Defaults to day.

timeZonestring

IANA zone whose wall clock the date and time are read on, and whose calendar decides today. Pass the venue's zone for an event time. Defaults to the viewer's.

disabledboolean | CalendarMatchers

`true` turns the picker off. Matchers, as on `Calendar`, disable those days in the calendar and refuse them when typed. Inherits `true` from `Field`.

invalidboolean

Marks the picker as invalid. Inherits from `Field` when omitted.

requiredboolean

Inherits from `Field` when omitted.

readOnlyboolean

Shows the value without letting it change.

namestring

Submits the value with a form under this name.

formstring

The id of a form outside the picker to submit the value with.

size"sm" | "md" | "lg"

Defaults to md.

emphasis"normal" | "subtle"

Defaults to 'normal'.

placeholderstring

Hint in the empty date input, such as "14 Mar or next Fri".

inputRefRef<HTMLInputElement>

A ref to the date input, for focusing it.

dateStyle"full" | "long" | "medium"

How the date reads when not being edited, from the datetime formatters.

Defaults to 'long'.

hourCycle12 | 24

At `minute` granularity, `12` reads "7:30pm" and `24` reads "19:30".

Defaults to 12.

minuteStepnumber

At `minute` granularity, minutes per step of the time field's arrow keys. A typed time off the step shows an error.

Defaults to 1.

todaystring

Today as an ISO date. Defaults to today in `timeZone`.

weekStartnumber

First day of the week in the calendar: 1 is Monday and 7 is Sunday.

Defaults to 1.

localestring

Defaults to 'en-AU'.

captionLayout"label" | "dropdown"

`dropdown` swaps the calendar's month name for month and year selects.

Defaults to 'label'.

startMonthstring

The earliest month the calendar reaches, as any ISO date in it.

endMonthstring

The latest month the calendar reaches, as any ISO date in it.

openboolean

Whether the calendar is open. Pair with `onOpenChange`.

defaultOpenboolean

Whether the calendar starts open when uncontrolled.

Defaults to false.

onOpenChange((open: boolean) => void)

Called when the calendar opens or closes.

Previous page← Date fieldNext pageDate range picker →