---
title: "MonthRangePicker"
description: "Presents a calendar view tailored for selecting month ranges."
canonical_url: "https://vinicunca.dev/akar/components/month-range-picker"
---
# MonthRangePicker

> Presents a calendar view tailored for selecting month ranges.

## Month Range Picker

`````vue [index.vue]
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
import { MonthRangePickerCell, MonthRangePickerCellTrigger, MonthRangePickerGrid, MonthRangePickerGridBody, MonthRangePickerGridRow, MonthRangePickerHeader, MonthRangePickerHeading, MonthRangePickerNext, MonthRangePickerPrev, MonthRangePickerRoot } from 'akar'
import './styles.css'

const defaultValue = {
  start: new CalendarDate(2024, 3, 1),
  end: new CalendarDate(2024, 6, 1),
}
</script>

<template>
  <div class="akar-demo akar-demo-MonthRangePicker">
    <MonthRangePickerRoot
        v-slot="{ grid }"
        :default-value="defaultValue"
        class="MonthRangePicker"
      >
        <MonthRangePickerHeader class="MonthRangePickerHeader">
          <MonthRangePickerPrev class="MonthRangePickerNavButton">
            <PIcon
              name="i-lucide-chevron-left"
              class="Icon"
            />
          </MonthRangePickerPrev>
          <MonthRangePickerHeading class="MonthRangePickerHeading" />
          <MonthRangePickerNext class="MonthRangePickerNavButton">
            <PIcon
              name="i-lucide-chevron-right"
              class="Icon"
            />
          </MonthRangePickerNext>
        </MonthRangePickerHeader>
        <div class="MonthRangePickerWrapper">
          <MonthRangePickerGrid class="MonthRangePickerGrid">
            <MonthRangePickerGridBody class="MonthRangePickerGridWrapper">
              <MonthRangePickerGridRow
                v-for="(months, index) in grid.rows"
                :key="`month-${index}`"
                class="MonthRangePickerGridRow"
              >
                <MonthRangePickerCell
                  v-for="month in months"
                  :key="month.toString()"
                  :date="month"
                  class="MonthRangePickerCell"
                >
                  <MonthRangePickerCellTrigger
                    :month="month"
                    class="MonthRangePickerCellTrigger"
                  />
                </MonthRangePickerCell>
              </MonthRangePickerGridRow>
            </MonthRangePickerGridBody>
          </MonthRangePickerGrid>
        </div>
      </MonthRangePickerRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/grass.css';

@scope (.akar-demo-MonthRangePicker) {
.Icon {
  width: 1rem;
  height: 1rem;
}

.MonthRangePicker {
  margin-top: 1.5rem;
  border-radius: 0.75rem;
  border: 1px solid #e5e5e5;
  background-color: #ffffff;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  padding: 1rem;
}

.MonthRangePickerHeader {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.MonthRangePickerNavButton {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 2rem;
  height: 2rem;
  color: #000000;
  background-color: transparent;
  cursor: pointer;
  border-radius: 0.375rem;
}

.MonthRangePickerNavButton:hover {
  background-color: #fafaf9;
}

.MonthRangePickerNavButton:focus {
  box-shadow: 0 0 0 2px #000000;
}

.MonthRangePickerHeading {
  font-size: 0.875rem;
  font-weight: 500;
  color: #000000;
}

.MonthRangePickerWrapper {
  padding-top: 1rem;
}

.MonthRangePickerGrid {
  width: 100%;
  user-select: none;
}

.MonthRangePickerGridWrapper {
  display: grid;
  gap: 0.25rem 0;
}

.MonthRangePickerGridRow {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.25rem;
}

.MonthRangePickerCell {
  position: relative;
  text-align: center;
}

.MonthRangePickerCellTrigger {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 400;
  color: #000000;
  background-color: transparent;
  outline: none;
  cursor: pointer;
  border: none;
}

.MonthRangePickerCellTrigger:hover {
  background-color: var(--grass-5);
}

.MonthRangePickerCellTrigger:focus {
  box-shadow: 0 0 0 2px #000000;
}

.MonthRangePickerCellTrigger[data-disabled] {
  color: rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

.MonthRangePickerCellTrigger[data-selected] {
  background-color: var(--grass-10);
  color: #ffffff;
  font-weight: 500;
}

.MonthRangePickerCellTrigger[data-highlighted] {
  background-color: var(--grass-5);
}

.MonthRangePickerCellTrigger[data-unavailable] {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
  pointer-events: none;
}

.MonthRangePickerCellTrigger::before {
  content: '';
  position: absolute;
  top: 0.25rem;
  width: 0.25rem;
  height: 0.25rem;
  border-radius: 9999px;
  display: none;
}

.MonthRangePickerCellTrigger[data-today]::before {
  display: block;
  background-color: var(--grass-9);
}

.MonthRangePickerCellTrigger[data-selected]::before {
  background-color: #ffffff;
}
}
```

## 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](https://react-spectrum.adobe.com/internationalized/date/index.html) 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.

```bash [pnpm]
pnpm add @internationalized/date
```

```bash [yarn]
yarn add @internationalized/date
```

```bash [npm]
npm install @internationalized/date
```

```bash [bun]
bun add @internationalized/date
```

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup>
import {
  MonthRangePickerCell,
  MonthRangePickerCellTrigger,
  MonthRangePickerGrid,
  MonthRangePickerGridBody,
  MonthRangePickerGridRow,
  MonthRangePickerHeader,
  MonthRangePickerHeading,
  MonthRangePickerNext,
  MonthRangePickerPrev,
  MonthRangePickerRoot,
} from 'akar';
</script>

