DatePicker
Segmented date input with a calendar popover; backed by React Aria + @internationalized/date for locale-aware formatting and full keyboard control.
Each date segment is its own labelled spinbutton; popover is a labelled dialog with a roving-tabindex calendar grid.
import { DatePicker } from '@arshad-shah/cynosure-react';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<div style={{ width: 320 }}>
<DatePicker label="Start date" defaultValue={parseDate('2026-04-17')} />
</div>
);
}
import { DatePicker } from "@arshad-shah/cynosure-react";import { parseDate } from "@internationalized/date";
<DatePicker label="Start date" defaultValue={parseDate("2026-04-17")} />Values are @internationalized/date DateValues — pair the picker with parseDate / today(getLocalTimeZone()) from @internationalized/date.
Variants
Section titled “Variants”outline (default), filled, and ghost tint the segmented track — the same vocabulary as the other form controls; the raised segment tiles stay constant.
import { DatePicker, Stack } from '@arshad-shah/cynosure-react';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<Stack gap="3" style={{ width: 320 }}>
<DatePicker label="Outline" variant="outline" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Filled" variant="filled" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Ghost" variant="ghost" defaultValue={parseDate('2026-04-17')} />
</Stack>
);
}
sm, md (default), and lg.
import { DatePicker, Stack } from '@arshad-shah/cynosure-react';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<Stack gap="3" style={{ width: 320 }}>
<DatePicker label="Small" size="sm" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Medium" size="md" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Large" size="lg" defaultValue={parseDate('2026-04-17')} />
</Stack>
);
}
States
Section titled “States”Disabled, read-only, invalid, and empty.
import { DatePicker, Stack } from '@arshad-shah/cynosure-react';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<Stack gap="3" style={{ width: 320 }}>
<DatePicker label="Default" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Disabled" isDisabled defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Read only" isReadOnly defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Invalid" invalid defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Empty" aria-label="Empty date" />
</Stack>
);
}
Min / max
Section titled “Min / max”Constrain the selectable range with minValue and maxValue. The calendar disables out-of-range cells and the segments reject out-of-range entries.
import { DatePicker } from '@arshad-shah/cynosure-react';
import { getLocalTimeZone, today } from '@internationalized/date';
export default function Example() {
const tz = getLocalTimeZone();
const TODAY = today(tz);
return (
<div style={{ width: 320 }}>
<DatePicker
label="Must fall within the next 30 days"
minValue={TODAY}
maxValue={TODAY.add({ days: 30 })}
defaultValue={TODAY.add({ days: 7 })}
/>
</div>
);
}
Granularity
Section titled “Granularity”granularity switches between day-only and time-aware segments (hour, minute, second).
import { DatePicker, Stack } from '@arshad-shah/cynosure-react';
import { parseDate } from '@internationalized/date';
export default function Example() {
return (
<Stack gap="3" style={{ width: 360 }}>
<DatePicker label="Day precision" granularity="day" defaultValue={parseDate('2026-04-17')} />
<DatePicker label="Minute precision" granularity="minute" />
</Stack>
);
}
Accessibility
Section titled “Accessibility”- Each segment (year/month/day, plus time when applicable) is a labelled
spinbutton— arrow keys nudge the value, type-ahead works for two-digit entry. - The calendar popover is a labelled dialog with a roving-tabindex
gridfor date navigation. invalidtogglesaria-invalidon the input group; the calendar respectsminValue/maxValueand skips disabled cells.- Pass
aria-label(or a stringlabelprop) so the field has an accessible name in both states.
Recipes
Section titled “Recipes”- Use
value+onChangefor controlled state; passnullto clear. - Combine with
FormField+FormMessageto surface “required date” validation. - Wrap in
LocaleProviderto switch the segment order and the calendar’s first-day-of-week.