Skip to main content

Date Picker

Every date and time experience — single date, time, date+time combo, range — starts with a single DatePicker.Provider. The provider owns the value, draft, and open state. Fields, triggers, calendars, popovers, and modals all read from it as siblings; you compose only the pieces you need.

Draft mode controls whether selections are staged until the user presses OK or commit immediately. Surfaces pick a sensible default: DatePicker.Popover defaults to auto-save (draft={false}) and DatePicker.Modal defaults to staged (draft={true}). Both auto-render a Cancel / OK footer (via DatePicker.Actions) when draft is on, and hide it when it's off. Pass draft on the provider to force either behavior globally, or on the surface to override just that surface.


Full date picker (field + trigger + popover)

The common pattern: typed input, icon trigger, docked calendar in a popover with Cancel / OK.

Preview (Web)
import { useState } from 'react';
import { DateField } from 'react-native-molecules/components/DateField';
import { DatePicker } from 'react-native-molecules/components/DatePicker';
import { IconButton } from 'react-native-molecules/components/IconButton';
import { TextInput } from 'react-native-molecules/components/TextInput';

export default function Example() {
  const [date, setDate] = useState<Date | null>(new Date());

  return (
      <DatePicker.Provider value={date} onChange={setDate}>
          <DateField>
              <TextInput.Right>
                  <DatePicker.Trigger>
                      <IconButton name="calendar" />
                  </DatePicker.Trigger>
              </TextInput.Right>
          </DateField>
          <DatePicker.Popover>
              <DatePicker.Calendar headerLayout="docked" />
          </DatePicker.Popover>
      </DatePicker.Provider>
  );
}

Full date picker (field + trigger + modal)

Same composition, swap DatePicker.Popover for DatePicker.Modal when you want a focused overlay instead of a docked surface. The modal renders its own Cancel / OK actions.

Preview (Web)
import { useState } from 'react';
import { DateField } from 'react-native-molecules/components/DateField';
import { DatePicker } from 'react-native-molecules/components/DatePicker';
import { IconButton } from 'react-native-molecules/components/IconButton';
import { TextInput } from 'react-native-molecules/components/TextInput';

export default function Example() {
  const [date, setDate] = useState<Date | null>(new Date());

  return (
      <DatePicker.Provider value={date} onChange={setDate}>
          <DateField>
              <TextInput.Right>
                  <DatePicker.Trigger>
                      <IconButton name="calendar" />
                  </DatePicker.Trigger>
              </TextInput.Right>
          </DateField>
          <DatePicker.Modal>
              <DatePicker.Calendar />
          </DatePicker.Modal>
      </DatePicker.Provider>
  );
}

Button trigger with date label

No field — use any button as the trigger and show the selected date inline.

Preview (Web)
import { useState } from 'react';
import { Button } from 'react-native-molecules/components/Button';
import { DatePicker } from 'react-native-molecules/components/DatePicker';

const formatLabel = (d: Date | null) =>
  d ? d.toLocaleDateString(undefined, { dateStyle: 'medium' }) : 'Pick a date';

export default function Example() {
  const [date, setDate] = useState<Date | null>(null);

  return (
      <DatePicker.Provider value={date} onChange={setDate}>
          <DatePicker.Trigger>
              <Button variant="outlined">
                  <Button.Text>{formatLabel(date)}</Button.Text>
              </Button>
          </DatePicker.Trigger>
          <DatePicker.Popover>
              <DatePicker.Calendar headerLayout="docked" />
          </DatePicker.Popover>
      </DatePicker.Provider>
  );
}

Just the field (no overlay)

Typed-only — parse and validate what the user types, with no calendar surface.

Preview (Web)
import { useState } from 'react';
import { DateField } from 'react-native-molecules/components/DateField';
import { DatePicker } from 'react-native-molecules/components/DatePicker';

