DatePicker

A set of pickers for selecting dates, date ranges, or date and time. Smooth, intuitive interfaces make choosing and adjusting values quick and precise.

Date Picker

Weekdays only, next 30 days. Greyed-out slots are full.

Task card affordance
vue
<script setup lang="ts">
import { ref } from 'vue'
import { DatePicker, Button } from 'frappe-ui'
import { dayjs } from '../../../utils/dayjs'
import type { Dayjs } from 'dayjs/esm'

// 1. Flight booking — can't fly into the past
const departure = ref('')
const today = dayjs().format('YYYY-MM-DD')
const oneYearOut = dayjs().add(1, 'year').format('YYYY-MM-DD')

// 2. Date of birth — can't be born in the future
const dob = ref('1995-08-14')
const longAgo = dayjs().subtract(120, 'year').format('YYYY-MM-DD')

// 3. Appointment — weekdays only, next 30 days, with quick actions and
//    a few slots already taken.
const appointment = ref('')
const inThirtyDays = dayjs().add(30, 'day').format('YYYY-MM-DD')
const fullyBooked = new Set([
  dayjs().add(2, 'day').format('YYYY-MM-DD'),
  dayjs().add(5, 'day').format('YYYY-MM-DD'),
  dayjs().add(11, 'day').format('YYYY-MM-DD'),
])
function isUnavailable(date: Dayjs) {
  const day = date.day()
  if (day === 0 || day === 6) return true
  return fullyBooked.has(date.format('YYYY-MM-DD'))
}
function nextMonday(from: Dayjs = dayjs()) {
  const diff = (8 - from.day()) % 7 || 7
  return from.add(diff, 'day')
}

// 4. Fun — pick a Stardate for a time-travel destination
const stardate = ref('')
const stardateFloor = dayjs('1800-01-01').format('YYYY-MM-DD')
const stardateCeil = dayjs('2300-12-31').format('YYYY-MM-DD')

// 5. Custom trigger — "Add due date" button on a task card
const dueDate = ref('')

const rowCls =
  'w-full rounded px-2 py-1.5 text-left text-base hover:bg-surface-gray-2'
</script>

<template>
  <div class="grid w-full max-w-sm gap-6 py-10">
    <!-- 1. Flight booking -->
    <DatePicker
      v-model="departure"
      label="Departure"
      placeholder="When are you flying?"
      format="ddd, MMM D"
      :min="today"
      :max="oneYearOut"
    >
      <template #prefix>
        <span class="lucide-plane size-4 text-ink-gray-5" />
      </template>
    </DatePicker>

    <!-- 2. Date of birth -->
    <DatePicker
      v-model="dob"
      label="Date of birth"
      placeholder="MM/DD/YYYY"
      format="MMM D, YYYY"
      :min="longAgo"
      :max="today"
      :clearable="false"
    >
      <template #prefix>
        <span class="lucide-cake size-4 text-ink-gray-5" />
      </template>
    </DatePicker>

    <!-- 3. Appointment booking -->
    <DatePicker
      v-model="appointment"
      label="Book appointment"
      description="Weekdays only, next 30 days. Greyed-out slots are full."
      placeholder="Pick a slot"
      :min="today"
      :max="inThirtyDays"
      :is-date-unavailable="isUnavailable"
    >
      <template #prefix>
        <span class="lucide-stethoscope size-4 text-ink-gray-5" />
      </template>
      <template #actions="{ setDate, close }">
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setDate(dayjs().add(1, 'day'))
              close()
            }
          "
        >
          Tomorrow
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setDate(nextMonday())
              close()
            }
          "
        >
          Next Monday
        </button>
      </template>
    </DatePicker>

    <!-- 4. Fun: Time-travel destination -->
    <DatePicker
      v-model="stardate"
      label="Time-travel destination"
      placeholder="When to?"
      format="[Stardate] YYYY.MM.DD"
      variant="outline"
      :min="stardateFloor"
      :max="stardateCeil"
    >
      <template #prefix>
        <span class="lucide-rocket size-4 text-ink-gray-5" />
      </template>
    </DatePicker>

    <!-- 5. Custom trigger — feels like a task-card affordance -->
    <div class="flex flex-col gap-1.5">
      <span class="text-sm text-ink-gray-7">Task card affordance</span>
      <DatePicker v-model="dueDate" format="MMM D">
        <template #trigger="{ togglePopover, displayLabel }">
          <Button
            :variant="dueDate ? 'subtle' : 'ghost'"
            @click="togglePopover"
          >
            <template #prefix>
              <span class="lucide-calendar-plus size-4" />
            </template>
            {{ dueDate ? `Due ${displayLabel}` : 'Add due date' }}
          </Button>
        </template>
      </DatePicker>
    </div>
  </div>
</template>

DateTime Picker

Must be scheduled at least 24 hours in advance.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { DateTimePicker } from 'frappe-ui'
import { dayjs } from '../../../utils/dayjs'

// 1. Meeting — can't schedule in the past, default to the next 30-min slot
const now = dayjs()
const nextSlot = now
  .minute(now.minute() < 30 ? 30 : 60)
  .second(0)
  .format('YYYY-MM-DD HH:mm:ss')
const meeting = ref(nextSlot)
const minMeetingTime = now.format('YYYY-MM-DD HH:mm:ss')

// 2. Server maintenance window — must be at least 24h out, max 60 days
const maintenance = ref('')
const tomorrow = dayjs()
  .add(1, 'day')
  .startOf('day')
  .format('YYYY-MM-DD HH:mm:ss')
