Docs
Multiple months
Multiple months
Compose your calendar to show multiple months at once.
You can display multiple months at once by composing multiple CalendarContent
together.
Here is an example of a calendar showing two months at once:
January 2024
Mo | Tu | We | Th | Fr | Sa | Su |
---|---|---|---|---|---|---|
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 |
February 2024
Mo | Tu | We | Th | Fr | Sa | Su |
---|---|---|---|---|---|---|
29 | 30 | 31 | 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 | 1 | 2 | 3 |
Set up the calendar
First, you need to add a Calendar
component:
import { Calendar } from '@bryanberger/datepicker';
const MultipleMonthsCalendar = () => {
const today = new Date();
return (
<Calendar
className="rounded-md border p-3 !flex-row gap-4"
defaultSelected={ today }
weekStartDay="monday"
showOutsideDates
>
</Calendar>
);
};
Divide the calendar
Then, divide the Calendar
with div
elements and add a Header
and a Content
component to each of them:
import { Calendar } from '@bryanberger/datepicker';
const MultipleMonthsCalendar = () => {
const today = new Date();
return (
<Calendar
className="rounded-md border p-3 !flex-row gap-4"
defaultSelected={ today }
weekStartDay="monday"
showOutsideDates
>
<div>
<Calendar.Header>
</Calendar.Header>
<Calendar.Content>
</Calendar.Content>
</div>
<div>
<Calendar.Header>
</Calendar.Header>
<Calendar.Content>
</Calendar.Content>
</div>
</Calendar>
);
};
Set up headers
Add a Title
component and pagination buttons to each Header
:
import { Calendar } from '@bryanberger/datepicker';
import { ChevronLeft, ChevronRight } from 'lucide-react';
const MultipleMonthsCalendar = () => {
const today = new Date();
return (
<Calendar
className="rounded-md border p-3 !flex-row gap-4"
defaultSelected={ today }
weekStartDay="monday"
showOutsideDates
>
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title className="text-sm font-medium" />
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1"
direction="previous"
>
<ChevronLeft className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
</Calendar.Content>
</div>
<div>
<Calendar.Header>
<Calendar.Title className="text-sm font-medium" />
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1"
direction="next"
>
<ChevronRight className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
</Calendar.Content>
</div>
</Calendar>
);
};
Setup grids
Add a Head
and a Grid
component to each calendar Content
:
import { Calendar } from '@bryanberger/datepicker';
import { ChevronLeft, ChevronRight } from 'lucide-react';
const MultipleMonthsCalendar = () => {
const today = new Date();
return (
<Calendar
className="rounded-md border p-3 !flex-row gap-4"
defaultSelected={ today }
weekStartDay="monday"
showOutsideDates
>
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title className="text-sm font-medium" />
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1"
direction="previous"
>
<ChevronLeft className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
/>
</Calendar.Content>
</div>
<div>
<Calendar.Header>
<Calendar.Title className="text-sm font-medium" />
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1"
direction="next"
>
<ChevronRight className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
/>
</Calendar.Content>
</div>
</Calendar>
);
};
Set up months
You choose which months to show by using the monthIndex
prop on the Title
and Grid
components. It will link the Title
and Grid
together.
For the first block:
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title
className="text-sm font-medium"
monthIndex={ 0 }
/>
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1"
direction="previous"
>
<ChevronLeft className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
monthIndex={ 0 }
/>
</Calendar.Content>
</div>
For the second block:
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title
className="text-sm font-medium"
monthIndex={ 1 }
/>
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1"
direction="previous"
>
<ChevronLeft className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
monthIndex={ 1 }
/>
</Calendar.Content>
</div>
Final result
import { Calendar } from '@bryanberger/datepicker';
import { ChevronLeft, ChevronRight } from 'lucide-react';
const MultipleMonthsCalendar = () => {
return (
<Calendar
className="rounded-md border p-3 !flex-row gap-4"
defaultSelected={ new Date() }
weekStartDay="monday"
showOutsideDates
>
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title className="text-sm font-medium" />
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1"
direction="previous"
>
<ChevronLeft className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
monthIndex={ 0 }
/>
</Calendar.Content>
</div>
<div>
<Calendar.Header className="relative w-full">
<Calendar.Title
className="text-sm font-medium"
monthIndex={ 1 }
/>
<div className="space-x-1 flex items-center">
<Calendar.NavButton
className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input hover:bg-accent hover:text-accent-foreground h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1"
direction="next"
>
<ChevronRight className="h-4 w-4" />
</Calendar.NavButton>
</div>
</Calendar.Header>
<Calendar.Content>
<Calendar.Head />
<Calendar.Grid
classNames={ { day: 'h-9 w-9 text-center text-sm p-0 relative data-[is-selected=false]:bg-accent/50 data-[is-selected=true]:bg-accent data-[is-first=true]:rounded-l-md data-[is-last=true]:rounded-r-md focus-within:relative focus-within:z-20' } }
monthIndex={ 1 }
/>
</Calendar.Content>
</div>
</Calendar>
);
};
export default MultipleMonthsCalendar;