Studio
2

Date Range Picker

Installation

pnpm dlx @mielui/svelte add date-range-picker

Usage

Compose two Inputs with type="start" and type="end". Each Input accepts its own form name. Bind an object with start and end DateValue properties; either endpoint can be undefined while editing.

import * as DateRangePicker from '$lib/mielui/components/date-range-picker';

<DateRangePicker.Root bind:value>
  <DateRangePicker.Label>Travel dates</DateRangePicker.Label>
  <DateRangePicker.Input type="start" name="arrival" aria-label="Arrival" />
  <DateRangePicker.Input type="end" name="departure" aria-label="Departure" />
  <DateRangePicker.Trigger />
  <DateRangePicker.Content align="end">
    <DateRangePicker.Calendar />
  </DateRangePicker.Content>
</DateRangePicker.Root>

Use CalendarDate from @internationalized/date for date-only values, or parseDate for ISO date strings. Bind placeholder to control the visible month. An explicit locale and placeholder keep server and client formatting predictable. Avoid converting a date-only selection through a UTC JavaScript Date to store it; value.toString() preserves its calendar date.

Examples

Booking range

Show two months with numberOfMonths and use minDays/maxDays for booking limits. Months wrap in narrow containers.

Disabled

disabled prevents editing and calendar activation. readonly preserves navigation while preventing value changes.

Forms and reset

A named Input submits its ISO date value. Required and invalid fields block submission; focus moves to the visible date segments. Disabled fields are omitted. Reset restores the initial selection. Input also accepts form to associate it with an external form.

Composition and accessibility

Calendar exposes a children snippet with months and weekdays. Keep the default Month, or compose Grid, GridHead, GridBody, GridRow, HeadCell, Cell and Day to restyle individual regions. Month also accepts a day(date) snippet. Header, Heading, PrevButton, NextButton, MonthSelect and YearSelect can be omitted, reordered or replaced with another documented composition.

Styled parts forward native attributes and expose bind:ref for their underlying element. Arrow keys move between days, Page Up and Page Down change the visible month, and Enter or Space selects. Focus and selection are distinct. Disabled dates cannot be selected; readonly calendars remain navigable. The today indicator and unavailable strike-through provide cues beyond color.

Input exposes a children snippet with segments for custom field composition. Render each Segment with its part to preserve keyboard editing. Put name on Input for ISO-value form submission, and required or validation callbacks on Root. Use errorMessageId to connect your error message. Popup focus returns to the trigger when dismissed; motion respects reduced-motion preferences.

API reference

DateRangePicker.Root

Prop Type Default
children Snippet<[]> | undefined —
id string | undefined —
placeholder Bindable DateValue | undefined

The placeholder value of the date field. This determines the format and what date the field starts at when it is empty.

—
style string | StyleProperties | null | undefined —
disabled boolean | undefined

If true, the date field will be disabled and users will not be able to interact with it. This also disables the hidden input element if the date field is used in a form.

false
value Bindable DateRange | undefined

The value of the date picker.

—
readonly boolean | undefined

If true, the date field will be readonly, and users will not be able to edit the values of any of the individual segments.

false
required boolean | undefined

Whether or not the hidden input of the date field requires a value to be submitted.

false
ref Bindable HTMLElement | null | undefined null
onValueChange OnChangeFn<DateRange> | undefined

A callback function called when the value changes.

—
onPlaceholderChange OnChangeFn<DateValue> | undefined

A callback function called when the placeholder value changes.

—
preventDeselect boolean | undefined

Whether or not users can deselect a date once selected without selecting another date.

—
minValue DateValue | undefined

The minimum acceptable date. When provided, the date field will be marked as invalid if the user enters a date before this date.

—
maxValue DateValue | undefined

The maximum acceptable date. When provided, the date field will be marked as invalid if the user enters a date after this date.

—
pagedNavigation boolean | undefined

Applicable only when `numberOfMonths` is greater than 1.

—
weekStartsOn WeekStartsOn | undefined

The day of the week to start the calendar on, which must be a number between 0 and 6, where 0 is Sunday and 6 is Saturday.

—
weekdayFormat "long" | "short" | "narrow" | undefined

How the string representation of the weekdays provided via the `weekdays` state store should be formatted.

'short'
isDateDisabled DateMatcher | undefined

A function that returns true if the given date is disabled, which makes the date unable to be selected in the calendar.

—
isDateUnavailable DateMatcher | undefined

A function that returns true if the given date is unavailable, where if selected, the date field will be marked as invalid.

