Components
Calendar
A date picker calendar component with single, multiple, and range selection modes.
Calendar
The Calendar component provides a rich date selection interface supporting single dates, multiple dates, or date ranges. It includes month navigation, customizable date constraints, and various display options.
For a complete date picker experience with an input field and popover, consider using the DatePicker component which wraps Calendar with additional UI.
Features
- Selection modes: single date, multiple dates, or date range
- Month navigation with previous/next buttons
- Optional year selector dropdown
- Min/max date constraints
- Custom disabled dates (array or function)
- Week numbers display
- Fixed weeks option for consistent height
- Multi-month display
- Customizable first day of week
- Outside days visibility control
- Initial focus support for accessibility
Usage
import { Calendar } from '@loke/design-system/calendar';
export default function Example() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
/>
);
}Tips:
- Use
mode="single"for selecting a single date. - Use
mode="range"for date range selection (e.g., booking dates). - Set
minDateandmaxDateto constrain selectable dates. - Enable
showWeekNumberfor calendars that need week-based navigation.
Props
Prop
Type
Examples
Single date selection
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
const [date, setDate] = useState<Date | undefined>(new Date());
<Calendar
mode="single"
selected={date}
onSelect={setDate}
/>Multiple date selection
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
const [dates, setDates] = useState<Date[]>([]);
<Calendar
mode="multiple"
selected={dates}
onSelect={setDates}
/>Date range selection
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
March 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
const [range, setRange] = useState<DateRange | undefined>();
<Calendar
mode="range"
selected={range}
onSelect={setRange}
numberOfMonths={2}
/>Disabled dates
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
// Disable weekends
<Calendar
mode="single"
disabled={(date) => date.getDay() === 0 || date.getDay() === 6}
/>
// Or disable specific dates
<Calendar
mode="single"
disabled={[new Date(2024, 0, 1), new Date(2024, 11, 25)]}
/>Min and max dates
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
<Calendar
mode="single"
minDate={new Date()}
maxDate={new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)}
/>Multiple months
January 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
March 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
<Calendar
mode="range"
numberOfMonths={2}
/>Week numbers
January 2026
| # | S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|---|
| 52 | |||||||
| 1 | |||||||
| 2 | |||||||
| 3 | |||||||
| 4 |
<Calendar
mode="single"
showWeekNumber
/>Year selector
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
<Calendar
mode="single"
captionProps={{ showYearSelector: true }}
/>Accessibility
- Calendar uses semantic table markup for screen reader compatibility.
- Keyboard navigation with arrow keys moves between days.
- Days are focusable with proper
tabIndexmanagement. - Selected state is conveyed via
aria-selectedattributes. - Disabled days are marked with
disabledattribute. - Use
initialFocusto ensure keyboard users land on a meaningful date when the calendar opens.
Best practices
- Set appropriate
minDate/maxDateconstraints to prevent invalid selections. - Use
mode="range"withnumberOfMonths={2}for better date range UX. - Enable
showWeekNumberfor business applications that reference week numbers. - Consider
fixedWeeksto prevent layout shifts when navigating months. - Use
captionProps.showYearSelectorwhen users need to navigate to distant dates. - Pair with
Labelcomponent for form accessibility.