Dates

Calendar

A composable calendar for choosing a single date.

Installation

pnpm dlx @mielui/svelte add calendar

Usage

Bind a DateValue, or undefined for no selection. The default view renders Header, PrevButton, Heading, NextButton and Month, the same parts you can compose yourself. Use Range Calendar for a start and end date.

<script lang="ts">
    import type { DateValue } from '@internationalized/date';
    import * as Calendar from '@mielui/svelte/components/calendar';

    let value = $state<DateValue | undefined>();
</script>

<Calendar.Root bind:value calendarLabel="Meeting date" />

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

Bound value

The line under the calendar prints the bound date each time the selection changes.

Constraints

Restrict the selectable dates with minValue, maxValue and isDateDisabled. Unavailable dates remain focusable and indicate invalid selections; disabled dates cannot be selected.

Composition and accessibility

Root 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:element 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.

The standalone calendar does not create a form field. Add a named hidden input when it participates in a form, or use the corresponding date picker for editable fields and form serialization. The calendar grid stays still during navigation; only state feedback changes.

Selection events

onValueChange runs with the new date each time the selection changes. Clicking the selected date again clears it, and the callback then receives undefined. Set preventDeselect to keep a date selected until another one replaces it.

The calendar also tracks a placeholder, the date that decides which month is on screen. onPlaceholderChange runs when that moves, for example when someone pages to the next month. initialFocus moves keyboard focus to the selected day, or today, as soon as the calendar mounts.

Weeks and months

weekStartsOn sets the first column, from 0 for Sunday to 6 for Saturday, and falls back to the locale. weekdayFormat picks narrow, short or long weekday names. fixedWeeks is on by default and always draws six rows so the height never jumps between months. Turn it off to draw only the weeks a month needs. Days from the neighbouring months fill the grid and cannot be selected. Set disableDaysOutsideMonth={false} to make them selectable.

numberOfMonths shows several months side by side. With more than one, the arrows move a single month at a time unless you set pagedNavigation, which jumps by the number of months shown.

Unavailable dates and formats

isDateDisabled removes a date from play: it cannot be focused or picked. isDateUnavailable is softer. An unavailable date is struck through and can still be focused, so keyboard users can read why it is off limits, and picking it marks the value invalid.

monthFormat and yearFormat on Root control how the heading and the selects name months and years. Each takes an Intl style such as short or 2-digit, or a function that receives the number and returns the text. MonthSelect and YearSelect take the same two props to override the format for their own options, and YearSelect takes years, the exact list of years to offer.

When you compose the calendar yourself, every part except Root and Month accepts child, a snippet that receives the part's props so you can render your own element with them, and style for inline styles. Month takes showHeading to print the month name above its grid, which Root turns on by itself when it shows more than one month.

API reference

Calendar.Root

  • children
    Snippet<[CalendarRootSnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • placeholder Bindable
    DateValue

    The placeholder date, used to control the view of the calendar when no value is present.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • disabled
    boolean

    Whether or not the calendar is disabled.

  • value Bindable
    DateValue

    The value of the selected date in the calendar.

  • readonly
    boolean

    Whether the calendar is readonly. When true, the user will be able to focus and navigate the calendar, but will not be able to select dates.

  • onValueChange
    OnChangeFn<DateValue | undefined>

    A callback function called when the value changes.

  • onPlaceholderChange
    OnChangeFn<DateValue>

    A callback function called when the placeholder value changes.

  • preventDeselect
    boolean

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

  • minValue
    DateValue

    The minimum date that can be selected in the calendar.

  • maxValue
    DateValue

    The maximum date that can be selected in the calendar.

  • pagedNavigation
    boolean

    Applicable only when numberOfMonths is greater than 1.

  • weekStartsOn
    WeekStartsOn

    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" | "narrow" | "short"

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

    Default 'short'

  • isDateDisabled
    DateMatcher

    A function that receives a date and returns true or false to indicate whether the date is disabled.

  • isDateUnavailable
    DateMatcher

    Dates matching the provided matchers are marked as "unavailable." Unlike disabled dates, users can still focus and select unavailable dates. However, selecting an unavailable date renders the date picker as invalid.

  • fixedWeeks
    boolean

    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.

    Default true

  • numberOfMonths
    number

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

  • calendarLabel
    string

    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

    The default locale setting.

    Default 'en-US'

  • initialFocus
    boolean

    If true, the calendar will focus the selected day, today, or the first day of the month in that order depending on what is visible when the calendar is mounted.

  • disableDaysOutsideMonth
    boolean

    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.

    Default true

  • maxDays
    number

    The maximum number of days that can be selected in multiple mode. When set, users cannot select more dates than this number.

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

    The format of the month names in the calendar.

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

    The format of the year names in the calendar.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Cell

  • children
    Snippet<[CalendarCellSnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • 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>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Day

  • children
    Snippet<[CalendarDaySnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[CalendarDaySnippetProps & { props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Grid

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.GridBody

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.GridHead

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.GridRow

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.HeadCell

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Header

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Heading

  • children
    Snippet<[CalendarHeadingSnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[CalendarHeadingSnippetProps & { props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.Month

  • class
    string

    Classes added to the element.

  • month Required
    { value: DateValue; weeks: DateValue[][]; dates: DateValue[]; }

    Month data from the Root snippet.

  • weekdays Required
    string[]

    Weekday names from the Root snippet.

  • locale
    string

    BCP 47 locale used for names and number formats.

    Default 'en-US'

  • showHeading
    boolean

    Shows the month name above the grid, for layouts with several months.

    Default false

  • day
    Snippet<[date: DateValue]>

    Custom content for each day cell.

Calendar.MonthSelect

  • children
    Snippet<[CalendarMonthSelectSnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[CalendarMonthSelectSnippetProps & { props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

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

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

  • months
    number[]

    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.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.NextButton

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.PrevButton

  • children
    Snippet<[]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[{ props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null

Calendar.YearSelect

  • children
    Snippet<[CalendarYearSelectSnippetProps]>

    Content rendered inside.

  • id
    string

    Id of the element.

  • style
    string | StyleProperties | null

    Inline styles for the element.

  • child
    Snippet<[CalendarYearSelectSnippetProps & { props: Record<string, unknown>; }]>

    Renders your own element in place of the default one. Spread the given props onto it.

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

    How the year should be formatted in the select options.

  • years
    number[]

    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.

  • element Bindable
    HTMLElement | null

    Bindable reference to the DOM element.

    Default null