Calendar
Standalone month-grid date picker backed by React Aria; supports single-date and range selection across one or two months.
Built on React Aria Calendar / RangeCalendar — full keyboard support, arrow-key date traversal, and labelled prev/next navigation.
Preview
tsx
import { Calendar } from '@arshad-shah/cynosure-react/calendar';
import { parseDate } from '@internationalized/date';
export default function Example() {
return <Calendar aria-label="Event date" defaultValue={parseDate('2026-04-17')} />;
}
Controlled
Section titled “Controlled”Drive selection from state by passing value + onChange. Values are @internationalized/date DateValues.
Preview
tsx
import { Calendar } from '@arshad-shah/cynosure-react/calendar';
import { type CalendarDate, getLocalTimeZone, today } from '@internationalized/date';
import { useState } from 'react';
export default function Example() {
const [value, setValue] = useState<CalendarDate | null>(today(getLocalTimeZone()));
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<Calendar aria-label="Event date" value={value} onChange={setValue} />
<p style={{ fontSize: '0.875rem', color: 'var(--cynosure-color-fg-muted)' }}>
Selected: {value?.toString() ?? 'none'}
</p>
</div>
);
}
Dual month
Section titled “Dual month”Use visibleMonths={2} to render two adjacent month grids — useful in dense scheduling UIs.
Preview
tsx
import { Calendar } from '@arshad-shah/cynosure-react/calendar';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<Calendar aria-label="Event date" defaultValue={parseDate('2026-04-17')} visibleMonths={2} />
);
}
Range selection
Section titled “Range selection”RangeCalendar selects a start / end pair. It defaults to two visible months.
Preview
tsx
import { RangeCalendar } from '@arshad-shah/cynosure-react/calendar';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<RangeCalendar
aria-label="Trip dates"
defaultValue={{
start: parseDate('2026-04-12'),
end: parseDate('2026-04-18'),
}}
/>
);
}
With footer
Section titled “With footer”Pass any node to footer to slot a “Go to today” link, keyboard hints, or a clear button below the grid.
PropTypeDefaultDescription
className
string
—
style
CSSProperties
—
visibleMonths
1|2
1
Number of months shown side by side. Use `2` for range-heavy UIs.
Default `1` for `<Calendar>`, `2` for `<RangeCalendar>`.
footer
ReactNode
—
Footer rendered below the grid — e.g. "Go to today" or keyboard hints.
Accessibility
Section titled “Accessibility”- Built on React Aria — exposes proper
role="grid"semantics and full keyboard traversal (arrows, Home/End, PageUp/PageDown). - The header’s previous / next buttons carry
aria-label="Previous month"/"Next month". - Always pass
aria-label(or visible labelling) onCalendarandRangeCalendarso screen readers can announce what the date is for. - Disabled and unavailable dates from React Aria are respected and skipped during keyboard navigation.
Recipes
Section titled “Recipes”- Use
minValue/maxValueto clamp the selectable range. - For range pickers in narrow layouts, set
visibleMonths={1}to drop down to a single grid. - Use
focusedValue+onFocusChangeto programmatically jump back to today.