RangeCalendar

GitHubnpm
Presents a calendar view tailored for selecting date ranges.

Range Calendar

Alpha
Event Date, October 2026
October 2026
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
<script setup lang="ts">
import type { RangeCalendarRootProps } from 'akar';
import { RangeCalendarCell, RangeCalendarCellTrigger, RangeCalendarGrid, RangeCalendarGridBody, RangeCalendarGridHead, RangeCalendarGridRow, RangeCalendarHeadCell, RangeCalendarHeader, RangeCalendarHeading, RangeCalendarNext, RangeCalendarPrev, RangeCalendarRoot } from 'akar';

import './styles.css';

const isDateUnavailable: RangeCalendarRootProps['isDateUnavailable'] = (date) => {
  return date.day === 17 || date.day === 18;
};
</script>

<template>
  <div class="akar-demo akar-demo-RangeCalendar">
    <RangeCalendarRoot
      v-slot="{ weekDays, grid }"
      :is-date-unavailable="isDateUnavailable"
      class="Calendar"
      fixed-weeks
    >
      <RangeCalendarHeader class="flex items-center justify-between">
        <RangeCalendarPrev
          class="CalendarNavButton"
        >
          <PIcon
            name="i-lucide-chevron-left"
            class="Icon"
          />
        </RangeCalendarPrev>
        <RangeCalendarHeading class="CalendarHeading" />
        <RangeCalendarNext
          class="CalendarNavButton"
        >
          <PIcon
            name="i-lucide-chevron-right"
            class="Icon"
          />
        </RangeCalendarNext>
      </RangeCalendarHeader>
      <div
        class="CalendarWrapper"
      >
        <RangeCalendarGrid
          v-for="month in grid"
          :key="month.value.toString()"
          class="CalendarGrid"
        >
          <RangeCalendarGridHead>
            <RangeCalendarGridRow class="CalendarGridRow">
              <RangeCalendarHeadCell
                v-for="day in weekDays"
                :key="day"
                class="CalendarHeadCell"
              >
                {{ day }}
              </RangeCalendarHeadCell>
            </RangeCalendarGridRow>
          </RangeCalendarGridHead>
          <RangeCalendarGridBody class="grid">
            <RangeCalendarGridRow
              v-for="(weekDates, index) in month.rows"
              :key="`weekDate-${index}`"
              class="CalendarGridRow"
            >
              <RangeCalendarCell
                v-for="weekDate in weekDates"
                :key="weekDate.toString()"
                :date="weekDate"
                class="CalendarCell"
              >
                <RangeCalendarCellTrigger
                  :day="weekDate"
                  :month="month.value"
                  class="CalendarCellTrigger"
                />
              </RangeCalendarCell>
            </RangeCalendarGridRow>
          </RangeCalendarGridBody>
        </RangeCalendarGrid>
      </div>
    </RangeCalendarRoot>
  </div>
</template>

Features

  • Full keyboard navigation
  • Can be controlled or uncontrolled
  • Focus is fully managed
  • Localization support
  • Highly composable

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.

pnpm add @internationalized/date

Install the component from your command line.

pnpm add akar

Anatomy

Import all parts and piece them together.

<script setup>
import {
  RangeCalendarCell,
  RangeCalendarCellTrigger,
  RangeCalendarGrid,
  RangeCalendarGridBody,
  RangeCalendarGridHead,
  RangeCalendarGridRow,
  RangeCalendarHeadCell,
  RangeCalendarHeader,
  RangeCalendarHeading,
  RangeCalendarNext,
  RangeCalendarPrev,
  RangeCalendarRoot,
} from 'akar';
</script>

<template>
  <RangeCalendarRoot>
    <RangeCalendarHeader>
      <RangeCalendarPrev />
      <RangeCalendarHeading />
      <RangeCalendarNext />
    </RangeCalendarHeader>
    <RangeCalendarGrid>
      <RangeCalendarGridHead>
        <RangeCalendarGridRow>
          <RangeCalendarHeadCell />
        </RangeCalendarGridRow>
      </RangeCalendarGridHead>
      <RangeCalendarGridBody>
        <RangeCalendarGridRow>
          <RangeCalendarCell>
            <RangeCalendarCellTrigger />
          </RangeCalendarCell>
        </RangeCalendarGridRow>
      </RangeCalendarGridBody>
    </RangeCalendarGrid>
  </RangeCalendarRoot>
