Skip to content

DateRange ​

DateRange is a feature-rich date range picker component that supports dual calendar display, shortcuts, range constraints, and complete internationalization functionality.

Main Features ​

Date Range Selection and Input ​

Basic Date Range Selection

Click to select start and end dates, supports dual calendar display

Date Range with Time

Set start and end times after selecting dates

Required Validation

Real-time validation with error messages

vue
<template>
  <!-- Basic range selection -->
  <DateRange v-model="basicRange" />

  <!-- Date range with time -->
  <DateRange v-model="timeRange" :showTime="true" />

  <!-- Required validation -->
  <DateRange v-model="requiredRange" required />
</template>

Direct Input Field Entry ​

Input Field Entry

Use input fields directly within the calendar to enter date ranges

Calendar Only Selection

Hide input fields, use calendar selection only

vue
<template>
  <!-- Enable input fields -->
  <DateRange v-model="inputRange" :inputEnabled="true" />

  <!-- Calendar only selection -->
  <DateRange v-model="calendarOnlyRange" :inputEnabled="false" />
</template>

WARNING

Input functionality is only available when displayMode is set to 'dual'

Calendar Display Mode ​

Dual Month Display Mode

Display two consecutive month calendars simultaneously for easy cross-month range selection

Single Month Display Mode

Display only a single month calendar to save display space

Auto Mode (Default)

Automatically switch based on screen width: dual month on desktop, single month on mobile

vue
<template>
  <!-- Force dual month display -->
  <DateRange v-model="dualModeRange" monthDisplayMode="dual" />

  <!-- Force single month display -->
  <DateRange v-model="singleModeRange" monthDisplayMode="single" />

  <!-- Auto adaptive (default behavior) -->
  <DateRange v-model="autoModeRange" />
</template>

Shortcuts ​

Built-in Shortcuts

Provides shortcuts like Today, Last 7 days, Last 30 days, This month, etc.

vue
<template>
  <!-- Show shortcuts -->
  <DateRange v-model="shortcutRange" :showShortcuts="true" />
</template>

Range Constraints ​

Maximum Range Limit

Can only select a range of up to 7 days

Minimum Range Limit

Must select at least a 3-day range

Date Range Constraints

Constrain selectable date range: 2025-01-01 ~ 2025-12-31

vue
<template>
  <!-- Maximum range limit -->
  <DateRange v-model="maxRangeLimit" :maxRange="7" />

  <!-- Minimum range limit -->
  <DateRange v-model="minRangeLimit" :minRange="3" />

  <!-- Date range constraints -->
  <DateRange
    v-model="dateConstrainedRange"
    :minDate="minDate"
    :maxDate="maxDate"
  />
</template>

Inline Mode ​

Set inline to render only the calendar body: no trigger row (calendar icon and clear button included), no Teleport, no positioning, and no document listener that could close the calendar. Opening and closing, outside-click, Esc, focus management and positioning are entirely your container's responsibility.

Use it when the calendar belongs inside a popover, dropdown, or panel you already own. Because the calendar becomes a real descendant of your panel, your own outside-click check (panel.contains(event.target)) recognises clicks on it — without inline, clicking a day would register as a click outside your panel and close it.

vue
<template>
  <div v-if="open" ref="panel" class="my-panel">
    <DateRange inline v-model="range" :show-shortcuts="true" />
  </div>
</template>

Differences under inline:

  • showCalendarIcon / showClearButton are ignored (not rendered); call the exposed reset() or set the v-model to null to clear
  • No component min-width is applied — width is up to your container; the calendar caps itself at 20rem (320px)
  • No border, shadow, background or z-index; your container provides the surface
  • The panel is role="group", not a modal dialog
  • When disabled, the calendar is not rendered (there is no trigger to disable)
  • monthDisplayMode defaults to 'single' and does not follow the window width; pass 'dual' explicitly if your container is at least ~570px wide
  • showShortcuts is kept; inputEnabled is kept (requires monthDisplayMode="dual")

Props ​

Basic Properties ​

PropertyTypeDefaultDescription
modelValue{ start: DateTimeInput; end: DateTimeInput } | nullnullBound date range value
disabledbooleanfalseWhether disabled
requiredbooleanfalseWhether required
showClearButtonbooleantrueShow clear button
separatorstring' ~ 'Separator between start and end dates