—
fixedWeeks boolean | undefined

Display 6 weeks per month, regardless the month's number of weeks. This is useful for displaying a consistent calendar, where the size of the calendar doesn't change month to month.

true
numberOfMonths number | undefined

Determines the number of months to display on the calendar simultaneously. For navigation between months, refer to the `pagedNavigation` prop.

—
calendarLabel string | undefined

This label is exclusively used for accessibility, remaining hidden from the page. It's read by screen readers when the calendar is opened. The current month and year are automatically appended to the label, so you only need to provide the base label.

—
locale string | undefined

The locale to use for formatting the date field.

'en-US'
disableDaysOutsideMonth boolean | undefined

Whether to disable the selection of days outside the current month. By default, days outside the current month are rendered to fill the calendar grid, but they are not selectable. Setting this prop to `true` will disable this behavior.

—
maxDays number | undefined

The maximum number of days that can be selected in a range.

—
monthFormat "numeric" | "long" | "short" | "narrow" | "2-digit" | ((month: number) => string) | undefined

The format of the month names in the calendar.

—
yearFormat "numeric" | "2-digit" | ((year: number) => string) | undefined

The format of the year names in the calendar.

—
open Bindable boolean | undefined

The open state of the date picker popover.

false
onOpenChange OnChangeFn<boolean> | undefined

A callback function called when the open state changes.

—
onOpenChangeComplete OnChangeFn<boolean> | undefined

A callback function called when the open state changes complete.

—
validate DateRangeValidator | undefined

A function that returns a string or array of strings as validation errors if the date is invalid, or nothing if the date is valid

—
onInvalid DateOnInvalid | undefined

A callback fired when the date field's value is invalid. Use this to display an error message to the user.

—
readonlySegments ("month" | "year" | "day" | "hour" | "minute" | "second" | "dayPeriod")[] | undefined

An array of segment names that should be readonly. If provided, only the segments not in this array will be editable.

—
hourCycle 12 | 24 | undefined

The format to use for displaying the time in the input. If using a 12 hour clock, ensure you also include the `dayPeriod` segment in your input to ensure the user can select AM/PM.

—
granularity Granularity | undefined

The granularity of the date field. This determines which segments will be includes in the segments array used to build the date field.

—
hideTimeZone boolean | undefined

Whether or not to hide the timeZoneName segment from the date field.

—
errorMessageId string | undefined

The `id` of the element which contains the error messages for the date field when the date is invalid.

—
closeOnRangeSelect boolean | undefined

Whether to close the popover when a date range is selected.

—
onStartValueChange OnChangeFn<DateValue | undefined> | undefined

A callback function called when the start value changes. This doesn't necessarily mean the `value` has updated and should be used to apply cosmetic changes to the calendar when only part of the value is changed/completed.

—
onEndValueChange OnChangeFn<DateValue | undefined> | undefined

A callback function called when the end value changes. This doesn't necessarily mean the `value` has updated and should be used to apply cosmetic changes to the calendar when only part of the value is changed/completed.

—
minDays number | undefined

The minimum number of days that can be selected in a range.

—
excludeDisabled boolean | undefined

Whether to automatically reset the range if any date within the selected range becomes disabled. When true, the entire range will be cleared if a disabled date is found between the start and end dates.

—

DateRangePicker.Content

Prop Type Default
children Snippet<[]> | undefined —
dir Direction | undefined

The text direction of the content.

—
id string | undefined —
style string | StyleProperties | null | undefined —
align "center" | "start" | "end" | undefined

The preferred alignment of the anchor to render against when open. This may change when collisions occur.

'start'
ref Bindable HTMLElement | null | undefined null
onInteractOutside InteractOutsideEventHandler | undefined

Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device.

—
interactOutsideBehavior InteractOutsideBehaviorType | undefined

Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction.

—
onFocusOutside ((event: FocusEvent) => void) | undefined

Callback fired when focus leaves the dismissible layer.

—
preventScroll boolean | undefined

Whether to prevent scrolling the body when the content is open. Whether to prevent body scrolling when the content is open.

—
onEscapeKeydown ((e: KeyboardEvent) => void) | undefined

Callback fired when escape is pressed.

—
escapeKeydownBehavior EscapeBehaviorType | undefined

Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press.

—
side "left" | "right" | "top" | "bottom" | undefined

The preferred side of the anchor to render against when open. Will be reversed when collisions occur.

—
sideOffset number | undefined

The distance in pixels from the anchor to the floating element.

6
alignOffset number | undefined

