Customizable React Calendar Component with TypeScript support
- 🎨 Fully Customizable - Easy to style with SCSS modules
- 📱 Responsive Design - Works on all screen sizes
- 🔧 TypeScript Support - Full type definitions included
- 📅 Month Navigation - Intuitive ← → navigation
- 🎯 Today Highlight - Current day automatically highlighted
- ✅ Selection State - Clear visual feedback on selected date
- 🖱️ Click Outside - Auto-closes when clicking outside calendar
- 🌍 i18n Ready - Easy to translate month/day names
- 📦 Lightweight - Minimal dependencies
npm install react react-iconsRequired Dependencies:
- React 18+
- react-icons (FaRegCalendarAlt, TiArrowLeftThick, TiArrowRightThick)
import Calendar from './components/Calendar/Calendar';
function MyForm() {
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
return (
<Calendar
label="Birth Date"
initialDate={new Date()}
onChange={(date) => setSelectedDate(date)}
/>
);
}import { Controller } from 'react-hook-form';
<Controller
name="birthDate"
control={control}
render={({ field }) => (
<Calendar
label="Select Date"
initialDate={field.value}
onChange={field.onChange}
/>
)}
/>| Prop | Type | Required | Description |
|---|---|---|---|
label |
string |
No | Calendar label text |
initialDate |
Date |
No | Initial selected date |
minDate |
Date |
No | Minimum allowed date (future feature) |
maxDate |
Date |
No | Maximum allowed date (future feature) |
onChange |
(date: Date) => void |
No | Callback function when date is selected |
className |
string |
No | Additional CSS class for the calendar container |
style |
React.CSSProperties |
No | Inline styles for the calendar container |
onDatechange |
`(date: Date | null) => void` | No |
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
const [currentMonth, setCurrentMonth] = useState<Date>(new Date());
const [isOpen, setIsOpen] = useState(false);selectedDate- Which date is selected by usercurrentMonth- Which month is currently being viewedisOpen- Whether calendar popup is open or closed
Uses useRef and useEffect to detect clicks outside the calendar and automatically close the popup:
const calendarRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (calendarRef.current && !calendarRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);const getMonthName = (date: Date): string => {
const months = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
];
return months[date.getMonth()];
};const renderWeekDay = () => {
const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
return days.map((day) => (
<div key={day} className={styles.weekDay}>{day}</div>
));
};All styles are in Calendar.module.scss - easily customize:
- Colors
- Border radius
- Fonts
- Spacing
- Animations
const getDayInMonth = (date: Date): number => {
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
};JavaScript trick: Day 0 of next month = Last day of current month!
.daysGrid {
display: grid;
grid-template-columns: repeat(7, 1fr); // 7 columns for 7 days
gap: 4px;
}- ✅ Min/Max date validation
- ✅ Disabled days
- ✅ Range selection (from-to)
- ✅ Multiple month display
- ✅ Full i18n support
- ✅ Keyboard navigation
- ✅ Accessibility (ARIA labels)
MIT License - Free to use in personal and commercial projects.
Created by Tamar Khuskivadze
If you like this project, please give it a ⭐ on GitHub!
