Calendar
● Stable · v0.1A month-grid date picker for choosing a single day — the date of a sale or expense, a loan's due date, a reminder. Big, readable day cells the user taps, with the selected day and today made obvious at a glance.
In context
Try it
Purpose
Dates are the one input people are worst at typing — formats differ (is 03/04 March or April?), and our users are often low-literacy and on a slow keyboard. A grid sidesteps all of it: the month is laid out the way a wall calendar is, the user finds the day and taps it, and there's no format to get wrong. Today and the chosen day are marked so the user always knows where they are.
It is controlled and presentational: you own the selected value and the component emits the picked Date via onChange. It carries no copy of its own — month and weekday names come in as props, so the same calendar localises by passing the right label arrays.
Anatomy
- Header — the current month and year, with previous / next arrows to move between months.
- Weekday row — short day labels, ordered by
firstDayOfWeek(Sunday or Monday). - Day grid — one tappable cell per day; each is at least a 44dp touch target.
- Selected day — a filled brand-teal circle with white text. Today — a teal ring and teal text when it isn't the selection.
Code
import { Calendar } from '@daytwo/components'const [date, setDate] = useState<Date | null>(null)<Calendarvalue={date}onChange={setDate}maxDate={new Date()} // can't pick the future/>
To localise, pass the month and weekday names (and start the week on Monday where that's the norm):
<Calendarvalue={date}onChange={setDate}firstDayOfWeek={1}monthNames={MY_MONTHS} // 12 names, Jan→DecweekdayNames={MY_WEEKDAYS} // 7 short names, Sun→SatfontFamily={burmeseFamily}/>
When to use
- To pick a specific calendar day — backdating a sale, setting a due date or a reminder.
- Whenever a typed date would be slow or error-prone (most of the time, for our users).
When NOT to use
- For a time, not a day — pair a separate time control; the Calendar only returns a date.
- For a wide range of years (a birth year) — month-by-month paging is slow; a year/decade picker fits better.
- When the choice is really "today vs a few recent days" — a row of chips (Segmented control) is faster than opening a full grid.
The correct scenario
Recording an expense the owner forgot to log yesterday: the sheet shows "When was this?" with the Calendar opened on the current month, today ringed. They tap yesterday — it fills teal — and continue. No keyboard, no format, no mistake.
Anti-patterns
Typed dates are the most error-prone input we have — wrong format, wrong order, typos. Let the user point at the day instead.
Edge cases
minDate/maxDate grey them out and block the tapmonthNames/weekdayNames + fontFamilyfirstDayOfWeek orders the header and grid