Date Range Picker
The date range calendar allows users to select a start and end date from a calendar.
Basic Usage
Property Value:
{
"startDate": "",
"endDate": ""
}
<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
<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
<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
Value: { "startDate": "", "endDate": "" }
<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.
Property Value:
{
"startDate": "",
"endDate": ""
}
<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.
Value: {
"startDate": "",
"endDate": ""
}
<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.
<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.
<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.
<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.
<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.
<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.
const restDays = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];
<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
orbottom-start
) - End Date Input: Uses
{placement}-end
(e.g.,top-end
orbottom-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
<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:
<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
const disabledDates = { from: '02-12-2025', to: '05-15-2025' };
<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' }
.
<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
Property | Description | Type | Default |
---|---|---|---|
id | Required to bind popper within the calendar | String | - |
v-model | Binds the selected date range value | Object | { startDate: '', endDate: '' } |
label | Label text for the input field | String | - |
width | Sets the width of the input | String | 400px |
format | Format for the selected date (e.g., 'MM-DD-YYYY') | String | MM-DD-YYYY |
disabled | Disables the date range calendar | Boolean | false |
readonly | Makes the date range calendar read-only | Boolean | false |
helper-text | Displays a helper message below the input | String | - |
helper-icon | Icon to display alongside the helper message | String | - |
display-helper | Shows the helper message | Boolean | false |
error | Indicates that there is an error with the input | Boolean | false |
current-year | Sets the current year in the calendar view | String | { new Date().getFullYear() } |
min-max-year | Sets the minimum and maximum years in the calendar | Object | { min: 1900, max: { new Date().getFullYear() } } |
rest-days | Array of days to be treated as rest days | Array | [] |
disabled-dates | Disables specific dates or date ranges | Object | {} |
placement | Changes 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-strategy | Popper positioning strategy | String | absolute |