An offset in pixels from the "start" or "end" alignment options.

—
arrowPadding number | undefined

This describes the padding between the arrow and the edges of the floating element. If your floating element has border-radius, this will prevent it from overflowing the corners.

—
avoidCollisions boolean | undefined

When `true`, overrides the `side` and `align` options to prevent collisions with the boundary edges.

—
collisionBoundary Arrayable<Boundary> | undefined

A boundary element or array of elements to check for collisions against.

—
collisionPadding number | Partial<Record<"left" | "right" | "top" | "bottom", number>> | undefined

The amount in pixels of virtual padding around the viewport edges to check for overflow which will cause a collision.

8
sticky "partial" | "always" | undefined —
hideWhenDetached boolean | undefined —
updatePositionStrategy "always" | "optimized" | undefined

"optimized" will only update the position when necessary, while "always" will update the position on each animation frame, which is useful if the floating content is following something like a mouse cursor.

—
strategy "absolute" | "fixed" | undefined

The positioning strategy to use for the floating element.

—
customAnchor string | HTMLElement | Measurable | null | undefined

Use an element other than the trigger to anchor the content to. If provided, the content will be anchored to the provided element instead of the trigger.

—
preventOverflowTextSelection boolean | undefined

Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer.

—
onOpenAutoFocus EventCallback | undefined

Event handler called when auto-focusing on open. Can be prevented.

—
onCloseAutoFocus EventCallback | undefined

Event handler called when auto-focusing on close. Can be prevented.

—
trapFocus boolean | undefined

Whether focus is trapped within the focus scope.

—
surface "solid" | "glass" | undefined —
portal boolean | undefined true

DateRangePicker.Segment

Prop Type Default
part Required "month" | "year" | "day" | "hour" | "minute" | "second" | "dayPeriod" | "timeZoneName" | "literal" —
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Cell

Prop Type Default
date Required CalendarDate | CalendarDateTime | ZonedDateTime

The date value of the cell.

—
month Required CalendarDate | CalendarDateTime | ZonedDateTime

The month DateValue that this cell is being rendered in.

—
child Snippet<[CalendarCellSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarCellSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Day

Prop Type Default
child Snippet<[CalendarDaySnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarDaySnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Grid

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.GridBody

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.GridHead

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.GridRow

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.HeadCell

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Header

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Heading

Prop Type Default
child Snippet<[CalendarHeadingSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarHeadingSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Month

Prop Type Default
class string | undefined —
month Required { value: DateValue; weeks: DateValue[][]; dates: DateValue[]; } —
weekdays Required string[] —
locale string | undefined 'en-US'
showHeading boolean | undefined false
day Snippet<[date: DateValue]> | undefined —

DateRangePicker.MonthSelect

Prop Type Default
monthFormat "numeric" | "long" | "short" | "narrow" | "2-digit" | ((month: number) => string) | undefined

How the month names should be formatted in the select options.

—
months number[] | undefined

An array of month numbers (1-12) to display in the select. This allows for flexible month selection, such as showing only specific months or seasons.

—
child Snippet<[CalendarMonthSelectSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarMonthSelectSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.NextButton

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.PrevButton

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.YearSelect

Prop Type Default
yearFormat "numeric" | "2-digit" | ((year: number) => string) | undefined

How the year should be formatted in the select options.

—
years number[] | undefined

An array of years to display in the select. This allows for complete control over which years appear, such as showing only years with data or excluding certain periods.

—
child Snippet<[CalendarYearSelectSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarYearSelectSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Calendar

Prop Type Default
children Snippet<[CalendarRootSnippetProps]> | undefined —
id string | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null

DateRangePicker.Input

Prop Type Default
children Snippet<[DateRangeFieldInputSnippetProps]> | undefined —
id string | undefined —
style string | StyleProperties | null | undefined —
type Required "start" | "end"

Whether this input represents the start or end of the date range.

—
name string | undefined

The name to use for the hidden input element associated with this input used for form submission.

—
ref Bindable HTMLElement | null | undefined null
form string | undefined —

DateRangePicker.Label

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

DateRangePicker.Trigger

Prop Type Default
children Snippet<[]> | undefined —
id string | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
openOnHover boolean | undefined

Whether the popover should open when the trigger is hovered.

—
openDelay number | undefined

How long to wait before opening the popover on hover (ms). Only applies when `openOnHover` is `true`.

—
closeDelay number | undefined

How long to wait before closing the popover after hover ends (ms). Only applies when `openOnHover` is `true`.

—