const sixtyDaysOut = dayjs()
  .add(60, 'day')
  .endOf('day')
  .format('YYYY-MM-DD HH:mm:ss')

// 3. Fun — schedule the great launch (with a "Pick a dramatic moment" preset)
const launch = ref('')

function nextFridayMidnight() {
  const today = dayjs()
  const diff = (5 - today.day() + 7) % 7 || 7
  return today.add(diff, 'day').hour(0).minute(0).second(0)
}

const rowCls =
  'w-full rounded px-2 py-1.5 text-left text-base hover:bg-surface-gray-2'
</script>

<template>
  <div class="grid w-full max-w-sm gap-6 py-10">
    <!-- 1. Meeting scheduler -->
    <DateTimePicker
      v-model="meeting"
      label="Meeting time"
      placeholder="When should we meet?"
      :min="minMeetingTime"
      format="ddd, MMM D · h:mm A"
    >
      <template #prefix>
        <span class="lucide-calendar-clock size-4 text-ink-gray-5" />
      </template>
    </DateTimePicker>

    <!-- 2. Maintenance window -->
    <DateTimePicker
      v-model="maintenance"
      label="Maintenance window"
      description="Must be scheduled at least 24 hours in advance."
      placeholder="Pick a low-traffic time"
      :min="tomorrow"
      :max="sixtyDaysOut"
    >
      <template #prefix>
        <span class="lucide-server size-4 text-ink-gray-5" />
      </template>
    </DateTimePicker>

    <!-- 3. Fun: dramatic launch moment -->
    <DateTimePicker
      v-model="launch"
      label="Launch moment"
      placeholder="When do we light the candle?"
      format="MMMM D, YYYY [at] h:mm A"
      variant="outline"
    >
      <template #prefix>
        <span class="lucide-rocket size-4 text-ink-gray-5" />
      </template>
      <template #actions="{ setDate, close }">
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setDate(dayjs().add(1, 'day').hour(12).minute(0))
              close()
            }
          "
        >
          High noon
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setDate(nextFridayMidnight())
              close()
            }
          "
        >
          Midnight Friday
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setDate(dayjs().add(1, 'day').hour(6).minute(15))
              close()
            }
          "
        >
          Sunrise
        </button>
      </template>
    </DateTimePicker>
  </div>
</template>

Date Range Picker

Defaults to the last 30 days.

Pick start and end. Weekends are skipped.

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { DateRangePicker } from 'frappe-ui'
import { dayjs } from '../../../utils/dayjs'
import type { Dayjs } from 'dayjs/esm'

const today = dayjs().format('YYYY-MM-DD')
const oneYearOut = dayjs().add(1, 'year').format('YYYY-MM-DD')

// 1. PTO request — quick presets feel native to HR tools
const timeOff = ref<string[]>([])

// 2. Hotel booking — dual pane, check-in must be today or later
const stay = ref<string[]>([])

// 3. Analytics filter — preset-driven, displays compact format
const analyticsRange = ref<string[]>([
  dayjs().subtract(29, 'day').format('YYYY-MM-DD'),
  dayjs().format('YYYY-MM-DD'),
])

function longWeekend(): [Dayjs, Dayjs] {
  const fri = upcomingDay(5)
  return [fri, fri.add(2, 'day')]
}

function workWeek(): [Dayjs, Dayjs] {
  const mon = upcomingDay(1)
  return [mon, mon.add(4, 'day')]
}

function upcomingDay(weekday: number) {
  const t = dayjs()
  const diff = (weekday - t.day() + 7) % 7 || 7
  return t.add(diff, 'day')
}

function lastNDays(days: number): [Dayjs, Dayjs] {
  return [dayjs().subtract(days - 1, 'day'), dayjs()]
}

// Canonical sidebar row styling.
const rowCls =
  'w-full rounded px-2 py-1.5 text-left text-base hover:bg-surface-gray-2'

// 4. Project sprint — weekdays only, span limited to ~2 weeks via `max`
const sprint = ref<string[]>([])
const sprintEnd = dayjs().add(60, 'day').format('YYYY-MM-DD')
function isWeekend(date: Dayjs) {
  const d = date.day()
  return d === 0 || d === 6
}

// 5. Flight booking — custom #trigger renders two side-by-side inputs
// that share one popover, so the calendar still visualizes the range.
const flight = ref<string[]>([])
const depart = computed(() =>
  flight.value[0] ? dayjs(flight.value[0]).format('ddd, MMM D') : '',
)
const ret = computed(() =>
  flight.value[1] ? dayjs(flight.value[1]).format('ddd, MMM D') : '',
)
</script>

