Skip to content

Date Range Picker

The date range calendar allows users to select a start and end date from a calendar.

Basic Usage

//
to
//

Property Value: { "startDate": "", "endDate": "" }

vue
<template>
  <spr-date-range-picker id="dateRange1" v-model="dateRangeModel" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Custom Input Area (Using Slot)

You can fully customize the date input area using the default slot. This allows you to use any component (like <spr-input> or <spr-chips>) and react to the selected range from v-model.

Using with Input

vue
<template>
  <spr-date-range-picker
    id="inputSample"
    v-model="liveInputRange"
    label="Custom Input (spr-input)"
    placement="top"
  >
    <template #default="{ handleClick }">
      <spr-input
        v-model="inputDisplayString"
        readonly
        class="spr-w-full spr-cursor-pointer"
        @click="handleClick"
      >
        <template #icon>
          <Icon icon="ph:calendar-blank" />
        </template>
      </spr-input>
    </template>
  </spr-date-range-picker>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue';
const dateRangeModel = ref({ startDate: '01-01-2024', endDate: '01-15-2024' });
const liveInputRange = ref({ startDate: '01-01-2024', endDate: '01-15-2024' });
const formatRange = (range) => {
  const monthNames = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
  if (range.startDate && !range.endDate) {
    const [startMonth, startDay] = range.startDate.split('-');
    return `${monthNames[parseInt(startMonth, 10) - 1]} / ${startDay} – `;
  }
  if (range.startDate && range.endDate) {
    const [startMonth, startDay] = range.startDate.split('-');
    const [endMonth, endDay] = range.endDate.split('-');
    return `${monthNames[parseInt(startMonth, 10) - 1]} / ${startDay} – ${monthNames[parseInt(endMonth, 10) - 1]} / ${endDay}`;
  }
  return '';
};

const inputDisplayString = ref('');
watch(liveInputRange, (range) => {
  inputDisplayString.value = formatRange(range);
}, { immediate: true });
</script>

Using with Chips

01-01-2024
to
01-15-2024
vue
<template>
  <spr-date-range-picker id="chipsSample" v-model="dateRangeModel" label="Pay Period">
    <template #default>
      <div class="spr-flex spr-gap-2 spr-items-center spr-p-2">
        <spr-chips tone="info" :label="dateRangeModel.startDate || 'Start'" />
        <span class="spr-text-mushroom-500">to</span>
        <spr-chips tone="info" :label="dateRangeModel.endDate || 'End'" />
      </div>
    </template>
  </spr-date-range-picker>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '01-01-2024', endDate: '01-15-2024' });
</script>

You can use any component or markup in the slot, and the slot will always receive the latest value from v-model for full control over the display.

Adding Label

//
to
//

Value: { "startDate": "", "endDate": "" }

vue
<template>
  <spr-date-range-picker id="dateRange2" v-model="dateRangeModel" label="Date Range" display-helper format="YYYY-MM-DD" />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Custom Width

You can manually set the width of the date range calendar by passing the width prop.

//
to
//

Property Value: { "startDate": "", "endDate": "" }

vue
<template>
  <spr-date-range-picker id="dateRange3" v-model="dateRangeModel" label="Date Range" width="400px" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Date Format

You can specify the format of the date by passing the format prop. The default format is MM-DD-YYYY. The component will return dates in the specified format.

//
to
//

Value: { "startDate": "", "endDate": "" }

vue
<template>
  <spr-date-range-picker id="dateRange4" v-model="dateRangeModel" label="Date Range" format="YYYY-MM-DD" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Disabled

Add the disabled prop to disable the date range calendar.

//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange5" v-model="dateRangeModel" label="Date Range" display-helper disabled />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Read Only

Add the readonly prop to make the date range calendar read only.

//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange6" v-model="dateRangeModel" label="Date Range" display-helper readonly />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Helper Text

A helper message is a text label displayed below the input field, offering additional information such as instructions, formatting tips, or validation feedback.

To display the helper message, set the display-helper prop to true and add the helper-text prop with the message content. You can also include an icon by using the helper-icon prop.

//
to
//
Select a date range
vue
<template>
  <spr-date-range-picker id="dateRange7" v-model="dateRangeModel" label="Date Range" helper-text="Select a date range" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Error State

To handle error states, add the error prop to the date range calendar. You can also include an icon by using the helper-icon prop.

//
to
//
This is a helper message
vue
<template>
  <spr-date-range-picker id="dateRange8" v-model="dateRangeModel" label="Date Range" helper-icon="ph:warning-circle-fill" helper-text="This is a helper message" display-helper error />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Min/Max Year

You can manually set the minimum and maximum year to be shown in the calendar. The default minimum year is 1900 and the maximum year is the current year.

//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange9" v-model="dateRangeModel" label="Date Range" :min-max-year="{ min: 2000, max: 2025 }" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Rest Days

You can set the rest days in the week by passing the rest-days prop.

js
const restDays = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];
//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange10" v-model="dateRangeModel" label="Date Range" :rest-days="['mo', 'we', 'fr', 'sa']" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Placement

The date range picker uses intelligent placement logic for the calendar popover:

