Almost every date picker on the web is built for the wrong task. It offers a grid of a month when the reader wants "next Tuesday", it demands two clicks for a range where one drag would do, and it treats time as an afterthought bolted under the calendar. The component is rarely the problem. The mismatch between the control and the question is.
90 public components on 21st have "calendar" in the name and a further handful say "date picker". Sorted by the question they answer rather than by how they look, they fall into five groups.
A single date, near today
The default case: a booking, a deadline, a birthday within a year or two. A month grid with keyboard navigation is right here, and it is also the case where the input beside it matters most.
Calendar by Ali Imam is the most-saved plain version. Calendar [React Day Picker] by originui is the same shape on top of React Day Picker, which is what shadcn/ui's own Calendar wraps, so it slots into an existing setup without a second date library.
The part worth doing properly is the text input. A calendar with no typed entry is slow for anyone who knows the date, and a typed entry that only accepts one format is worse than no typing at all. Accept what people type, echo back what you understood, and keep the grid for browsing rather than for entry.
A single date, far from today
A birthday, a passport expiry, a historic record. A month grid is the wrong control: reaching 1987 costs several hundred clicks on the previous arrow.
Two answers. Give the header a month and year select, which is the smallest fix and the one most implementations skip. Or use a wheel: Date Wheel Picker by Osiris Balonga is the mobile-native shape, three spinning columns, which is what an operating system offers for exactly this reason.
A range
Ranges are where usability is won or lost, because the two-click model is where readers get stuck. The rules that make a range picker feel obvious: show two months side by side on wide screens, preview the range as the cursor moves before the second click lands, allow the second click to be earlier than the first and swap the ends silently, and always offer presets. "Last 7 days" and "This month" answer most range questions without a calendar at all.
Fullscreen Calendar by Ahmed Mayara is the full-page take for a scheduling surface, and Glass Calendar by Ravi Katiyar is the styled version of the same grid.

![Calendar [React Day Picker] by originui](https://cdn.21st.dev/cdn-cgi/image/fit=scale-down,width=640,quality=75,format=auto/https://cdn.21st.dev/user_originui/calendar/default/preview.1737991983843.png)


A date with a time
The combination that most libraries treat as an afterthought, and the one real products need most: a meeting, a delivery slot, a call.
Calendar with time pressets by shadcn is the pattern that works, a grid beside a list of times rather than a separate time input underneath. Presets beat a free-form time field because the answer is almost always one of a dozen options.
The scheduling components take this further and put availability in the picture. Coach Scheduling Card by Isaiah, Meeting Scheduler by Kavi Katiyar, Visualize Booking by LN and Delivery Scheduler by Ravi Katiyar are all the same insight: when only some slots are available, showing the slots is a better interface than showing a calendar and then rejecting the choice.
A date as data, not as input
Sometimes the calendar is a readout. GitHub calendar by Ali Imam is the contribution-heatmap shape, and Economic Calendar by Ravi Katiyar is the dated-events list. Different job, same word, and worth separating when you are searching: a heatmap is a chart, not a picker.




The four things that break date pickers in production
Time zones. A date picked in Tokyo and stored as a UTC timestamp is a different day when it is read in Los Angeles. The rule that avoids most of this: if the value is a calendar date, store a calendar date (2026-08-20), not an instant. Only use a timestamp when the value genuinely is a moment in time, and then store the zone alongside it.
Parsing the string the reader typed. new Date("03/04/2026") is March in the United States and April almost everywhere else, and the browser will not tell you which one it chose. Parse with an explicit format, and show the interpreted date back in an unambiguous form.
The keyboard. A calendar grid is a roving-tabindex widget: one stop in the tab order, arrows to move between days, Page Up and Page Down for months, Home and End for the week. Every cell being tabbable turns a month into forty tab stops. This is the part most hand-built pickers never implement, and the strongest argument for taking the behaviour from a library.
Announcing the change. When the reader moves to another day, a screen reader has to hear it. That means the focused cell carries the full date as its accessible name, not just "14", and the selected state is exposed with aria-selected rather than a class.
Where else to look
The honest list of alternatives, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| React Day Picker | The engine under shadcn/ui's Calendar: ranges, keyboard, localisation | Unstyled by design; the popover and input are yours |
| React Aria | The most complete keyboard, screen reader and internationalisation behaviour | More API to learn, and you still write the visuals |
| Temporal / date-fns | The date maths itself, with time zones handled honestly | Not a UI at all |
| 21st | Finished pickers, schedulers and the availability-first booking shapes | Quality varies by author, so preview before you take it |
The split that holds up: React Day Picker or React Aria for behaviour, a catalogue component for the layout, and a real date library for anything involving arithmetic or zones.
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a date picker, get the previews inline, and let the agent write the file.
Frequently asked
- What is the best date picker for React?
- React Day Picker for most cases, which is what shadcn/ui's Calendar wraps, or React Aria when internationalisation and screen reader behaviour matter more than bundle size. Both are behaviour rather than design, so the visual layer still comes from your design system or a catalogue component. The choice that matters more is which control fits the question being asked.
- How do you handle time zones in a date picker?
- If the value is a calendar date, store a calendar date such as 2026-08-20, not a timestamp. A date picked in Tokyo and stored as a UTC instant is a different day when read in Los Angeles. Only store a moment in time when the value genuinely is one, and then keep the zone alongside it rather than assuming the reader's.
- How should a date range picker behave?
- Two months side by side on wide screens, a live preview of the range as the pointer moves before the second click lands, silent swapping when the second click is earlier than the first, and presets. Last 7 days and This month answer most range questions without opening a calendar at all.
- How do you make a calendar keyboard accessible?
- Treat the grid as a roving-tabindex widget: one stop in the tab order, arrow keys between days, Page Up and Page Down for months, Home and End for the week. Every cell being tabbable turns one month into forty tab stops. Each focused cell needs the full date as its accessible name, not just the number, and selection exposed through aria-selected rather than a class.