Date Picker
A button that opens a calendar in a popover: a single date, a range, or a date and a time. Composed from Button, Popover, Calendar and Input.
When to use
- A date, a range, or a date and a time in a form, where the calendar only needs to show on demand.
When not to use
- A time on its own: use Input with
type="time". - A date of birth or any date users know by heart: use Input, so they type it.
- A page whose main task is picking a date: use Calendar inline.
Install
npx shadcn@latest add @clinia/button @clinia/popover @clinia/calendar @clinia/input @clinia/labelClinia rules
- The trigger is an
outlineButton with a calendar icon. It shows the chosen value, or a placeholder that names the choice (Pick a date) intext-muted-foreground. - Format dates the same way everywhere on a page, with the month in words (
Sep 18, 2026), so 09/10 is never read two ways. - Close the popover once a single date is picked. For a range or a date and time, keep it open until both parts are set.
- A range is
mode="range"on Calendar: the two ends are primary fills and the days between are tintedbg-accent/15. Show two months so a range across a month end fits in one view. - For a time, use the native
<input type="time">;step={900}limits it to quarter hours. Build a custom time picker only if the native one can't do the job.
Do and don't
Accessibility
Built in
- Time uses the browser's own
<input type="time">: it handles the keyboard, screen readers, and the 12- or 24-hour format of the user's locale.
Your responsibility
- Label the trigger with
aria-labelledbypointing at both the label and the value, as the examples do, so a screen reader hears "Follow-up date, Sep 18, 2026". A bare button reads only asPick a date. - Keep the chosen value visible in the trigger after the popover closes.
How to test
- Press Tab to reach the trigger: the Trust ring appears. A screen reader reads the label and the current value.
- Press Enter: the popover opens and focus moves into it.
- Tab to the day grid, move with the arrow keys and press Enter: the trigger shows the new date.
- Press Escape: the popover closes and focus returns to the trigger.