<template>
  <MonthRangePickerRoot>
    <MonthRangePickerHeader>
      <MonthRangePickerPrev />
      <MonthRangePickerHeading />
      <MonthRangePickerNext />
    </MonthRangePickerHeader>
    <MonthRangePickerGrid>
      <MonthRangePickerGridBody>
        <MonthRangePickerGridRow>
          <MonthRangePickerCell>
            <MonthRangePickerCellTrigger />
          </MonthRangePickerCell>
        </MonthRangePickerGridRow>
      </MonthRangePickerGridBody>
    </MonthRangePickerGrid>
  </MonthRangePickerRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a month range picker

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `allowNonContiguousRanges` | `false` | `boolean` | When combined with `isMonthUnavailable`, determines whether non-contiguous ranges 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.<br><br>Read our [Composition](/akar/guides/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. |
| `disabled` | `false` | `boolean` | Whether or not the calendar is disabled |
| `fixedDate` |  | `"start" \| "end"` | Which part of the range should be fixed |
| `initialFocus` | `false` | `boolean` | If true, the calendar will focus the selected month on mount |
| `isMonthDisabled` |  | `Matcher` | A function that returns whether or not a month is disabled |
| `isMonthUnavailable` |  | `Matcher` | A function that returns whether or not a month is unavailable |
| `locale` |  | `string` | The locale to use for formatting dates |
| `maximumMonths` |  | `number` | The maximum number of months 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 month range of the month range picker. Can be bound as `v-model`. |
| `nextPage` |  | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the calendar. |
| `placeholder` |  | `DateValue` | The placeholder date, which is used to determine what year to display when no date is selected. |
| `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. |
| `readonly` | `false` | `boolean` | Whether or not the calendar is readonly |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `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 |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `date` | `DateValue` | The current date of the placeholder |
| `grid` | `Grid<DateValue>` | The grid of months |
| `locale` | `string` | The calendar locale |
| `modelValue` | `DateRange` | The current date range |

[MonthRangePickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerRoot.vue)

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

### Header

Contains the navigation buttons and the heading segments.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |

[MonthRangePickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerHeader.vue)

### Prev Button

Calendar navigation button. It navigates the calendar one year in the past.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/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 Root. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `disabled` | `boolean` | Current disable state |

[MonthRangePickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerPrev.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |

### Next Button

Calendar navigation button. It navigates the calendar one year in the future.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/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 Root. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `disabled` | `boolean` | Current disable state |

[MonthRangePickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerNext.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |

### Heading

Heading for displaying the current year.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `headingValue` | `string` | Current year heading |

[MonthRangePickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerHeading.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |

### Grid

Container for wrapping the month range picker grid.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |

[MonthRangePickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGrid.vue)

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

### Grid Body

Container for wrapping the grid body.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |

[MonthRangePickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGridBody.vue)

### Grid Row

Container for wrapping the grid row.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |

[MonthRangePickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGridRow.vue)

### Cell

Container for wrapping the month range picker cells.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |
| `date*` |  | `DateValue` | The date value for the cell |

[MonthRangePickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerCell.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |

### Cell Trigger

Interactable container for displaying the cell months. Clicking it selects the month.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `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.<br><br>Read our [Composition](/akar/guides/composition) guide for more details. |
| `month*` |  | `DateValue` | The date value provided to the cell trigger |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `monthValue` | `string` | Current month value (short name) |
| `disabled` | `boolean` | Current disable state |
| `selected` | `boolean` | Current selected state |
| `today` | `boolean` | Current month is today's month 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 |

[MonthRangePickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerCellTrigger.vue)

| 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 the month is the current month |
| `[data-selection-start]` | Present when the month is the start of the selection. |
| `[data-selection-end]` | Present when the month is the end of the selection. |
| `[data-highlighted]` | Present when the month is highlighted by the user as they select a range. |
| `[data-highlighted-start]` | Present when the month is the start of the range that is highlighted by the user. |
| `[data-highlighted-end]` | Present when the month is the end of the range that is highlighted by the user. |
| `[data-focused]` | Present when focused |

## Accessibility

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>Tab</kbd> | When focus moves onto the month range picker, focuses the first navigation button. |
| <kbd>Space</kbd> |  When the focus is on either `MonthRangePickerNext` or `MonthRangePickerPrev`, it navigates the calendar. Otherwise, it selects the month.  |
| <kbd>Enter</kbd> |  When the focus is on either `MonthRangePickerNext` or `MonthRangePickerPrev`, it navigates the calendar. Otherwise, it selects the month.  |
| <kbd>ArrowLeft</kbd> / <kbd>ArrowRight</kbd> / <kbd>ArrowUp</kbd> / <kbd>ArrowDown</kbd> | When the focus is on `MonthRangePickerCellTrigger`, it navigates the months, changing the year if necessary. |
| <kbd>PageUp</kbd> | When the focus is on `MonthRangePickerCellTrigger`, it navigates to the same month in the previous year. |
| <kbd>PageDown</kbd> | When the focus is on `MonthRangePickerCellTrigger`, it navigates to the same month in the next year. |
| <kbd>Escape</kbd> | Cancels the current range selection and restores the previous valid range. |

---

- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
