Date Range Field
An enhanced alternative to using multiple native date inputs for selecting a date range.
Features
- Full keyboard navigation
- Localization support
- Can be controlled or uncontrolled
- Focus is fully managed
- Accessible by default
- Supports both date and date-time formats
Overview
The Date Range Field is an enhanced alternative to the rather limited date range selection setup using two native inputs. It provides a more user-friendly interface for selecting dates and times, is fully accessible, and works in all modern browsers & devices.
Anatomy
- Field: The element which contains the date segments
- Start Segment: An individual segment of the start date (day, month, year, etc.)
- End Segment: An individual segment of the end date (day, month, year, etc.)
- Label: The label for the date field
- Start Hidden Input: A hidden input element containing the ISO 8601 formatted string of the start date
- End Hidden Input: A hidden input element containing the ISO 8601 formatted string of the end date
Tutorial
Learn how to use the Date Range Field builder by starting simple and working your way up to more complex examples and use cases. The goal is to teach you the key features and concepts of the builder, so you won’t have to read through a bunch of API reference docs (Although, those are available too!)
Building a Date Range Field
Let's initialize our field using the createDateRangeField
function, which returns an object
consisting of the stores & methods needed to construct the field.
To start off, we'll destructure the field
, startSegment
, endSegment
, label
, and
segmentContents
.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
The field
is responsible for containing the date segments. The label
for the date field is not
an actual <label>
element, due to the way we interact with the field, but is still accessible to
screen readers in the same way.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
<span use:melt={$label}>Trip Dates</span>
<div use:melt={$field}>
<!-- ... -->
</div>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
<span {...$label} use:label>Trip Dates</span>
<div {...$field} use:field>
<!-- ... -->
</div>
Unlike the other elements, startSegment
& endSegment
are functions which take a SegmentPart
as an argument, which is used to determine which segment this element represents.
While it's possible to use the start and end functions to render each segment individually like so:
<span use:melt={$label}>Trip Date</span>
<div use:melt={$field}>
<div use:melt={$startSegment('day')}>
<!-- ... -->
</div>
<div use:melt={$startSegment('month')}>
<!-- ... -->
</div>
<div use:melt={$startSegment('year')}>
<!-- ... -->
</div>
<div use:melt={$endSegment('day')}>
<!-- ... -->
</div>
<!-- ...rest -->
</div>
<span {...$label} use:label>Trip Date</span>
<div {...$field} use:field>
<div {...$startSegment('day')} use:startSegment>
<!-- ... -->
</div>
<div {...$startSegment('month')} use:startSegment>
<!-- ... -->
</div>
<div {...$startSegment('year')} use:startSegment>
<!-- ... -->
</div>
<div {...$endSegment('day')} use:endSegment>
<!-- ... -->
</div>
<!-- ...rest -->
</div>
It's not recommended, as the formatting doesn't adapt to the locale and type of date being represented, which is one of the more powerful features this builder provides.
Instead, you can use the segmentContents
state, which is an object containing start
and end
properties, whose values are an array of objects necessary to form the date. Each object has a
part
property, which is the `SegmentPart`, and a value
property, which is
the locale-aware string representation of the segment.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
<span use:melt={$label}>Trip Dates</span>
<div use:melt={$field}>
{#each $segmentContents.start as seg, i (i)}
<div use:melt={$startSegment(seg.part)}>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div use:melt={$endSegment(seg.part)}>
{seg.value}
</div>
{/each}
</div>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField()
</script>
<span {...$label} use:label>Trip Dates</span>
<div {...$field} use:field>
{#each $segmentContents.start as seg, i (i)}
<div {...$startSegment(seg.part)} use:startSegment>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div {...$endSegment(seg.part)} use:endSegment>
{seg.value}
</div>
{/each}
</div>
To actually use the value of the field, you can either use the value
state directly, or if you're
using it within a form, the startHiddenInput
& endHiddenInput
elements, which are hidden input
elements containing an ISO 8601 formatted string of the value that input represents.
If you plan on using the hidden inputs, you'll need to pass the startName
and endName
props,
which will be used as the respective input's name attribute.
<script lang="ts">
import { createDateField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label, startHiddenInput, endHiddenInput },
states: { segmentContents, value }
} = createDateField({
startName: 'tripStart',
endName: 'tripEnd'
})
</script>
<form method="POST">
<span use:melt={$label}>Trip Dates</span>
<div use:melt={$field}>
{#each $segmentContents.start as seg, i (i)}
<div use:melt={$startSegment(seg.part)}>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div use:melt={$endSegment(seg.part)}>
{seg.value}
</div>
{/each}
<input use:melt={$startHiddenInput} />
<input use:melt={$endHiddenInput} />
</div>
<p>
You selected:
{#if $value}
{$value}
{/if}
</p>
</form>
<script lang="ts">
import { createDateField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label, startHiddenInput, endHiddenInput },
states: { segmentContents, value }
} = createDateField({
startName: 'tripStart',
endName: 'tripEnd'
})
</script>
<form method="POST">
<span {...$label} use:label>Trip Dates</span>
<div {...$field} use:field>
{#each $segmentContents.start as seg, i (i)}
<div {...$startSegment(seg.part)} use:startSegment>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div {...$endSegment(seg.part)} use:endSegment>
{seg.value}
</div>
{/each}
<input {...$startHiddenInput} use:startHiddenInput />
<input {...$endHiddenInput} use:endHiddenInput />
</div>
<p>
You selected:
{#if $value}
{$value}
{/if}
</p>
</form>
And that, along with some additional structure and styles, is all you need to get a fully functional Date Range Field!
The Power of Placeholder
In the previous example, we didn't pass any date-related props to the createDateRangeField
function, which means it defaulted to a CalendarDate
object with the current date. What if we
wanted to start off with a different type of date, such as a CalendarDateTime
or a
ZonedDateTime
, but keep the initial value empty?
That's where the placeholder props come in, which consist of the uncontrolled defaultPlaceholder
prop, and the controlled placeholder
prop.
In the absense of a value
or defaultValue
prop (which we'll cover soon), the placeholder holds
all the power in determining what type of date the field represents, and how it should be
rendered/formatted.
Let's convert our previous example into a Date & Time field, by passing a CalendarDateTime
object
as the defaultPlaceholder
prop.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDateTime(2023, 10, 11, 12, 30)
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDateTime(2023, 10, 11, 12, 30)
})
</script>
As you can see above, by making that one change, the field now represents date and times, and the segments have been updated to reflect that.
If your placeholder value is coming from a database or elsewhere, you can use one of the parser
functions provided by
@internationalized/date to
convert it into a CalendarDateTime
object.
import { CalendarDateTime, parseDateTime } from '@internationalized/date'
// Constructor with a time
const date = new CalendarDateTime(2023, 10, 11, 12, 30)
// Constructor without a time (defaults to 00:00:00)
const date = new CalendarDateTime(2023, 10, 11)
// Parser function to convert an ISO 8601 formatted string
const date = parseDateTime('2023-10-11T12:30:00')
import { CalendarDateTime, parseDateTime } from '@internationalized/date'
// Constructor with a time
const date = new CalendarDateTime(2023, 10, 11, 12, 30)
// Constructor without a time (defaults to 00:00:00)
const date = new CalendarDateTime(2023, 10, 11)
// Parser function to convert an ISO 8601 formatted string
const date = parseDateTime('2023-10-11T12:30:00')
We can also just as easily convert the field into a Zoned Date & Time field, by passing a
ZonedDateTime
object as the defaultPlaceholder
prop.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { now, getLocalTimeZone } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: now(getLocalTimeZone())
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { now, getLocalTimeZone } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: now(getLocalTimeZone())
})
</script>
We're using the now
parser function to create a ZonedDateTime
object with the current date and
time, and we're getting the user's local timezone using the getLocalTimeZone
function.
Alternatively, we can hardcode the timezone to something like America/Los_Angeles
by passing it as
the argument to the now
function.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { now } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: now('America/Los_Angeles')
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { now } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: now('America/Los_Angeles')
})
</script>
How you represent and store dates with timezones will depend entirely on your use case, but there are a number of parser functions available to help you out, which you can read more about here .
Working with Values
Now that we've covered the basics of the Date Range Field, as well as the power of the placeholder,
let's look at how we can use the defaultValue
to set the value of the field.
Remember, the placeholder props are only relevant in the absense of a value
or defaultValue
prop, as they take precedence over the placeholder. When a value
or defaultValue
prop is passed,
the placeholder is set to the end
value of those props.
We can demonstrate this by keeping the defaultPlaceholder
prop as a CalendarDate
object, and
passing a DateRange
using CalendarDateTime
objects as the defaultValue
prop. It's not
recommended that you ever these to to different types, but it's useful to understand how the
placeholder & value props interact.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime, CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDate(2023, 10, 11),
defaultValue: {
start: new CalendarDateTime(2023, 10, 11, 12, 30),
end: new CalendarDateTime(2023, 10, 15, 12, 30)
}
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime, CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDate(2023, 10, 11),
defaultValue: {
start: new CalendarDateTime(2023, 10, 11, 12, 30),
end: new CalendarDateTime(2023, 10, 15, 12, 30)
}
})
</script>
As you can see, the field represents a CalendarDateTime
object, and even if you clear the field,
it will retain that shape.
A really useful scenario for using the defaultValue
prop and the defaultPlaceholder
prop in
conjunction with one another is when a defaultValue
may or may not be present, and you want to
ensure the field always represents a certain type of date.
For example, let's say this field is selecting a contact availability range in a user's profile,
which is optional, but you want to ensure that if they do enter a range, it's represented as a
CalendarDateTime
object. The code to accomplishing that may look something like this:
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime, CalendarDate, parseDateTime } from '@internationalized/date'
export let data
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDate(2023, 10, 11),
defaultValue: {
start: data?.userAvailabilityStart ? parseDateTime(data?.userAvailabilityStart) : undefined,
end: data?.userAvailabilityEnd ? parseDateTime(data?.userAvailabilityEnd) : undefined
}
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDateTime, CalendarDate, parseDateTime } from '@internationalized/date'
export let data
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultPlaceholder: new CalendarDate(2023, 10, 11),
defaultValue: {
start: data?.userAvailabilityStart ? parseDateTime(data?.userAvailabilityStart) : undefined,
end: data?.userAvailabilityEnd ? parseDateTime(data?.userAvailabilityEnd) : undefined
}
})
</script>
If the user has those availability settings, we parse the ISO 8601 formatted string into a
CalendarDateTime
object, and if not, we pass undefined
for the start and end values, which will
cause the field to default to the defaultPlaceholder
prop, which we've set to a CalendarDate
object.
The following example demonstrates how it would work in both scenarios (with and without availability dates).
Situations like this make using the defaultValue
and defaultPlaceholder
props together a must.
Validating Dates
This is where things start to get a lot more fun! This builder provides a few ways to validate
dates, which we'll cover in this section, starting with the isDateUnavailable
prop.
The isDateUnavailable
prop is a Matcher
function, which takes a DateValue
object as an
argument, and returns a boolean indicating whether or not that date is unavailable.
type Matcher = (date: DateValue) => boolean
type Matcher = (date: DateValue) => boolean
If the date the user selects is unavailable, is marked as invalid, and you can do whatever you'd like with that information.
Let's say that we don't want users to ever be able to select the 1st or the 15th of any month, as
those are the only two days we're not working on builder tutorials. We can setup a Matcher
function to accomplish just that.
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable: isFirstOrFifteenth
})
</script>
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable: isFirstOrFifteenth
})
</script>
If you have a few different matchers you want to use, you can simply combine them like so:
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const isWeekend: Matcher = (date) => {
return date.dayOfWeek === 0 || date.dayOfWeek === 6
}
const isDateUnavailable: Matcher = (date) => {
return isFirstOrFifteenth(date) || isWeekend(date)
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable
})
</script>
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const isWeekend: Matcher = (date) => {
return date.dayOfWeek === 0 || date.dayOfWeek === 6
}
const isDateUnavailable: Matcher = (date) => {
return isFirstOrFifteenth(date) || isWeekend(date)
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable
})
</script>
Or if you want to get really fancy with it, you can create a helper function that takes an array of matchers which you could use throughout your app.
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const isWeekend: Matcher = (date) => {
return date.dayOfWeek === 0 || date.dayOfWeek === 6
}
const matchers = [isFirstOrFifteenth, isWeekend]
const isDateUnavailable: (...matchers: Matcher[]) => Matcher = (...matchers) => {
return (date) => {
return matchers.some((matcher) => matcher(date))
}
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable
})
</script>
<script lang="ts">
import { createDateField, melt, type Matcher } from '@melt-ui/svelte'
const isFirstOrFifteenth: Matcher = (date) => {
return date.day === 1 || date.day === 15
}
const isWeekend: Matcher = (date) => {
return date.dayOfWeek === 0 || date.dayOfWeek === 6
}
const matchers = [isFirstOrFifteenth, isWeekend]
const isDateUnavailable: (...matchers: Matcher[]) => Matcher = (...matchers) => {
return (date) => {
return matchers.some((matcher) => matcher(date))
}
}
const {
elements: { field, startSegment, endSegment, label, validation },
states: { value, segmentContents, isInvalid }
} = createDateField({
isDateUnavailable
})
</script>
When a field is marked as invalid, the isInvalid
store will be set to true
, and a data-invalid
attribute will be added to all the elements that make up the field, which you can use to style the
field however you'd like.
You'll want to use the validation
element to display a message to the user indicating why the date
is invalid. It's automatically hidden when the field is valid, and is wired up via aria attributes
to give screen readers the information they need.
<span use:melt={$label}>Availability</span>
<div use:melt={$field}>
{#each $segmentContents.start as seg, i (i)}
<div use:melt={$startSegment(seg.part)}>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div use:melt={$endSegment(seg.part)}>
{seg.value}
</div>
{/each}
</div>
<small use:melt={$validation}> Date cannot be on the 1st or 15th of the month. </small>
<span {...$label} use:label>Availability</span>
<div {...$field} use:field>
{#each $segmentContents.start as seg, i (i)}
<div {...$startSegment(seg.part)} use:startSegment>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg, i (i)}
<div {...$endSegment(seg.part)} use:endSegment>
{seg.value}
</div>
{/each}
</div>
<small {...$validation} use:validation> Date cannot be on the 1st or 15th of the month. </small>
Here's an example to get an idea of what you might do. Attempt to enter an unavailable date, and you'll see the behavior in action.
The Date Field builder also accepts minValue
and maxValue
props to set the minimum and maximum
dates a user can select.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label, validation },
states: { segmentContents }
} = createDateRangeField({
defaultValue: {
start: new CalendarDate(2023, 10, 11),
end: new CalendarDate(2023, 10, 13)
},
minValue: new CalendarDate(2023, 10, 11),
maxValue: new CalendarDate(2024, 10, 11)
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
import { CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label, validation },
states: { segmentContents }
} = createDateRangeField({
defaultValue: {
start: new CalendarDate(2023, 10, 11),
end: new CalendarDate(2023, 10, 13)
},
minValue: new CalendarDate(2023, 10, 11),
maxValue: new CalendarDate(2024, 10, 11)
})
</script>
In this example, we're limiting the selection dates to between October 11th, 2023 and October 11th, 2024.
If you increment the year of the end date to 2024, you'll see the validation message appear, as the range exceeds the maximum date.
Locale-aware Formatting
One of the coolest features of this builder is the ability to automatically format the segments and placeholder based on the locale.
Of course it's up to you to decide how you get your user's locale, but once you have it, it's as
simple as passing it as the locale
prop.
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label, validation },
states: { segmentContents }
} = createDateRangeField({
locale: 'de'
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '@melt-ui/svelte'
const {
elements: { field, startSegment, endSegment, label, validation },
states: { segmentContents }
} = createDateRangeField({
locale: 'de'
})
</script>
Here's an example showcasing a few different locales:
Notice that they all have the same defaultPlaceholder
, yet the segments are formatted differently
depending on the locale, and all it took was changing the locale
prop. Pretty cool, right?
Readonly Segments
Like the Date Field builder, Date Range Fields can be set as readonly using the readonly
prop. But
in some situations, you may want a user to be able to edit the time but not the date, or the month
but not the year. You can configure which segments are readonly for the start and end fields
separately using the readonlySegments
prop.
<script lang="ts">
import { createDateRangeField, melt } from '$lib'
import { CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultValue: {
start: new CalendarDate(2023, 10, 11),
end: new CalendarDate(2023, 10, 12)
},
readonlySegments: {
start: ['month', 'year'],
end: ['year']
}
})
</script>
<script lang="ts">
import { createDateRangeField, melt } from '$lib'
import { CalendarDate } from '@internationalized/date'
const {
elements: { field, startSegment, endSegment, label },
states: { segmentContents }
} = createDateRangeField({
defaultValue: {
start: new CalendarDate(2023, 10, 11),
end: new CalendarDate(2023, 10, 12)
},
readonlySegments: {
start: ['month', 'year'],
end: ['year']
}
})
</script>
In this example, the year
segment is readonly on both start and end fields, month
is also
readonly on start, but the day
segment is focusable and editable on both.
This could be used to ensure the end year can not be set different from the start year, using a controlled value prop, for example.
API Reference
createDateRangeField
The builder function used to create the date field component.
Props
Prop | Default | Type / Description |
defaultValue | - | DateRange | undefined The default value for the date range field. When provided the |
value | - | Writable<DateRange | undefined> A writable store than can be used to control the value of the date range field from outside the builder. Useful if you want to sync the value of the date field with another store used in your app. |
onValueChange | - | ChangeFn<DateRange | undefined> A function called when the value of the date range field changes. It receives a single argument, which is an object containing |
defaultPlaceholder | CalendarDate | DateValue The date that is used when the date range field is empty to determine what point in time the field should start at. |
placeholder | - | Writable<DateValue> A writable store that can be used to control the placeholder date from outside the builder. When this prop is provided, the |
onPlaceholderChange | - | ChangeFn<DateValue> A function called when the placeholder value changes. It receives a single argument, which is an object containing |
isDateUnavailable | - | Matcher | undefined A function that accepts a date and returns a boolean indicating whether the date is unavailable. |
minValue | - | DateValue | undefined The minimum date that can be selected. |
maxValue | - | DateValue | undefined The maximum date that can be selected. |
disabled | false | boolean Whether the date field is disabled. |
readonly | false | boolean Whether the date field is readonly. |
readonlySegments | - | { start: EditableSegmentPart[], end: EditableSegmentPart[] } The sets of segments that are readonly on the start and end fields. |
hourCycle | - | HourCycle The hour cycle to use when formatting the date. |
locale | 'en' | string The locale to use when formatting the date. |
granularity | - | 'day' | 'hour' | 'minute' | 'second' The granularity of the date range field. Defaults to |
name | - | string The name of the hidden input element. |
required | false | boolean Whether the hidden input is required. |
ids | - | DateRangeFieldIds Override the default ids used by the various elements within the date range field. |
Elements
Element | Description |
The element which contains the date segments | |
An individual segment of the start date | |
An individual segment of the end date | |
The label for the date field | |
The element containing the validation message | |
The hidden input used to submit the start value within a form | |
The hidden input used to submit the end value within a form |
States
State | Description |
value | A writable store which represents the current value of the date field. |
segmentValues | An object of writable stores containing the current values of the date segments. |
segmentContents | An object of readable stores used to dynamically render the date segments. |
segmentContentsObj | An object of readable stores containing the current values of the date segments. |
placeholder | A writable store which represents the placeholder value of the date field. |
isInvalid | A readable store which represents whether the date field is invalid. |
isDateUnavailable | A readable store which returns a function that accepts a date and returns a boolean indicating whether the date is unavailable. |
Options
Option | Description |
defaultValue | The default value for the date range field. When provided the |
onValueChange | A function called when the value of the date range field changes. It receives a single argument, which is an object containing |
defaultPlaceholder | The date that is used when the date range field is empty to determine what point in time the field should start at. |
onPlaceholderChange | A function called when the placeholder value changes. It receives a single argument, which is an object containing |
isDateUnavailable | A function that accepts a date and returns a boolean indicating whether the date is unavailable. |
minValue | The minimum date that can be selected. |
maxValue | The maximum date that can be selected. |
disabled | Whether the date field is disabled. |
readonly | Whether the date field is readonly. |
readonlySegments | The sets of segments that are readonly on the start and end fields. |
hourCycle | The hour cycle to use when formatting the date. |
locale | The locale to use when formatting the date. |
granularity | The granularity of the date range field. Defaults to |
name | The name of the hidden input element. |
required | Whether the hidden input is required. |
ids | Override the default ids used by the various elements within the date range field. |
field
The element which contains the date segments
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the date field is invalid. |
[data-disabled] | Present when the date field is disabled. |
[data-melt-datefield-field] | Present on all field elements. |
startSegment
The start segment for the date range field
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-disabled] | Present when the field is disabled. |
[data-segment] | SegmentPart |
[data-melt-datefield-segment] | Present on all segment elements. |
Custom Events
Event | Value |
m-keydown | (e: ) => void |
m-focusout | (e: ) => void |
m-click | (e: ) => void |
endSegment
The end segment for the date range field
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-disabled] | Present when the field is disabled. |
[data-segment] | SegmentPart |
[data-melt-datefield-segment] | Present on all segment elements. |
Custom Events
Event | Value |
m-keydown | (e: ) => void |
m-focusout | (e: ) => void |
m-click | (e: ) => void |
label
The label for the date field
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-melt-datefield-label] | Present on all label elements. |
validation
The element containing the validation message
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-melt-datefield-validation] | Present on all validation elements. |
startHiddenInput
The hidden input for the start date field.
Data Attributes
Data Attribute | Value |
[data-melt-datefield-hiddenInput] | Present on all hiddenInput elements. |
endHiddenInput
The hidden input for the start date field.
Data Attributes
Data Attribute | Value |
[data-melt-datefield-hiddenInput] | Present on all hiddenInput elements. |
On This Page