A simple and accessible React Calendar & Date Picker component that allows users to select dates. The component supports single date selection by default and can be configured for multi-date selection.
Click Demo
Click LIBRARY
To install the package, you can use npm:
npm install react-multi-date-picker-calendar
Here's how you can use the Calendar & Date Picker component in your React application:
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
// Handle the selected dates
console.log("Selected Dates:", dates);
};
return (
<div>
<h1>My App</h1>
<Calendar
multiSelect={true}
// dates={[new Date("2023-07-18T05:45:48.005Z")]}
onChange={handleDateChange} />
</div>
);
};
export default App;
A versatile date picker React component that supports various selection modes and features.
The Calendar
component accepts the following props:
Prop | Type | Default | Description |
---|---|---|---|
multiSelect |
boolean | false |
Enable multi-date selection. |
dates |
Date[] | [] |
An array of pre-selected dates. |
label |
string | - | Label for the date picker input. |
id |
string | Auto-generated | ID for the date picker input. |
readonly |
boolean | true |
Whether the input field is readonly. |
isDisabled |
boolean | false |
Whether the date picker is disabled. |
onChange |
function | - | Callback function when selected dates change. |
minDate |
Date | - | Minimum selectable date. |
maxDate |
Date | - | Maximum selectable date. |
disabledDates |
Date[] | [] |
An array of disabled dates. |
selectsRange |
boolean | false |
Enable date range selection. |
PrevIcon |
React.ReactNode | - | Custom icon for the previous button. |
NextIcon |
React.ReactNode | - | Custom icon for the next button. |
showMonth |
boolean | false |
Show month dropdown for navigation. |
showYear |
boolean | false |
Show year dropdown for navigation. |
minYear |
number | 1970 |
Minimum year in the year dropdown. |
maxYear |
number | 2025 |
Maximum year in the year dropdown. |
appointments |
Appointment[] | [] |
An array of appointments to display with status. |
showSelectedDatesList |
boolean | false |
Show a list of selected dates. |
showDatePicker |
boolean | false |
Show the date picker input. |
tooltipVisible |
boolean | false |
Show the tooltip. |
Property | Type | Description |
---|---|---|
date |
Date | The date of the appointment. |
status |
string | The status of the appointment (e.g., 'Missed', 'Cancelled', 'Incomplete', 'Completed', etc.). |
id |
string | (Optional) Unique ID for the appointment. |
time |
string | (Optional) The time of the appointment. |
title |
string | (Optional) The title of the appointment. |
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar onChange={handleDateChange} />;
};
export default App;
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar multiSelect onChange={handleDateChange} />;
};
export default App;
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar selectsRange onChange={handleDateChange} />;
};
export default App;
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const disabledDates: Date[] = [
new Date("2023-07-12"), // Example: Disable July 5th, 2023
new Date("2023-07-16"),
new Date("2023-07-18"),
new Date("2023-07-20"),
new Date("2023-07-22"),
new Date("2023-07-25")
// Add more Date objects as needed for other disabled dates
];
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar disabledDates={disabledDates} onChange={handleDateChange} />;
};
export default App;
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar
disabledDates={disabledDates}
onChange={handleDateChange}
minDate={new Date()}
maxDate={new Date("2024-07-25")} />;
};
export default App;
import React from "react";
import Calendar from "react-multi-date-picker-calendar";
const App = () => {
const handleDateChange = (dates) => {
console.log("Selected Dates:", dates);
};
return <Calendar
multiSelect={true}
showSelectedDatesList
onChange={handleDateChange}
/>;
};
export default App;
import React from "react";
import Calendar, {
logSelectedDatesAppointments,
Appointment
} from "react-multi-date-picker-calendar";
const App = () => {
const appointments: Appointment[] = [
{
date: new Date('2023-08-10'),
status: 'Completed',
id: '123',
time: '10:00 AM',
title: 'Meeting with Client A',
},
{
date: new Date('2023-08-10'),
status: 'Completed',
id: '456',
time: '2:30 PM',
title: 'Meeting with Client B',
},
{
date: new Date('2023-08-10'),
status: 'Completed',
id: '457',
time: '2:30 PM',
title: 'Meeting with Client B',
},
{
date: new Date('2023-08-10'),
status: 'incomplete',
},
{
date: new Date('2023-08-11'),
status: 'completed',
},
{
date: new Date('2023-08-11'),
status: 'Cancelled',
},
{
date: new Date('2023-08-13'),
status: 'Missed',
},
{
date: new Date('2023-08-13'),
status: 'incomplete',
},
{
date: new Date('2023-08-15'),
status: 'Cancelled',
},
{
date: new Date('2023-08-15'),
status: 'Missed',
},
// Add more appointments as needed...
];
// Define the handleSelectedDatesChange function (same as before)
const handleSelectedDatesChange = (selectedDates: Date[]) => {
const selectedAppointments = logSelectedDatesAppointments(
selectedDates,
appointments
);
console.log("Selected Dates:", selectedDates);
console.log("Selected Dates Appointments:", selectedAppointments);
// Add any other logic you want to perform when selected dates change
};
return <Calendar
onChange={handleSelectedDatesChange}
multiSelect={true}
PrevIcon="<<"
NextIcon=">>"
showMonth={true}
showYear={true}
appointments={appointments}
/>;
};
export default App;
const handleSelectedDatesChange = (selectedDates: Date[]) => {
const selectedAppointments = logSelectedDatesAppointments(
selectedDates,
appointments
);
console.log('Selected Dates Appointments:', selectedAppointments);
};
You can customize the appearance and behavior of the calendar component by passing different props. Additionally, you can style the component using CSS.
.calendar-section {
position: relative;
display: inline-block;
}
.calendar-container.open-calendar-popup {
position: absolute;
right: 0;
left: 0;
width: max-content;
z-index: 99999;
}
.calendar-container.close-calendar-popup {
display: none;
}
.calendar-container.open-calendar-popup.calendar-top {
bottom: calc(
100% + 10px
); /* Adjust the value as needed to position the calendar */
}
.calendar-container.open-calendar-popup.calendar-bottom {
top: calc(
100% + 10px
); /* Adjust the value as needed to position the calendar */
}
.calendar-container {
min-height: 320px;
font-family: Arial, sans-serif;
display: inline-flex;
background-color: #fff;
border: 1px solid #e0e0e0;
}
.calendar-input-group {
display: block;
text-align: left;
}
.calendar-input-group label {
margin-bottom: 8px;
display: inline-block;
}
.input-container {
display: flex;
align-items: center;
position: relative;
}
.calendar-input {
width: 100%;
min-height: 35px;
}
.icon-container {
display: inline-block;
width: 24px; /* Adjust dimensions as needed */
height: 24px;
position: absolute;
top: 50%;
right: 5px; /* Adjust as needed */
transform: translateY(-50%);
pointer-events: none;
}
.calendar-section {
width: 300px;
margin: 0 auto;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
background-color: #f0f0f0;
min-height: 56px;
}
.calendar-btn {
background-color: transparent;
border: none;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
.calendar-month {
margin: 0;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 1px;
}
.calendar-day {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 40px;
background-color: #fff;
border: 1px solid #e0e0e0;
cursor: pointer;
}
.calendar-day.empty {
background-color: #f0f0f0;
cursor: default;
}
.calendar-day.today {
background-color: #e0e0e0;
font-weight: bold;
}
.calendar-day:focus {
outline: 2px solid #007bff;
}
.calendar-day.selected {
background-color: #007bff;
color: #fff;
}
.calendar-day.selected:hover {
background-color: #0069d9;
}
.calendar-weekdays {
justify-content: space-between;
background-color: #f0f0f0;
padding: 8px 0;
font-weight: bold;
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 1px;
}
.calendar-weekday {
display: flex;
justify-content: center;
align-items: center;
height: 25px;
background-color: #f0f0f0;
}
/* CSS */
/* Styles for the dropdown container */
.calendar-dropdown-container {
position: relative;
display: inline-block;
margin: 0 5px;
}
/* Styles for the dropdown button */
.calendar-month-button {
min-width: 100px;
padding: 5px 5px 5px 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.monthDropdown-close {
display: none;
}
.yearDropdown-close {
display: none;
}
/* Styles for the dropdown options list */
.calendar-month-list {
min-width: 72px;
position: absolute;
top: 100%;
left: 0;
z-index: 1;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
max-height: 255px;
overflow: auto;
}
/* Styles for the individual dropdown option */
.calendar-month-option {
padding: 8px;
cursor: pointer;
font-size: 14px;
}
/* Styles for the dropdown button */
.calendar-year-button {
min-width: 75px;
padding: 5px 5px 5px 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
/* Styles for the dropdown options list */
.calendar-year-list {
min-width: 72px;
position: absolute;
top: 100%;
left: 0;
z-index: 1;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
max-height: 255px;
overflow: auto;
}
/* Styles for the individual dropdown option */
.calendar-year-option {
padding: 8px;
cursor: pointer;
font-size: 14px;
}
/* Styles for day dots container */
.calendar-day-dots {
display: flex;
justify-content: center;
align-items: center;
margin-top: 5px;
position: absolute;
bottom: 2px;
left: 0;
right: 0;
}
/* Styles for individual dots */
.calendar-day-dots .dot {
width: 6px;
height: 6px;
border-radius: 50%;
margin: 0 2px;
}
/* Styles for different appointment statuses */
.dot-missed {
background-color: red;
}
.dot-cancelled {
background-color: orange;
}
.dot-incomplete {
background-color: yellow;
}
.dot-completed {
background-color: green;
}
/* Style for the "more" dot */
.dot-more {
font-size: 10px;
margin-left: 2px;
}
/* CSS for the selected dates list */
.selected-dates-list {
min-width: 120px;
flex: 1 1;
padding: 10px;
border-left: 1px solid #ccc;
list-style: none;
margin: 0;
min-height: 255px;
max-height: 299px;
overflow: auto;
overflow-x: hidden;
height: calc(100% - 65px);
}
.selected-list-block {
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
padding: 13px 20px;
}
.selected-list-block p {
margin: auto;
font-weight: bold;
}
.selected-dates-list li {
margin-bottom: 5px;
display: flex;
align-items: center;
}
/* CSS for the close button */
.close-button {
border: none;
background: transparent;
cursor: pointer;
font-size: 14px;
line-height: 1;
margin-left: 5px;
color: #888;
}
.close-button:hover {
color: #f00; /* Change the color when hovered for better visibility */
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* CSS for the tooltip */
.tooltip {
position: absolute;
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px;
border-radius: 5px;
font-size: 14px;
display: block;
z-index: 99999;
width: max-content;
}
.tooltip .tooltip_info {
margin: 0;
}
.tooltip-dot {
display: inline-flex;
flex-shrink: 0;
width: 6px;
height: 6px;
border-radius: 50%;
margin: 0 2px;
}
.tooltip-list {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.tooltip-list:last-child {
margin-bottom: 0;
}
.tooltip-dot {
margin-right: 4px;
}
The Calendar component is designed with accessibility in mind. It includes ARIA attributes for improved screen reader support and supports keyboard navigation.