<template>
  <div class="grid w-full max-w-sm gap-6 py-10">
    <!-- 1. PTO request -->
    <DateRangePicker
      v-model="timeOff"
      label="Time off"
      placeholder="Pick your dates"
      :min="today"
    >
      <template #prefix>
        <span
          class="lucide-palmtree size-4 text-ink-gray-5"
          aria-hidden="true"
        />
      </template>
      <template #actions="{ setRange, close }">
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(longWeekend())
              close()
            }
          "
        >
          Long weekend
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(workWeek())
              close()
            }
          "
        >
          Next week
        </button>
      </template>
    </DateRangePicker>

    <!-- 2. Hotel booking — dual pane shines for >1 month stays -->
    <DateRangePicker
      v-model="stay"
      label="Check-in / Check-out"
      placeholder="Select your stay"
      dual-pane
      :min="today"
      :max="oneYearOut"
    >
      <template #prefix>
        <span class="lucide-hotel size-4 text-ink-gray-5" aria-hidden="true" />
      </template>
    </DateRangePicker>

    <!-- 3. Analytics date range filter -->
    <DateRangePicker
      v-model="analyticsRange"
      label="Report range"
      description="Defaults to the last 30 days."
      format="MMM D"
      :max="today"
    >
      <template #prefix>
        <span
          class="lucide-chart-line size-4 text-ink-gray-5"
          aria-hidden="true"
        />
      </template>
      <template #actions="{ fromDate, toDate, setRange, clear, close }">
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange([dayjs(), dayjs()])
              close()
            }
          "
        >
          Today
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(lastNDays(7))
              close()
            }
          "
        >
          Last 7 days
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(lastNDays(28))
              close()
            }
          "
        >
          Last 4 weeks
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(lastNDays(90))
              close()
            }
          "
        >
          Last 3 months
        </button>
        <button
          type="button"
          :class="rowCls"
          @click="
            () => {
              setRange(lastNDays(365))
              close()
            }
          "
        >
          Last 12 months
        </button>
        <hr class="my-1 border-outline-gray-2" />
        <button
          v-if="fromDate || toDate"
          type="button"
          :class="rowCls"
          @click="
            () => {
              clear()
              close()
            }
          "
        >
          Clear
        </button>
      </template>
    </DateRangePicker>

    <!-- 4. Sprint window — weekdays only -->
    <DateRangePicker
      v-model="sprint"
      label="Sprint window"
      description="Pick start and end. Weekends are skipped."
      :min="today"
      :max="sprintEnd"
      :is-date-unavailable="isWeekend"
    >
      <template #prefix>
        <span
          class="lucide-timer-reset size-4 text-ink-gray-5"
          aria-hidden="true"
        />
      </template>
    </DateRangePicker>

    <!-- 5. Flight booking — split trigger over one shared popover -->
    <DateRangePicker v-model="flight" dual-pane :min="today">
      <template #trigger="{ togglePopover, isOpen }">
        <div
          class="grid grid-cols-2 divide-x divide-outline-gray-2 rounded border bg-surface-white text-sm transition-colors"
          :class="
            isOpen
              ? 'border-outline-gray-4 ring-2 ring-outline-gray-2'
              : 'border-outline-gray-2 hover:border-outline-gray-3'
          "
        >
          <button
            type="button"
            class="flex items-center gap-2 rounded-l px-3 py-2 text-left hover:bg-surface-gray-1"
            @click="togglePopover"
          >
            <span
              class="lucide-plane-takeoff size-4 text-ink-gray-5"
              aria-hidden="true"
            />
            <div class="flex flex-col leading-tight">
              <span class="text-xs text-ink-gray-5">Depart</span>
              <span class="text-ink-gray-9">
                {{ depart || 'Add date' }}
              </span>
            </div>
          </button>
          <button
            type="button"
            class="flex items-center gap-2 rounded-r px-3 py-2 text-left hover:bg-surface-gray-1"
            @click="togglePopover"
          >
            <span
              class="lucide-plane-landing size-4 text-ink-gray-5"
              aria-hidden="true"
            />
            <div class="flex flex-col leading-tight">
              <span class="text-xs text-ink-gray-5">Return</span>
              <span class="text-ink-gray-9">
                {{ ret || 'Add date' }}
              </span>
            </div>
          </button>
        </div>
      </template>
    </DateRangePicker>
  </div>
</template>

API Reference

DatePicker

Show types
typescript
import type { Dayjs } from 'dayjs/esm'
import type { InputSize, InputVariant } from '../../composables/inputTypes'
import type { InputLabelingProps } from '../../composables/useInputLabeling'

export type PopoverSide = 'top' | 'right' | 'bottom' | 'left'
export type PopoverAlign = 'start' | 'center' | 'end'

// Shared props for both single date and range pickers
export interface CommonDatePickerProps extends InputLabelingProps {
  // Positioning — aligned with Combobox/Dropdown vocabulary
  /** Preferred popover side relative to the trigger. */
  side?: PopoverSide

  /** Alignment of the popover along the trigger edge. */
  align?: PopoverAlign

  /** Gap between the trigger and popover content in pixels. */
  offset?: number

  /**
   * Preferred popover placement relative to the trigger.
   * @deprecated Use `side` and `align` instead.
   */
  placement?: DatePickerPlacement

  // Display
  /** Display format used for the input text. */
  format?: string

  /** Size of the trigger input. */
  size?: InputSize

  /** Visual style variant passed through to the input. */
  variant?: InputVariant

  /** Placeholder text shown when no value is selected. */
  placeholder?: string

  // Interaction
  /** Controls popover open state (for controlled usage). */
  open?: boolean

  /** Opens the popover when the input receives focus. Default: false. */
  openOnFocus?: boolean

  /** Opens the popover when the input is clicked. Default: true. */
  openOnClick?: boolean

  /**
   * Whether the trigger input accepts typed input. When `false` the user can
   * still open the popover and pick a date, but cannot type a date manually.
   * Default: `true`.
   */
  typeable?: boolean

  /**
   * Prevents manual typing while keeping the picker interactive.
   * @deprecated Use `typeable: false` instead.
   */
  readonly?: boolean

  /** Disables the trigger input and calendar interactions. */
  disabled?: boolean

  /** Shows clear and quick-action controls when enabled. */
  clearable?: boolean

  /** Keeps the popover open after a date is selected. Default: false. */
  keepOpen?: boolean

