Date Range Field
<script setup lang="ts">
import { DateRangeFieldInput, DateRangeFieldRoot, Label } from 'radix-vue'
</script>
<template>
<div class="flex flex-col gap-2">
<Label for="date-field" class="text-white">Booking</Label>
<DateRangeFieldRoot
id="date-field"
v-slot="{ segments }"
:is-date-unavailable="date => date.day === 19"
class="flex select-none bg-white items-center rounded-lg text-center text-green10 border border-transparent p-1 data-[invalid]:border-red-500"
>
<template v-for="item in segments.start" :key="item.part">
<DateRangeFieldInput
v-if="item.part === 'literal'"
:part="item.part"
type="start"
>
{{ item.value }}
</DateRangeFieldInput>
<DateRangeFieldInput
v-else
:part="item.part"
class="rounded-md p-0.5 focus:outline-none focus:shadow-[0_0_0_2px] focus:shadow-black aria-[valuetext=Empty]:text-green9"
type="start"
>
{{ item.value }}
</DateRangeFieldInput>
</template>
<span class="mx-2">
-
</span>
<template v-for="item in segments.end" :key="item.part">
<DateRangeFieldInput
v-if="item.part === 'literal'"
:part="item.part"
type="end"
>
{{ item.value }}
</DateRangeFieldInput>
<DateRangeFieldInput
v-else
:part="item.part"
class="rounded-md p-0.5 focus:outline-none focus:shadow-[0_0_0_2px] focus:shadow-black aria-[valuetext=Empty]:text-green9"
type="end"
>
{{ item.value }}
</DateRangeFieldInput>
</template>
</DateRangeFieldRoot>
</div>
</template>
Credit
This component was built taking inspiration from the implementation in melt-ui.
Features
- Full keyboard navigation
- Can be controlled or uncontrolled
- Focus is fully managed
- Localization support
- Highly composable
- Accessible by default
- Supports both date and date-time formats
Preface
The component depends on the @internationalized/date package, which solves a lot of the problems that come with working with dates and times in JavaScript.
We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components.
Installation
Install the date package.
npm install -D @internationalized/date
Install the component from your command line.
npm install radix-vue
Anatomy
Import all parts and piece them together.
<script setup>
import {
DateRangeFieldInput,
DateRangeFieldRoot,
} from 'radix-vue'
</script>
<template>
<DateRangeFieldRoot>
<DateRangeFieldInput />
</DateRangeFieldRoot>
</template>
API Reference
Root
Contains all the parts of a date field
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultPlaceholder | DateValue The default placeholder date | |
defaultValue | { start: DateValue; end: DateValue; } The default value for the calendar | |
disabled | false | boolean Whether or not the date field is disabled |
granularity | 'day' | 'hour' | 'minute' | 'second' The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | |
hideTimeZone | boolean Whether or not to hide the time zone segment of the field | |
hourCycle | 12 | 24 The hour cycle used for formatting times. Defaults to the local preference | |
id | string Id of the element | |
isDateUnavailable | Matcher A function that returns whether or not a date is unavailable | |
locale | 'en' | 'tr' | 'th' | 'en' | 'ach' | 'af' | 'am' | 'an' | 'ar' | 'ast' | 'az' | 'be' | 'bg' | 'bn' | 'br' | 'bs' | 'ca' | 'cak' | 'ckb' | 'cs' | 'cy' | 'da' | 'de' | 'dsb' | 'el' | 'eo' | 'es' | ... 49 more ... Whether or not the calendar is readonly |
maxValue | DateValue The maximum date that can be selected | |
minValue | DateValue The locale to use for formatting dates | |
modelValue | { start: DateValue; end: DateValue; } The controlled checked state of the calendar. Can be bound as | |
name | string The name of the date field. Submitted with its owning form as part of a name/value pair. | |
placeholder | DateValue The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programatically control the calendar view | |
readonly | false | boolean Whether or not the date field is readonly |
required | boolean When |
Emit | Payload |
---|---|
update:modelValue | [{ start: DateValue; end: DateValue; }] Event handler called whenever the model value changes |
update:placeholder | [date: DateValue] Event handler called whenever the placeholder value changes |
Slots (default) | Payload |
---|---|
modelValue | { start: DateValue | undefined; end: DateValue | undefined; } |
segments | { start: { part: SegmentPart; value: string; }[]; end: { part: SegmentPart; value: string; }[]; } |
Methods | Type |
---|---|
setFocusedElement | (el: HTMLElement) => void |
Data Attribute | Value |
---|---|
[data-readonly] | Present when readonly |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
Input
Contains the date field segments
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
part* | 'day' | 'month' | 'year' | 'hour' | 'minute' | 'second' | 'dayPeriod' | 'literal' | 'timeZoneName' The part of the date to render | |
type* | 'start' | 'end' The type of field to render (start or end) |
Data Attribute | Value |
---|---|
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
Accessibility
Keyboard Interactions
Key | Description |
---|---|
Tab | When focus moves onto the date field, focuses the first segment. |
ArrowLeftArrowRight |
Navigates between the date field segments.
|
ArrowUpArrowDown | Increments/changes the value of the segment. |
0-9 |
When the focus is on a numeric DateFieldInput , it types in the number and focuses the next segment if the next input would result in an invalid value.
|
Backspace | Deletes a digit from the focused numeric segments. |
AP | When the focus is on the day period, it sets it to AM or PM. |