</template>

API Reference

Root

Contains all the parts of a calendar

PropDefaultType
allowNonContiguousRanges
false
boolean

When combined with isDateUnavailable, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected.

as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

calendarLabel
string

The accessible label for the calendar

defaultPlaceholder
DateValue

The default placeholder date

defaultValue
{ start: undefined, end: undefined }
DateRange

The default value for the calendar

dir
"ltr" | "rtl"

The reading direction of the calendar when applicable.

If omitted, inherits globally from ConfigProvider or assumes LTR (left-to-right) reading mode.

disabled
false
boolean

Whether or not the calendar is disabled

disableDaysOutsideCurrentView
false
boolean

Whether or not to disable days outside the current view.

fixedDate
"start" | "end"

Which part of the range should be fixed

fixedWeeks
false
boolean

Whether or not to always display 6 weeks in the calendar

initialFocus
false
boolean

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

isDateDisabled
Matcher

A function that returns whether or not a date is disabled

isDateHighlightable
Matcher

A function that returns whether or not a date is hightable

isDateUnavailable
Matcher

A function that returns whether or not a date is unavailable

locale
string

The locale to use for formatting dates

maximumDays
number

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

maxValue
DateValue

The maximum date that can be selected

minValue
DateValue

The minimum date that can be selected

modelValue
DateRange | null

The controlled selected date range of the calendar. Can be bound as v-model.

nextPage
((placeholder: DateValue) => DateValue)

A function that returns the next page of the calendar. It receives the current placeholder as an argument inside the component.

numberOfMonths
1
number

The number of months to display at once

pagedNavigation
false
boolean

This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month

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 programmatically control the calendar view

preventDeselect
false
boolean

Whether or not to prevent the user from deselecting a date without selecting another date first

prevPage
((placeholder: DateValue) => DateValue)

A function that returns the previous page of the calendar. It receives the current placeholder as an argument inside the component.

readonly
false
boolean

Whether or not the calendar is readonly

weekdayFormat
"narrow"
"narrow" | "short" | "long"

The format to use for the weekday strings provided via the weekdays slot prop

weekStartsOn
0 | 1 | 2 | 3 | 4 | 5 | 6

The day of the week to start the calendar on

EventPayload
update:modelValue
date: DateRange

Event handler called whenever the model value changes

update:placeholder
date: DateValue

Event handler called whenever the placeholder value changes

update:startValue
date: DateValue

Event handler called whenever the start value changes

update:validModelValue
date: DateRange

Event handler called whenever there is a new validModel

Slot (default)Payload
date
DateValue

The current date of the placeholder

grid
Grid<DateValue>[]

The grid of dates

weekDays
string[]

The days of the week

weekStartsOn
0 | 1 | 2 | 3 | 4 | 5 | 6

The start of the week

locale
string

The calendar locale

fixedWeeks
boolean

Whether or not to always display 6 weeks in the calendar

modelValue
DateRange

The current date range

RangeCalendarRoot.vue source

Data attribute Value
[data-readonly]
Present when readonly
[data-disabled]
Present when disabled
[data-invalid]
Present when invalid

Contains the navigation buttons and the heading segments.

PropDefaultType
as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarHeader.vue source

Prev Button

Calendar navigation button. It navigates the calendar one month/year/decade in the past based on the current calendar view.

Data attribute Value
[data-disabled]
Present when disabled
PropDefaultType
as
"button"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

prevPage
((placeholder: DateValue) => DateValue)

The function to be used for the prev page. Overwrites the prevPage function set on the RangeCalendarRoot.

Slot (default)Payload
disabled
boolean

Current disable state

RangeCalendarPrev.vue source

Next Button

Calendar navigation button. It navigates the calendar one month/year/decade in the future based on the current calendar view.

PropDefaultType
as
"button"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

nextPage
((placeholder: DateValue) => DateValue)

The function to be used for the next page. Overwrites the nextPage function set on the RangeCalendarRoot.