  /**
   * Closes the popover after a value is picked.
   * @deprecated Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).
   */
  autoClose?: boolean

  // Constraints
  /**
   * Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  min?: string

  /**
   * Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  max?: string

  /** Return true to prevent a date from being selected. Combined with `min`/`max`. */
  isDateUnavailable?: (date: Dayjs) => boolean

  // Deprecated
  /**
   * Allows users to type custom date text into the input.
   * @deprecated Use `typeable: false` instead.
   */
  allowCustom?: boolean

  /**
   * Additional classes applied to the trigger input.
   * @deprecated Apply `class` directly to the DatePicker component element to control width.
   */
  inputClass?: string | Array<string> | Record<string, boolean>
}

export interface DatePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string
}

export interface DateRangePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial range value as `[from, to]` in `YYYY-MM-DD` format.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string[]

  /** Controlled range value as `[from, to]` in `YYYY-MM-DD` format, or `[]` for no selection. */
  modelValue?: string[]

  /** Render two calendar panels side by side (current month + next month). */
  dualPane?: boolean
}

export type DatePickerEmits = {
  /** Fired when the picker value changes. */
  (event: 'update:modelValue', value: string): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: string): void
}

/** Emitted range value: a `[from, to]` tuple in `YYYY-MM-DD` format, or `[]` when cleared. */
export type DateRangeValue = [string, string] | []

export type DateRangePickerEmits = {
  /** Fired when the range value changes. Emits `[from, to]` or `[]` when cleared. */
  (event: 'update:modelValue', value: DateRangeValue): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized range value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: DateRangeValue): void
}

export interface DateTimePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string

  /**
   * Earliest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `min` instead.
   */
  minDateTime?: string

  /**
   * Latest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `max` instead.
   */
  maxDateTime?: string

  /** Allows typing a custom time into the embedded time picker. */
  allowCustomTime?: boolean
}

export type DateTimePickerEmits = DatePickerEmits

export type DatePickerPlacement =
  | 'top-start'
  | 'top-end'
  | 'bottom-start'
  | 'bottom-end'
  | 'right-start'
  | 'right-end'
  | 'left-start'
  | 'left-end'

// ── Slot prop shapes ─────────────────────────────────────────────────────────

/** Props bound to the trigger / prefix / suffix slots on all three pickers. */
export interface DatePickerTriggerSlotProps {
  togglePopover: () => void
  isOpen: boolean
  displayLabel: string
  inputValue: string
}

/** Props bound to the `actions` slot on `DatePicker`. */
export interface DatePickerActionsSlotProps {
  selected: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateRangePicker`. */
export interface DateRangePickerActionsSlotProps {
  fromDate: string
  toDate: string
  /**
   * Commits one endpoint, mirroring a calendar cell click:
   * first call sets `from`, second call sets `to`.
   */
  setDate: (date: string | Date | Dayjs) => void
  /**
   * Commits both endpoints atomically. Normalizes order so the earlier
   * date becomes `from`. Use for fixed-window presets ("Last 7 days").
   */
  setRange: (
    range: [string | Date | Dayjs, string | Date | Dayjs],
  ) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateTimePicker`. */
export interface DateTimePickerActionsSlotProps {
  selected: string
  time: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

export interface DatePickerSlots {
  /** Custom trigger renderer for the picker. */
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Custom trigger renderer for the picker.
   * @deprecated Use `#trigger` instead. `#target` remains as a back-compat alias through v1.x.
   */
  target?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered before the trigger input value. */
  prefix?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered after the trigger input value. */
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date shortcuts
   * ("Today", "Tomorrow", "Last 7 days") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DatePickerActionsSlotProps) => any
}

export interface DateRangePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for range shortcuts
   * ("Last 7 days", "Last 12 months") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DateRangePickerActionsSlotProps) => any
}

export interface DateTimePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date-time
   * shortcuts ("Now", "Tomorrow 9am") and other preset actions. When
   * omitted, the popover shows the calendar and time picker only.
   */
  actions?: (props: DateTimePickerActionsSlotProps) => any
}

export type DatePickerViewMode = 'date' | 'month' | 'year'

export interface DatePickerDateObj {
  date: Dayjs
  key: string
  inMonth: boolean
  isToday: boolean
  isSelected: boolean
}
value
= ""

Deprecated — Use `modelValue` with `v-model` instead.

modelValue
= ""
string

Controlled value for the picker.

side
PopoverSide

Preferred popover side relative to the trigger.

align
PopoverAlign

Alignment of the popover along the trigger edge.

offset
number

Gap between the trigger and popover content in pixels.

placement

Deprecated — Use `side` and `align` instead.

format
string

Display format used for the input text.

size
InputSize

Size of the trigger input.

variant
= "subtle"
InputVariant

Visual style variant passed through to the input.

placeholder
= "Select date"
string

Placeholder text shown when no value is selected.

open
boolean

Controls popover open state (for controlled usage).

openOnFocus
= false
boolean

Opens the popover when the input receives focus. Default: false.

openOnClick
= true
boolean

Opens the popover when the input is clicked. Default: true.

typeable
= true
boolean

Whether the trigger input accepts typed input. When `false` the user can still open the popover and pick a date, but cannot type a date manually. Default: `true`.

readonly
= false

Deprecated — Use `typeable: false` instead.

disabled
= false
boolean

Disables the trigger input and calendar interactions.

clearable
= true
boolean

Shows clear and quick-action controls when enabled.