export default function Example() {
  const [date, setDate] = useState<Date | null>(null);

  return (
      <DatePicker.Provider value={date} onChange={setDate} draft={false}>
          <DateField />
      </DatePicker.Provider>
  );
}

Just the calendar (standalone)

DatePicker.Calendar works without a provider — give it date and onChange directly.

Preview (Web)
import { useState } from 'react';
import { DatePicker } from 'react-native-molecules/components/DatePicker';

export default function Example() {
  const [date, setDate] = useState<Date | null>(new Date());

  return (
      <DatePicker.Calendar
          mode="single"
          date={date}
          onChange={({ date }) => setDate(date ?? null)}
      />
  );
}

Auto-close popover on selection

The popover defaults to draft={false}, so each calendar tap commits through the provider's onChange. Control open on the provider and close it from onChange to dismiss the popover the moment a date is picked.

Preview (Web)
import { useState } from 'react';
import { DateField } from 'react-native-molecules/components/DateField';
import { DatePicker } from 'react-native-molecules/components/DatePicker';
import { IconButton } from 'react-native-molecules/components/IconButton';
import { TextInput } from 'react-native-molecules/components/TextInput';

export default function Example() {
  const [date, setDate] = useState<Date | null>(new Date());
  const [open, setOpen] = useState(false);

  return (
      <DatePicker.Provider
          value={date}
          onChange={next => {
              setDate(next);
              setOpen(false);
          }}
          open={open}
          onOpenChange={setOpen}>
          <DateField>
              <TextInput.Right>
                  <DatePicker.Trigger>
                      <IconButton name="calendar" />
                  </DatePicker.Trigger>
              </TextInput.Right>
          </DateField>
          <DatePicker.Popover>
              <DatePicker.Calendar headerLayout="docked" />
          </DatePicker.Popover>
      </DatePicker.Provider>
  );
}

Date + time combos

Side-by-side date field + time field

One provider in mode="datetime" holds a single Date; each field edits its slice.

Preview (Web)
import { useState } from 'react';
import { View } from 'react-native';
import { DateField } from 'react-native-molecules/components/DateField';
import { DatePicker } from 'react-native-molecules/components/DatePicker';
import { TimeField } from 'react-native-molecules/components/TimeField';

export default function Example() {
  const [value, setValue] = useState<Date | null>(new Date());

  return (
      <DatePicker.Provider mode="datetime" value={value} onChange={setValue} draft={false}>
          <View style={{ flexDirection: 'row', gap: 12 }}>
              <DateField style={{ flex: 1 }} />
              <TimeField style={{ flex: 1 }} />
          </View>
      </DatePicker.Provider>
  );
}

Date + time in a single popover

Calendar and clock side by side, shared draft, one OK to commit both.

Preview (Web)
import { useState } from 'react';
import { View } from 'react-native';
import { DatePicker } from 'react-native-molecules/components/DatePicker';
import { Icon } from 'react-native-molecules/components/Icon';
import { Text } from 'react-native-molecules/components/Text';
import { TimePicker } from 'react-native-molecules/components/TimePicker';
import { TouchableRipple } from 'react-native-molecules/components/TouchableRipple';

const formatLabel = (d: Date | null) =>
  d
      ? d.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' })
      : 'Pick date & time';

export default function Example() {
  const [value, setValue] = useState<Date | null>(new Date());

  return (
      <DatePicker.Provider mode="datetime" value={value} onChange={setValue}>
          <DatePicker.Trigger>
              <TouchableRipple
                  style={{
                      flexDirection: 'row',
                      alignItems: 'center',
                      gap: 8,
                      paddingHorizontal: 16,
                      paddingVertical: 10,
                      borderRadius: 8,
                      borderWidth: 1,
                      borderColor: '#CAC4D0',
                      alignSelf: 'flex-start',
                  }}
                  accessibilityRole="button">
                  <Text>{formatLabel(value)}</Text>
                  <Icon name="chevron-down" size={18} />
              </TouchableRipple>
          </DatePicker.Trigger>
          <DatePicker.Popover align="center">
              <View style={{ flexDirection: 'row', gap: 16, padding: 12 }}>
                  <DatePicker.Calendar headerLayout="docked" />
                  <TimePicker.Clock inputType="picker" />
              </View>
          </DatePicker.Popover>
      </DatePicker.Provider>
  );
}