Calendar System ​

PropertyTypeDefaultDescription
calendarstring'gregory'Calendar system ('gregory', 'roc')
localestring'zh-TW'Locale
weekStartsOn0-60Week start day (0=Sunday)

Date Format ​

PropertyTypeDefaultDescription
dateFormatstring'YYYY-MM-DD'Date format
dateSeparatorstring'-'Date separator
outputTypeOutputType'iso'Output type
useStrictISObooleanfalseStrict ISO format

Time Options ​

PropertyTypeDefaultDescription
showTimebooleanfalseShow time selection
timeFormatstringundefinedTime format (defaults based on enableSeconds & use24Hour)
enableSecondsbooleantrueEnable seconds
use24HourbooleantrueUse 24-hour format

Range-Specific Options ​

PropertyTypeDefaultDescription
monthDisplayMode'single' | 'dual'undefinedCalendar display mode, auto-switches by window size when unset; always 'single' when inline
showShortcutsbooleanfalseShow shortcuts
incompletebooleantrueShow incomplete range selection
maxRangenumberundefinedMaximum selectable days
minRangenumberundefinedMinimum selectable days
minDatestringundefinedMinimum selectable date
maxDatestringundefinedMaximum selectable date

Theme Appearance ​

PropertyTypeDefaultDescription
mode'light' | 'dark' | 'auto''auto'Theme mode (light / dark / follow system)
themeTailwindColor | stringundefinedTheme color — a built-in name, hex, rgb, or oklch. Defaults to the family primary (indigo).

Internationalization & Error Handling ​

PropertyTypeDefaultDescription
customLocaleMessagesLocaleMessagesundefinedCustom locale messages
customErrorMessagesRecord<string, string>{}Custom error messages
useI18nbooleantrueUse built-in i18n
showErrorMessagebooleantrueShow error messages

Input Control ​

PropertyTypeDefaultDescription
inlinebooleanfalseRender only the calendar body, without the built-in popup (see Inline Mode above)
inputEnabledbooleanfalseAllow input field entry
placeholderOverridesPlaceholderOverrides{}Custom placeholders
autoFocusTimeAfterDatebooleantrueAuto focus time input after date

PlaceholderOverrides interface:

typescript
interface PlaceholderOverrides {
  start?: string; // Start date hint text
  end?: string; // End date hint text
  year?: string; // Year input placeholder
  month?: string; // Month input placeholder
  day?: string; // Day input placeholder
  hour?: string; // Hour input placeholder
  minute?: string; // Minute input placeholder
  second?: string; // Second input placeholder
}

Events ​

Event NameParametersDescription
update:modelValue(range: { start: DateTimeInput; end: DateTimeInput } | null)Triggered when range value changes
change(range: { start: DateTimeInput; end: DateTimeInput } | null)Triggered when user changes value
validation(isValid: boolean, errors: Record<string, string>, errorParams?: Record<string, Record<string, any>>)Triggered when validation changes

Advanced Features ​

Multiple Calendar Systems ​

Gregorian Calendar

ROC Calendar

vue
<template>
  <!-- Gregorian Calendar -->
  <DateRange v-model="gregorianRange" calendar="gregory" />

  <!-- ROC Calendar -->
  <DateRange v-model="rocRange" calendar="roc" outputType="custom" />
</template>

TIP

For more calendar systems, see calendar

Theme Modes ​

Light Mode

Dark Mode

vue
<template>
  <!-- Different theme modes -->
  <DateRange v-model="lightRange" mode="light" theme="blue" />
  <DateRange v-model="darkRange" mode="dark" theme="emerald" />
</template>

TIP

For more theme options, see theme

Time Configuration ​

24-Hour Time Range

12-Hour Time Range

Time Range without Seconds

vue
<template>
  <!-- 24-hour format -->
  <DateRange v-model="time24Range" :showTime="true" :use24Hour="true" />

  <!-- 12-hour format -->
  <DateRange v-model="time12Range" :showTime="true" :use24Hour="false" />

  <!-- Without seconds -->
  <DateRange
    v-model="timeNoSecondsRange"
    :showTime="true"
    :enableSeconds="false"
  />