keepOpen
boolean

Keeps the popover open after a date is selected. Default: false.

autoClose
= true

Deprecated — Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).

min
string

Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

max
string

Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

isDateUnavailable
((date: Dayjs) => boolean)

Return true to prevent a date from being selected. Combined with `min`/`max`.

allowCustom
= true

Deprecated — Use `typeable: false` instead.

inputClass

Deprecated — Apply `class` directly to the DatePicker component element to control width.

label
string

Label rendered above (or beside, for binary controls) the input.

description
string

Helper text rendered below the input. Hidden when `error` is set.

error
string | FrappeUIError

Error message rendered below the input. When set, the control receives `aria-invalid="true"` and `data-state="invalid"`. May be either a string or an `Error` object whose `messages?: string[]` is rendered as stacked lines (with `Error.message` as the fallback).

required
boolean

Marks the field as required. Renders an asterisk next to the label and forwards `required` / `aria-required` to the underlying control.

id
string

HTML id of the underlying control. Auto-generated via `useId()` if omitted.

trigger
DatePickerTriggerSlotProps

Custom trigger renderer for the picker.

target

Deprecated — Use `#trigger` instead. `#target` remains as a back-compat alias through v1.x.

prefix
DatePickerTriggerSlotProps

Content rendered before the trigger input value.

suffix
DatePickerTriggerSlotProps

Content rendered after the trigger input value.

actions
DatePickerActionsSlotProps

Sidebar rendered to the left of the calendar. Use for date shortcuts ("Today", "Tomorrow", "Last 7 days") and other preset actions. When omitted, the popover shows the calendar only.

update:modelValue
[value: string]

Fired when the model value changes.

change
[value: string]

Fired after the value is committed.

update:open
[value: boolean]

Fired when the open state changes.

DateRangePicker

Show types
typescript
import type { Dayjs } from 'dayjs/esm'
import type { InputSize, InputVariant } from '../../composables/inputTypes'
import type { InputLabelingProps } from '../../composables/useInputLabeling'

export type PopoverSide = 'top' | 'right' | 'bottom' | 'left'
export type PopoverAlign = 'start' | 'center' | 'end'

// Shared props for both single date and range pickers
export interface CommonDatePickerProps extends InputLabelingProps {
  // Positioning — aligned with Combobox/Dropdown vocabulary
  /** Preferred popover side relative to the trigger. */
  side?: PopoverSide

  /** Alignment of the popover along the trigger edge. */
  align?: PopoverAlign

  /** Gap between the trigger and popover content in pixels. */
  offset?: number

  /**
   * Preferred popover placement relative to the trigger.
   * @deprecated Use `side` and `align` instead.
   */
  placement?: DatePickerPlacement

  // Display
  /** Display format used for the input text. */
  format?: string

  /** Size of the trigger input. */
  size?: InputSize

  /** Visual style variant passed through to the input. */
  variant?: InputVariant

  /** Placeholder text shown when no value is selected. */
  placeholder?: string

  // Interaction
  /** Controls popover open state (for controlled usage). */
  open?: boolean

  /** Opens the popover when the input receives focus. Default: false. */
  openOnFocus?: boolean

  /** Opens the popover when the input is clicked. Default: true. */
  openOnClick?: boolean

  /**
   * Whether the trigger input accepts typed input. When `false` the user can
   * still open the popover and pick a date, but cannot type a date manually.
   * Default: `true`.
   */
  typeable?: boolean

  /**
   * Prevents manual typing while keeping the picker interactive.
   * @deprecated Use `typeable: false` instead.
   */
  readonly?: boolean

  /** Disables the trigger input and calendar interactions. */
  disabled?: boolean

  /** Shows clear and quick-action controls when enabled. */
  clearable?: boolean

  /** Keeps the popover open after a date is selected. Default: false. */
  keepOpen?: boolean

  /**
   * Closes the popover after a value is picked.
   * @deprecated Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).
   */
  autoClose?: boolean

  // Constraints
  /**
   * Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  min?: string

  /**
   * Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  max?: string

  /** Return true to prevent a date from being selected. Combined with `min`/`max`. */
  isDateUnavailable?: (date: Dayjs) => boolean

  // Deprecated
  /**
   * Allows users to type custom date text into the input.
   * @deprecated Use `typeable: false` instead.
   */
  allowCustom?: boolean

  /**
   * Additional classes applied to the trigger input.
   * @deprecated Apply `class` directly to the DatePicker component element to control width.
   */
  inputClass?: string | Array<string> | Record<string, boolean>
}

export interface DatePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string
}

export interface DateRangePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial range value as `[from, to]` in `YYYY-MM-DD` format.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string[]

  /** Controlled range value as `[from, to]` in `YYYY-MM-DD` format, or `[]` for no selection. */
  modelValue?: string[]

  /** Render two calendar panels side by side (current month + next month). */
  dualPane?: boolean
}

export type DatePickerEmits = {
  /** Fired when the picker value changes. */
  (event: 'update:modelValue', value: string): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: string): void
}

/** Emitted range value: a `[from, to]` tuple in `YYYY-MM-DD` format, or `[]` when cleared. */
export type DateRangeValue = [string, string] | []

export type DateRangePickerEmits = {
  /** Fired when the range value changes. Emits `[from, to]` or `[]` when cleared. */
  (event: 'update:modelValue', value: DateRangeValue): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized range value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: DateRangeValue): void
}