Component reference

DatePickerProvider

Inputs & Controls

DatePickerProvider

Shared state container for every date / time component in its subtree.

Usage

Wrap fields, triggers, calendars, and overlays to share one value and open state.

Highlights

  • Single source of truth for value, draft, and open state
  • Modes: date, time, datetime, range
  • Draft mode on by default — pair with DatePickerActions to commit

When to use it

  • You render any combination of field, trigger, calendar, popover, or modal.
  • You want one value shared across date and time inputs.

DatePickerTrigger

Inputs & Controls

DatePickerTrigger

Headless trigger that toggles the overlay and registers the anchor ref.

Usage

Render as a default icon button, wrap any pressable, or pass asChild to slot a custom button.

Highlights

  • Renders a default icon button when no children are provided
  • Pass asChild to merge press handling onto a custom button
  • Registers itself as the popover anchor

When to use it

  • You want a button outside of a field to open the overlay.
  • A field uses TextInput.Right to slot the trigger as an adornment.

DatePickerActions

Inputs & Controls

DatePickerActions

Cancel / OK footer that commits the provider draft or reverts.

Usage

Mount inside a popover or modal when draft mode is on (the default).

Highlights

  • Only renders when draft mode is on
  • Calls provider commit / cancel so overlays close with the result

When to use it

  • Selections should stage a draft until the user confirms.
  • You want consistent Cancel / OK buttons across popover and modal surfaces.

DateField

Inputs & Controls

DateField

Pure text input that reads / writes the provider date value with masking.

Usage

Mount inside a DatePickerProvider for typed date entry; optional alongside a trigger.

Highlights

  • Parses and formats automatically using the provider date format
  • Supports range mode via inputMode="start" | "end"
  • No built-in trigger or overlay — compose those as siblings

When to use it

  • The user should be able to type a date directly.
  • You want typed entry paired with an optional calendar surface.

Inherits: TextInputProps

DateCalendar

Inputs & Controls

DateCalendar

Calendar surface that works standalone or reads from the surrounding DatePickerProvider.

Usage

Mount inside a provider to share state, or pass date / onChange directly for standalone use.

Highlights

  • Standalone or provider-driven
  • Day, month, year views with keyboard navigation
  • Range and multi-date selection supported

When to use it

  • You want a shared calendar surface across modal, popover, and inline layouts.
  • Range or multi-date selection belongs outside a field wrapper.

DatePicker.Calendar accepts headerLayout"docked" uses the two-up month/year layout (default inside DatePicker.Popover), "inline" uses the stacked header.

DatePickerPopover

Overlay & Menus

DatePickerPopover

Presentation shell for mounting date picker content in a popover.

Usage

Attach a calendar to a trigger without forcing modal UX.

Highlights

  • Uses Popover positioning, anchored to the trigger registered with the provider
  • Pure visual shell — draft / commit behavior comes from the provider
  • Nested DateCalendar defaults to the docked month/year header layout

When to use it

  • The screen should keep surrounding context visible while selecting a date.
  • Desktop and tablet flows benefit from anchored overlays.

DatePickerModal

Overlay & Menus

DatePickerModal

Modal shell for date picker content; reads from DatePickerProvider or falls back to its own props.

Usage

Wrap a calendar surface when the picker should open in a focused overlay.

Highlights

  • Dual-mode: delegates to DatePickerProvider when present, otherwise owns state
  • Built-in Cancel / OK and typed-entry toggle

When to use it

  • The date selection UI should open in a focused overlay.
  • You want the same trigger to swap between inline and modal presentations.