</template>

Output Formats ​

ISO Format Output

Output: { "start": "", "end": "" }

ISO Format Output (Strict Mode)

Output: { "start": "", "end": "" }

JavaScript Date Object Format

Output: { "start": "", "end": "" }

Object Format

Output: { "start": "", "end": "" }

Custom Format Output

Output: { "start": "", "end": "" }

vue
<template>
  <!-- ISO format -->
  <DateRange v-model="isoRange" outputType="iso" />

  <!-- ISO format (strict mode) -->
  <DateRange
    v-model="isoStrictRange"
    outputType="iso"
    :useStrictISO="true"
    :showTime="true"
  />

  <!-- Date object format -->
  <DateRange v-model="jsDateRange" outputType="date" />

  <!-- Object format -->
  <DateRange v-model="objectRange" outputType="object" />

  <!-- Custom format -->
  <DateRange
    v-model="customFormatRange"
    outputType="custom"
    dateFormat="YY/MM/DD"
  />
</template>

Slots ​

DateRange provides multiple slots to customize shortcuts and error message handling.

Shortcuts Slot ​

Custom Shortcuts

Add custom shortcut buttons

Code Example
vue
<template>
  <DateRange v-model="range" :showShortcuts="true">
    <template #shortcuts="{ applyShortcut }">
      <button
        @click="
          applyShortcut({
            label: 'This Quarter',
            getValue: () => getCurrentQuarterRange(),
          })
        "
        class="px-3 py-1 text-xs bg-purple-100 text-purple-700 hover:bg-purple-200 rounded-sm transition-colors"
      >
        This Quarter
      </button>
      <button
        @click="
          applyShortcut({
            label: 'Same Period Last Year',
            getValue: () => getLastYearSamePeriod(),
          })
        "
        class="px-3 py-1 text-xs bg-green-100 text-green-700 hover:bg-green-200 rounded-sm transition-colors"
      >
        Same Period Last Year
      </button>
    </template>
  </DateRange>

  <script setup lang="ts">
    // Custom shortcut functions
    const getCurrentQuarterRange = () => {
      const now = new Date();
      const quarter = Math.floor(now.getMonth() / 3);
      const startMonth = quarter * 3;
      const start = new Date(now.getFullYear(), startMonth, 1);
      const end = new Date(now.getFullYear(), startMonth + 3, 0);

      return {
        start: {
          year: start.getFullYear(),
          month: start.getMonth() + 1,
          day: start.getDate(),
        },
        end: {
          year: end.getFullYear(),
          month: end.getMonth() + 1,
          day: end.getDate(),
        },
      };
    };

    const getLastYearSamePeriod = () => {
      const now = new Date();
      const lastYear = now.getFullYear() - 1;

      return {
        start: {
          year: lastYear,
          month: now.getMonth() + 1,
          day: 1,
        },
        end: {
          year: lastYear,
          month: now.getMonth() + 1,
          day: now.getDate(),
        },
      };
    };
  </script>
</template>

DateRange also supports calendar customization, see DatePicker Slots.

Error Message Slot ​

DateRange also supports custom error messages, see Error Message Handling Documentation.

Available Slots List ​

Slot NameDescriptionSlot Props
shortcutsCustom shortcuts{ applyShortcut, shortcuts, currentRange }
errorCustom error message display{ errors, errorParams, hasErrors }

Keyboard Navigation ​

DateRange provides complete keyboard navigation functionality:

Smart Input and Navigation

• Tab / Shift+Tab switch between start and end dates

• → / ← switch between date fields

• Backspace in empty field returns to previous field

• Enter completes input and validates

• Auto focus to end date after completing start date

• Auto focus to time field after completing date input

Range Validation ​

DateRange provides multiple range validation features:

Invalid Range Handling

Try selecting a range longer than 5 days or empty range to see error messages

Auto-correct Range Order

If end date is earlier than start date, the system will automatically swap them

Common validation rules:

  • End date must be later than or equal to start date
  • Range days must comply with minRange and maxRange limits
  • Dates must be within minDate and maxDate range
  • Both dates cannot be empty