Default Input Fields

When using the default input fields (no custom slot), the component uses the placement prop to determine the base direction (top or bottom) and automatically concatenates it with the appropriate alignment based on which input field is clicked:

  • Start Date Input: Uses {placement}-start (e.g., top-start or bottom-start)
  • End Date Input: Uses {placement}-end (e.g., top-end or bottom-end)

For example, if you set placement="top":

  • Clicking the start date input will use top-start placement
  • Clicking the end date input will use top-end placement

This dynamic placement ensures the calendar always appears in the most appropriate position relative to the clicked input field while respecting your preferred vertical direction.

Default Inputs with Custom Placement

//
to
//
vue
<template>
  <spr-date-range-picker 
    id="defaultTopPlacement" 
    v-model="dateRangeModel" 
    label="Top Placement" 
    placement="top"
    display-helper 
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Custom Slot Components

When using a custom slot for the input area, the component respects the placement prop you specify:

vue
<template>
  <spr-date-range-picker
    v-model="liveInputRange"
    label="Custom Input (spr-input)"
  >
    <template #default="{ handleClick }">
      <spr-input
        v-model="inputDisplayString"
        readonly
        class="spr-w-full spr-cursor-pointer"
        @click="handleClick"
      >
        <template #icon>
          <Icon icon="ph:calendar-blank" />
        </template>
      </spr-input>
    </template>
  </spr-date-range-picker>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue';
import { Icon } from '@iconify/vue';
const liveInputRange = ref({ startDate: '01-01-2024', endDate: '01-15-2024' });
const inputDisplayString = ref('');
const formatRange = (range) => {
  const monthNames = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
  if (range.startDate && !range.endDate) {
    const [startMonth, startDay] = range.startDate.split('-');
    return `${monthNames[parseInt(startMonth, 10) - 1]} / ${startDay} – `;
  }
  if (range.startDate && range.endDate) {
    const [startMonth, startDay] = range.startDate.split('-');
    const [endMonth, endDay] = range.endDate.split('-');
    return `${monthNames[parseInt(startMonth, 10) - 1]} / ${startDay} – ${monthNames[parseInt(endMonth, 10) - 1]} / ${endDay}`;
  }
  return '';
};
watch(liveInputRange, (range) => {
  inputDisplayString.value = formatRange(range);
}, { immediate: true });
</script>

Available Placement Options

  • top-start, top, top-end
  • bottom-start, bottom, bottom-end
  • left-start, left, left-end
  • right-start, right, right-end

Disabled Dates

You can disable specific dates by passing the disabled-dates prop. There are ways to disable dates:

  • Disable dates using From and To
  • Disable Past or Future Dates
  • Disable Past or Future with Selected Date
  • Disable Selected Dates
  • Disable Weekends
  • Disable Weekdays
  • Disable Selected Days
js
const disabledDates = { from: '02-12-2025', to: '05-15-2025' };
//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange11" v-model="dateRangeModel" label="Date Range" :disabled-dates="{ from: '02-12-2025', to: '05-15-2025' }" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '', endDate: '' });
</script>

Pre-selected Range

You can pre-select a date range by just adding values in your v-model. The value should be in the format { startDate: 'MM-DD-YYYY', endDate: 'MM-DD-YYYY' }.

//
to
//
vue
<template>
  <spr-date-range-picker id="dateRange12" v-model="dateRangeModel" label="Date Range" display-helper />
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const dateRangeModel = ref({ startDate: '09-11-2022', endDate: '09-15-2022' });
</script>

Emits

  • @get-input-value - Emits the actual date range that is being typed or selected
  • @get-date-formats - Emits the available date formats for the selected range
  • @get-month-list - Emits the list of months
  • @get-year-list - Emits the list of years
  • @get-date-errors - Emits the available date errors
  • @range-change - Emits when the range changes

API Reference

PropertyDescriptionTypeDefault
idRequired to bind popper within the calendarString-
v-modelBinds the selected date range valueObject{ startDate: '', endDate: '' }
labelLabel text for the input fieldString-
widthSets the width of the inputString400px
formatFormat for the selected date (e.g., 'MM-DD-YYYY')StringMM-DD-YYYY
disabledDisables the date range calendarBooleanfalse
readonlyMakes the date range calendar read-onlyBooleanfalse
helper-textDisplays a helper message below the inputString-
helper-iconIcon to display alongside the helper messageString-
display-helperShows the helper messageBooleanfalse
errorIndicates that there is an error with the inputBooleanfalse
current-yearSets the current year in the calendar viewString{ new Date().getFullYear() }
min-max-yearSets the minimum and maximum years in the calendarObject{ min: 1900, max: { new Date().getFullYear() } }
rest-daysArray of days to be treated as rest daysArray[]
disabled-datesDisables specific dates or date rangesObject{}
placementChanges the placement of the dropdown popper. For default inputs, uses the specified placement (e.g., 'top' or 'bottom') and concatenates with 'start' or 'end' based on clicked field. For custom slots, uses the exact placement value specified.String'bottom'
popper-strategyPopper positioning strategyStringabsolute

Product Uses

Sprout Sidekick