export interface DateTimePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string

  /**
   * Earliest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `min` instead.
   */
  minDateTime?: string

  /**
   * Latest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `max` instead.
   */
  maxDateTime?: string

  /** Allows typing a custom time into the embedded time picker. */
  allowCustomTime?: boolean
}

export type DateTimePickerEmits = DatePickerEmits

export type DatePickerPlacement =
  | 'top-start'
  | 'top-end'
  | 'bottom-start'
  | 'bottom-end'
  | 'right-start'
  | 'right-end'
  | 'left-start'
  | 'left-end'

// ── Slot prop shapes ─────────────────────────────────────────────────────────

/** Props bound to the trigger / prefix / suffix slots on all three pickers. */
export interface DatePickerTriggerSlotProps {
  togglePopover: () => void
  isOpen: boolean
  displayLabel: string
  inputValue: string
}

/** Props bound to the `actions` slot on `DatePicker`. */
export interface DatePickerActionsSlotProps {
  selected: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateRangePicker`. */
export interface DateRangePickerActionsSlotProps {
  fromDate: string
  toDate: string
  /**
   * Commits one endpoint, mirroring a calendar cell click:
   * first call sets `from`, second call sets `to`.
   */
  setDate: (date: string | Date | Dayjs) => void
  /**
   * Commits both endpoints atomically. Normalizes order so the earlier
   * date becomes `from`. Use for fixed-window presets ("Last 7 days").
   */
  setRange: (
    range: [string | Date | Dayjs, string | Date | Dayjs],
  ) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateTimePicker`. */
export interface DateTimePickerActionsSlotProps {
  selected: string
  time: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

export interface DatePickerSlots {
  /** Custom trigger renderer for the picker. */
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Custom trigger renderer for the picker.
   * @deprecated Use `#trigger` instead. `#target` remains as a back-compat alias through v1.x.
   */
  target?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered before the trigger input value. */
  prefix?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered after the trigger input value. */
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date shortcuts
   * ("Today", "Tomorrow", "Last 7 days") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DatePickerActionsSlotProps) => any
}

export interface DateRangePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for range shortcuts
   * ("Last 7 days", "Last 12 months") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DateRangePickerActionsSlotProps) => any
}

export interface DateTimePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date-time
   * shortcuts ("Now", "Tomorrow 9am") and other preset actions. When
   * omitted, the popover shows the calendar and time picker only.
   */
  actions?: (props: DateTimePickerActionsSlotProps) => any
}

export type DatePickerViewMode = 'date' | 'month' | 'year'

export interface DatePickerDateObj {
  date: Dayjs
  key: string
  inMonth: boolean
  isToday: boolean
  isSelected: boolean
}
value
= []

Deprecated — Use `modelValue` with `v-model` instead.

modelValue
= []
string[]

Controlled range value as `[from, to]` in `YYYY-MM-DD` format, or `[]` for no selection.

dualPane
= false
boolean

Render two calendar panels side by side (current month + next month).

side
PopoverSide

Preferred popover side relative to the trigger.

align
PopoverAlign

Alignment of the popover along the trigger edge.

offset
number

Gap between the trigger and popover content in pixels.

placement

Deprecated — Use `side` and `align` instead.

format
string

Display format used for the input text.

size
InputSize

Size of the trigger input.

variant
= "subtle"
InputVariant

Visual style variant passed through to the input.

placeholder
= "Select range"
string

Placeholder text shown when no value is selected.

open
boolean

Controls popover open state (for controlled usage).

openOnFocus
= false
boolean

Opens the popover when the input receives focus. Default: false.

openOnClick
= true
boolean

Opens the popover when the input is clicked. Default: true.

typeable
= true
boolean

Whether the trigger input accepts typed input. When `false` the user can still open the popover and pick a date, but cannot type a date manually. Default: `true`.

readonly
= false

Deprecated — Use `typeable: false` instead.

disabled
= false
boolean

Disables the trigger input and calendar interactions.

clearable
= true
boolean

Shows clear and quick-action controls when enabled.

keepOpen
boolean

Keeps the popover open after a date is selected. Default: false.

autoClose
= true

Deprecated — Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).

min
string

Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

max
string

Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

isDateUnavailable
((date: Dayjs) => boolean)

Return true to prevent a date from being selected. Combined with `min`/`max`.

allowCustom
= true

Deprecated — Use `typeable: false` instead.

inputClass

Deprecated — Apply `class` directly to the DatePicker component element to control width.

label
string

Label rendered above (or beside, for binary controls) the input.

description
string

Helper text rendered below the input. Hidden when `error` is set.

error
string | FrappeUIError

Error message rendered below the input. When set, the control receives `aria-invalid="true"` and `data-state="invalid"`. May be either a string or an `Error` object whose `messages?: string[]` is rendered as stacked lines (with `Error.message` as the fallback).

required
boolean

Marks the field as required. Renders an asterisk next to the label and forwards `required` / `aria-required` to the underlying control.

id
string

HTML id of the underlying control. Auto-generated via `useId()` if omitted.

trigger
DatePickerTriggerSlotProps
target

Deprecated — Use `#trigger` instead.

prefix
DatePickerTriggerSlotProps
suffix
DatePickerTriggerSlotProps
actions
DateRangePickerActionsSlotProps

Sidebar rendered to the left of the calendar. Use for range shortcuts ("Last 7 days", "Last 12 months") and other preset actions. When omitted, the popover shows the calendar only.

update:modelValue
[value: DateRangeValue]

Fired when the model value changes.

change
[value: DateRangeValue]

Fired after the value is committed.

update:open
[value: boolean]

