Calendar
Interactive calendar component for date selection with month/year navigation
Calendar
An interactive calendar component for selecting dates. Features month/year navigation, three view modes (day/month/year), and programmatic control via ref.
Installation
import { Calendar } from '@geckoui/geckoui';Basic Usage
'use client';
import { useState } from 'react';
import { Calendar } from '@geckoui/geckoui';
function Example() {
const [selectedDate, setSelectedDate] = useState<string | undefined>();
return (
<div className="space-y-4">
<Calendar selectedDate={selectedDate} onSelectDate={setSelectedDate} />
{selectedDate && <p className="text-sm text-gray-600">Selected: {selectedDate}</p>}
</div>
);
}Props API
Single Mode Props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | 'single' | 'single' | Selection mode for single date |
selectedDate | string | null | undefined | - | Currently selected date in YYYY-MM-DD format |
onSelectDate | (date: string) => void | - | Callback when date is selected |
Range Mode Props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | 'range' | - | Selection mode for date range |
selectedRange | DateRange | - | Selected date range with from and to |
onSelectRange | (range: DateRange | null) => void | - | Callback when range is selected |
numberOfMonths | 1 | 2 | 2 | Number of months to display side by side |
Common Props
| Prop | Type | Default | Description |
|---|---|---|---|
calendarRef | React.Ref<CalendarRef> | - | Ref for programmatic control |
className | string | - | Additional CSS classes |
style | React.CSSProperties | - | Inline styles |
disableDate | (date: string) => boolean | - | Callback to determine if a date should be disabled |
renderDayCell | (props: DayCellRenderProps) => ReactNode | - | Custom renderer for day cells |
DateRange Type
interface DateRange {
from: string | null; // ISO format: 'YYYY-MM-DD'
to?: string | null; // ISO format: 'YYYY-MM-DD'
}DayCellRenderProps Type
interface DayCellRenderProps {
day: number;
month: number;
year: number;
date: string; // 'YYYY-MM-DD' format
isDisabled: boolean;
isSelected: boolean;
isFocusedMonth: boolean; // true if the day is in the current month being viewed
}Date Format
All dates must be in ISO format: YYYY-MM-DD
// ✅ Correct
selectedDate="2024-12-25"
selectedDate="2024-01-01"
// ❌ Incorrect
selectedDate="12/25/2024"
selectedDate="25-12-2024"The component validates the date format and logs an error if invalid.
Examples
With Default Date
Pre-select a date when the calendar loads:
Selected: 2024-06-15
const [selectedDate, setSelectedDate] = useState<string | undefined>('2024-06-15');
<Calendar selectedDate={selectedDate} onSelectDate={setSelectedDate} />Use Cases:
- Highlight today's date
- Mark important dates (holidays, events)
- Show reference dates while selecting
Programmatic Control
Navigate to specific months/years using calendarRef:
'use client';
import { useState, useRef } from 'react';
import { Calendar, Button } from '@geckoui/geckoui';
import type { CalendarRef } from '@geckoui/geckoui';
function Example() {
const [selectedDate, setSelectedDate] = useState<string | undefined>();
const calendarRef = useRef<CalendarRef>(null);
const jumpToDate = (month: number, year: number) => {
calendarRef.current?.moveTo(month, year);
};
return (
<div className="space-y-4">
<div className="flex gap-2">
<Button size="sm" variant="outlined" onClick={() => jumpToDate(1, 2025)}>
January 2025
</Button>
<Button size="sm" variant="outlined" onClick={() => jumpToDate(7, 2024)}>
July 2024
</Button>
<Button size="sm" variant="outlined" onClick={() => jumpToDate(12, 2023)}>
December 2023
</Button>
</div>
<Calendar
selectedDate={selectedDate}
onSelectDate={setSelectedDate}
calendarRef={calendarRef}
/>
</div>
);
}CalendarRef API
interface CalendarRef {
moveTo: (month: number, year: number) => void;
}Parameters:
month: 1-12 (January = 1, December = 12)year: Full year (e.g., 2024, 2025)
Behavior:
- Switches view to Day mode
- Displays the specified month/year
- Does NOT select a date (only navigates)
Range Mode
Use mode="range" to enable date range selection with a dual-month calendar display.
'use client';
import { useState } from 'react';
import { Calendar } from '@geckoui/geckoui';
import type { DateRange } from '@geckoui/geckoui';
function Example() {
const [selectedRange, setSelectedRange] = useState<DateRange | undefined>();
return (
<Calendar
mode="range"
selectedRange={selectedRange}
onSelectRange={(range) => setSelectedRange(range ?? undefined)}
/>
);
}Single Month Display
Use numberOfMonths={1} for a compact single-month range picker:
<Calendar
mode="range"
selectedRange={selectedRange}
onSelectRange={(range) => setSelectedRange(range ?? undefined)}
numberOfMonths={1}
/>Disable Dates
Use disableDate to prevent selection of specific dates. The callback receives a date string in YYYY-MM-DD format and returns true to disable the date.
'use client';
import { useState } from 'react';
import { Calendar } from '@geckoui/geckoui';
function Example() {
const [selectedDate, setSelectedDate] = useState<string | undefined>();
const disableDate = (date: string) => {
const dayOfWeek = new Date(date).getDay();
return dayOfWeek === 0 || dayOfWeek === 6; // Disable weekends
};
return (
<Calendar
selectedDate={selectedDate}
onSelectDate={setSelectedDate}
disableDate={disableDate}
/>
);
}Common Use Cases:
- Disable weekends
- Disable past dates
- Disable holidays or specific dates
- Disable dates outside a valid range
Custom Day Rendering
Use renderDayCell to customize how each day cell is displayed. This allows adding custom styling, indicators, or content to specific dates.
'use client';
import { useState } from 'react';
import { Calendar } from '@geckoui/geckoui';
import type { DayCellRenderProps } from '@geckoui/geckoui';
function Example() {
const [selectedDate, setSelectedDate] = useState<string | undefined>();
const hasEvent = (date: string) => {
const today = new Date();
return today.getDate() === new Date(date).getDate();
};
return (
<div className="space-y-4">
<Calendar
selectedDate={selectedDate}
onSelectDate={setSelectedDate}
renderDayCell={({ day, date }) => (
<>
<span>{day}</span>
{hasEvent(date) && (
<span className="absolute top-1 right-1 w-1.5 h-1.5 bg-red-500 rounded-full" />
)}
</>
)}
/>
{selectedDate && <p className="text-sm text-gray-600">Selected: {selectedDate}</p>}
</div>
);
}Common Use Cases:
- Add event indicators or dots
- Show custom styling for holidays
- Display additional information on hover
- Highlight specific date ranges
Styling
The component uses BEM-style class names:
Main Container:
GeckoUICalendar- Main containerGeckoUICalendar--calendars-2- Dual calendar mode modifierGeckoUICalendar__dual- Dual calendar wrapperGeckoUICalendar__dual--first/GeckoUICalendar__dual--second- First/second calendar
Header:
GeckoUICalendar__header- Header containerGeckoUICalendar__header__title- Month/year titleGeckoUICalendar__header__title--clickable- Clickable title stateGeckoUICalendar__header__arrow-button- Navigation arrow buttonsGeckoUICalendar__header__arrow-left-icon/GeckoUICalendar__header__arrow-right-icon- Arrow icons
Year Picker:
GeckoUICalendar__year-picker- Year picker gridGeckoUICalendar__year-picker__button- Year buttonGeckoUICalendar__year-picker__button--selected- Selected yearGeckoUICalendar__year-picker__button--prev-next- Previous/next year buttons
Month Picker:
GeckoUICalendar__month-picker- Month picker gridGeckoUICalendar__month-picker__button- Month buttonGeckoUICalendar__month-picker__button--selected- Selected month
Day Picker:
GeckoUICalendar__day-picker-weekdays- Weekday header rowGeckoUICalendar__day-picker- Day picker gridGeckoUICalendar__day-picker__button- Day buttonGeckoUICalendar__day-picker__button--today- Today's dateGeckoUICalendar__day-picker__button--selected- Selected dateGeckoUICalendar__day-picker__button--disabled- Disabled dateGeckoUICalendar__day-picker__button--active-month-false- Dates outside current monthGeckoUICalendar__day-picker__button--in-range- Date within selected rangeGeckoUICalendar__day-picker__button--range-start- Range start dateGeckoUICalendar__day-picker__button--range-end- Range end dateGeckoUICalendar__day-picker__button--hover-preview- Hover preview for range selectionGeckoUICalendar__day-picker__button--hover-preview-start/GeckoUICalendar__day-picker__button--hover-preview-end- Hover preview boundaries
Accessibility
- Semantic HTML with proper table structure for day grid
- Keyboard navigation with arrow keys
- Tab to focus navigation buttons
- Enter/Space to select dates
- Screen reader announcements for date selection
- ARIA labels for navigation controls
Best Practices
- Always use ISO format: Use YYYY-MM-DD for all date values
- Validate dates: Check date ranges and constraints in onSelectDate
- Clear selection: Provide a way to clear the selected date
- Form integration: Disable submit until date is selected
- Error handling: Show validation errors near the calendar
- Responsive design: Calendar adapts to container width
Related Components
- DateInput - Input field with calendar popup
- DateRangeInput - Input for selecting date ranges
- RHFDateInput - React Hook Form integrated date input