Slot (default)Payload
disabled
boolean

Current disable state

RangeCalendarNext.vue source

Data attribute Value
[data-disabled]
Present when disabled

Heading

Heading for displaying the current month and year.

PropDefaultType
as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

Slot (default)Payload
headingValue
string

Current month and year

RangeCalendarHeading.vue source

Data attribute Value
[data-disabled]
Present when disabled

Grid

Container for wrapping the calendar grid.

PropDefaultType
as
"table"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarGrid.vue source

Data attribute Value
[data-readonly]
Present when readonly
[data-disabled]
Present when disabled

Grid Head

Container for wrapping the grid head.

PropDefaultType
as
"thead"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarGridHead.vue source

Grid Body

Container for wrapping the grid body.

PropDefaultType
as
"tbody"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarGridBody.vue source

Grid Row

Container for wrapping the grid row.

PropDefaultType
as
"tr"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarGridRow.vue source

Head Cell

Container for wrapping the head cell. Used for displaying the week days.

PropDefaultType
as
"th"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

RangeCalendarHeadCell.vue source

Cell

Container for wrapping the calendar cells.

PropDefaultType
as
"td"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

date*
DateValue

RangeCalendarCell.vue source

Data attribute Value
[data-disabled]
Present when disabled

Cell Trigger

Interactable container for displaying the cell dates. Clicking it selects the date.

PropDefaultType
as
"div"
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

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.

day*
DateValue
month*
DateValue
Slot (default)Payload
dayValue
string

Current day

disabled
boolean

Current disable state

selected
boolean

Current selected state

today
boolean

Current today state

outsideView
boolean

Current outside view state

outsideVisibleView
boolean

Current outside visible view state

unavailable
boolean

Current unavailable state

highlighted
boolean

Current highlighted state

highlightedStart
boolean

Current highlighted start state

highlightedEnd
boolean

Current highlighted end state

selectionStart
boolean

Current selection start state

selectionEnd
boolean

Current selection end state

RangeCalendarCellTrigger.vue source

Data attribute Value
[data-selected]
Present when selected
[data-value]
The ISO string value of the date.
[data-disabled]
Present when disabled
[data-unavailable]
Present when unavailable
[data-today]
Present when today
[data-outside-view]
Present when the date is outside the current month it is displayed in.
[data-outside-visible-view]
Present when the date is outside the months that are visible on the calendar.
[data-selection-start]
Present when the date is the start of the selection.
[data-selection-end]
Present when the date is the end of the selection.
[data-highlighted]
Present when the date is highlighted by the user as they select a range.
[data-highlighted-start]
Present when the date is the start of the range that is highlighted by the user.
[data-highlighted-end]
Present when the date is the end of the range that is highlighted by the user.
[data-focused]
Present when focused

Accessibility

Keyboard Interactions

Key Description
Tab
When focus moves onto the calendar, focuses the first navigation button.
Space
When the focus is on either RangeCalendarNext or RangeCalendarPrev, it navigates the calendar. Otherwise, it selects the date.
Enter
When the focus is on either RangeCalendarNext or RangeCalendarPrev, it navigates the calendar. Otherwise, it selects the date.
ArrowLeft/ArrowRight/ArrowUp/ArrowDown
When the focus is on RangeCalendarCellTrigger, it navigates the dates, changing the month/year/decade if necessary.
Home
When the focus is on RangeCalendarCellTrigger, it moves focus to the first day of the current week.
End
When the focus is on RangeCalendarCellTrigger, it moves focus to the last day of the current week.
PageUp
When the focus is on RangeCalendarCellTrigger, it moves to the previous month while preserving the day of the month when possible, or clamps to the last day of the month.
PageDown
When the focus is on RangeCalendarCellTrigger, it moves to the next month while preserving the day of the month when possible, or clamps to the last day of the month.
Shift+PageUp
When the focus is on RangeCalendarCellTrigger, it moves to the previous year while preserving the month and day when possible, or clamps to the last day of the month.
Shift+PageDown
When the focus is on RangeCalendarCellTrigger, it moves to the next year while preserving the month and day when possible, or clamps to the last day of the month.