Fired when the open state changes.

DateTimePicker

Show types
typescript
import type { Dayjs } from 'dayjs/esm'
import type { InputSize, InputVariant } from '../../composables/inputTypes'
import type { InputLabelingProps } from '../../composables/useInputLabeling'

export type PopoverSide = 'top' | 'right' | 'bottom' | 'left'
export type PopoverAlign = 'start' | 'center' | 'end'

// Shared props for both single date and range pickers
export interface CommonDatePickerProps extends InputLabelingProps {
  // Positioning — aligned with Combobox/Dropdown vocabulary
  /** Preferred popover side relative to the trigger. */
  side?: PopoverSide

  /** Alignment of the popover along the trigger edge. */
  align?: PopoverAlign

  /** Gap between the trigger and popover content in pixels. */
  offset?: number

  /**
   * Preferred popover placement relative to the trigger.
   * @deprecated Use `side` and `align` instead.
   */
  placement?: DatePickerPlacement

  // Display
  /** Display format used for the input text. */
  format?: string

  /** Size of the trigger input. */
  size?: InputSize

  /** Visual style variant passed through to the input. */
  variant?: InputVariant

  /** Placeholder text shown when no value is selected. */
  placeholder?: string

  // Interaction
  /** Controls popover open state (for controlled usage). */
  open?: boolean

  /** Opens the popover when the input receives focus. Default: false. */
  openOnFocus?: boolean

  /** Opens the popover when the input is clicked. Default: true. */
  openOnClick?: boolean

  /**
   * Whether the trigger input accepts typed input. When `false` the user can
   * still open the popover and pick a date, but cannot type a date manually.
   * Default: `true`.
   */
  typeable?: boolean

  /**
   * Prevents manual typing while keeping the picker interactive.
   * @deprecated Use `typeable: false` instead.
   */
  readonly?: boolean

  /** Disables the trigger input and calendar interactions. */
  disabled?: boolean

  /** Shows clear and quick-action controls when enabled. */
  clearable?: boolean

  /** Keeps the popover open after a date is selected. Default: false. */
  keepOpen?: boolean

  /**
   * Closes the popover after a value is picked.
   * @deprecated Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).
   */
  autoClose?: boolean

  // Constraints
  /**
   * Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  min?: string

  /**
   * Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`,
   * `YYYY-MM-DD HH:mm:ss` for second-level granularity).
   */
  max?: string

  /** Return true to prevent a date from being selected. Combined with `min`/`max`. */
  isDateUnavailable?: (date: Dayjs) => boolean

  // Deprecated
  /**
   * Allows users to type custom date text into the input.
   * @deprecated Use `typeable: false` instead.
   */
  allowCustom?: boolean

  /**
   * Additional classes applied to the trigger input.
   * @deprecated Apply `class` directly to the DatePicker component element to control width.
   */
  inputClass?: string | Array<string> | Record<string, boolean>
}

export interface DatePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string
}

export interface DateRangePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial range value as `[from, to]` in `YYYY-MM-DD` format.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string[]

  /** Controlled range value as `[from, to]` in `YYYY-MM-DD` format, or `[]` for no selection. */
  modelValue?: string[]

  /** Render two calendar panels side by side (current month + next month). */
  dualPane?: boolean
}

export type DatePickerEmits = {
  /** Fired when the picker value changes. */
  (event: 'update:modelValue', value: string): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: string): void
}

/** Emitted range value: a `[from, to]` tuple in `YYYY-MM-DD` format, or `[]` when cleared. */
export type DateRangeValue = [string, string] | []

export type DateRangePickerEmits = {
  /** Fired when the range value changes. Emits `[from, to]` or `[]` when cleared. */
  (event: 'update:modelValue', value: DateRangeValue): void

  /** Fired when the popover open state changes. */
  (event: 'update:open', value: boolean): void

  /**
   * Fired after the picker commits a normalized range value.
   * @deprecated Functionally identical to `update:modelValue`. Bind via `v-model` instead.
   */
  (event: 'change', value: DateRangeValue): void
}

export interface DateTimePickerProps extends CommonDatePickerProps {
  /**
   * Uncontrolled initial value for the picker.
   * @deprecated Use `modelValue` with `v-model` instead.
   */
  value?: string

  /** Controlled value for the picker. */
  modelValue?: string

  /**
   * Earliest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `min` instead.
   */
  minDateTime?: string

  /**
   * Latest selectable date-time in `YYYY-MM-DD HH:mm:ss` format.
   * @deprecated Use `max` instead.
   */
  maxDateTime?: string

  /** Allows typing a custom time into the embedded time picker. */
  allowCustomTime?: boolean
}

export type DateTimePickerEmits = DatePickerEmits

export type DatePickerPlacement =
  | 'top-start'
  | 'top-end'
  | 'bottom-start'
  | 'bottom-end'
  | 'right-start'
  | 'right-end'
  | 'left-start'
  | 'left-end'

// ── Slot prop shapes ─────────────────────────────────────────────────────────

/** Props bound to the trigger / prefix / suffix slots on all three pickers. */
export interface DatePickerTriggerSlotProps {
  togglePopover: () => void
  isOpen: boolean
  displayLabel: string
  inputValue: string
}

/** Props bound to the `actions` slot on `DatePicker`. */
export interface DatePickerActionsSlotProps {
  selected: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateRangePicker`. */
export interface DateRangePickerActionsSlotProps {
  fromDate: string
  toDate: string
  /**
   * Commits one endpoint, mirroring a calendar cell click:
   * first call sets `from`, second call sets `to`.
   */
  setDate: (date: string | Date | Dayjs) => void
  /**
   * Commits both endpoints atomically. Normalizes order so the earlier
   * date becomes `from`. Use for fixed-window presets ("Last 7 days").
   */
  setRange: (
    range: [string | Date | Dayjs, string | Date | Dayjs],
  ) => void
  clear: () => void
  close: () => void
}

/** Props bound to the `actions` slot on `DateTimePicker`. */
export interface DateTimePickerActionsSlotProps {
  selected: string
  time: string
  setDate: (date: string | Date | Dayjs) => void
  clear: () => void
  close: () => void
}

export interface DatePickerSlots {
  /** Custom trigger renderer for the picker. */
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Custom trigger renderer for the picker.
   * @deprecated Use `#trigger` instead. `#target` remains as a back-compat alias through v1.x.
   */
  target?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered before the trigger input value. */
  prefix?: (props: DatePickerTriggerSlotProps) => any

  /** Content rendered after the trigger input value. */
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date shortcuts
   * ("Today", "Tomorrow", "Last 7 days") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DatePickerActionsSlotProps) => any
}

export interface DateRangePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for range shortcuts
   * ("Last 7 days", "Last 12 months") and other preset actions. When
   * omitted, the popover shows the calendar only.
   */
  actions?: (props: DateRangePickerActionsSlotProps) => any
}

export interface DateTimePickerSlots {
  trigger?: (props: DatePickerTriggerSlotProps) => any

  /** @deprecated Use `#trigger` instead. */
  target?: (props: DatePickerTriggerSlotProps) => any

  prefix?: (props: DatePickerTriggerSlotProps) => any
  suffix?: (props: DatePickerTriggerSlotProps) => any

  /**
   * Sidebar rendered to the left of the calendar. Use for date-time
   * shortcuts ("Now", "Tomorrow 9am") and other preset actions. When
   * omitted, the popover shows the calendar and time picker only.
   */
  actions?: (props: DateTimePickerActionsSlotProps) => any
}

export type DatePickerViewMode = 'date' | 'month' | 'year'

export interface DatePickerDateObj {
  date: Dayjs
  key: string
  inMonth: boolean
  isToday: boolean
  isSelected: boolean
}
value
= ""

Deprecated — Use `modelValue` with `v-model` instead.

modelValue
= ""
string

Controlled value for the picker.

minDateTime

Deprecated — Use `min` instead.

maxDateTime

Deprecated — Use `max` instead.

allowCustomTime
= true
boolean

Allows typing a custom time into the embedded time picker.

side
PopoverSide

Preferred popover side relative to the trigger.

align
PopoverAlign

Alignment of the popover along the trigger edge.

offset
number

Gap between the trigger and popover content in pixels.

placement

Deprecated — Use `side` and `align` instead.

format
string

Display format used for the input text.

size
InputSize

Size of the trigger input.

variant
= "subtle"
InputVariant

Visual style variant passed through to the input.

placeholder
= "Select date & time"
string

Placeholder text shown when no value is selected.

open
boolean

Controls popover open state (for controlled usage).

openOnFocus
= false
boolean

Opens the popover when the input receives focus. Default: false.

openOnClick
= true
boolean

Opens the popover when the input is clicked. Default: true.

typeable
= true
boolean

Whether the trigger input accepts typed input. When `false` the user can still open the popover and pick a date, but cannot type a date manually. Default: `true`.

readonly
= false

Deprecated — Use `typeable: false` instead.

disabled
= false
boolean

Disables the trigger input and calendar interactions.

clearable
= true
boolean

Shows clear and quick-action controls when enabled.

keepOpen
boolean

Keeps the popover open after a date is selected. Default: false.

autoClose
= true

Deprecated — Use `keepOpen` instead (inverse semantics: `autoClose: false` → `keepOpen: true`).

min
string

Earliest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

max
string

Latest selectable date. Accepts `YYYY-MM-DD` (or, for `DateTimePicker`, `YYYY-MM-DD HH:mm:ss` for second-level granularity).

isDateUnavailable
((date: Dayjs) => boolean)

Return true to prevent a date from being selected. Combined with `min`/`max`.

allowCustom
= true

Deprecated — Use `typeable: false` instead.

inputClass

Deprecated — Apply `class` directly to the DatePicker component element to control width.

label
string

Label rendered above (or beside, for binary controls) the input.

description
string

Helper text rendered below the input. Hidden when `error` is set.

error
string | FrappeUIError

Error message rendered below the input. When set, the control receives `aria-invalid="true"` and `data-state="invalid"`. May be either a string or an `Error` object whose `messages?: string[]` is rendered as stacked lines (with `Error.message` as the fallback).

required
boolean

Marks the field as required. Renders an asterisk next to the label and forwards `required` / `aria-required` to the underlying control.

id
string

HTML id of the underlying control. Auto-generated via `useId()` if omitted.

trigger
DatePickerTriggerSlotProps
target

Deprecated — Use `#trigger` instead.

prefix
DatePickerTriggerSlotProps
suffix
DatePickerTriggerSlotProps
actions
DateTimePickerActionsSlotProps

Sidebar rendered to the left of the calendar. Use for date-time shortcuts ("Now", "Tomorrow 9am") and other preset actions. When omitted, the popover shows the calendar and time picker only.

update:modelValue
[value: string]

Fired when the model value changes.

change
[value: string]

Fired after the value is committed.

update:open
[value: boolean]

Fired when the open state changes.