Skip to main content
Date picking lives on MonthList, the vertically-scrolling month list. It takes the selection props and renders a range as filled endpoint badges with a centered rounded “pill” band across the span; today keeps its own badge. Pass fillCellOnSelection to fill the whole cell instead of the pill. Calendar takes the same props in month and year modes, so an events calendar can carry a selection too. See In the calendar.

Range selection with useDateRange

useDateRange owns the start/end state machine: the first press sets the start, the second sets the end (auto-swapping if you tap an earlier day), and a third press starts over.
Tap two days to set the ends, or drag to sweep out a range: long-press a day and drag, and the list auto-scrolls at the edges so a range can span months. Wire onSelectDrag to useDateRange’s selectRange.

Single and multiple days

selectedDates marks discrete days. Drive it from onPressDay:

Disabled days

minDate, maxDate, and isDateDisabled render days dimmed, ignore taps, and keep them out of any selection (drag included). Pass the same constraints to useDateRange so a rejected day never opens a range:
Selection is a rangeBackground band over the span; there is no per-day selected circle by default, so the “today” badge stays distinct. See Theming for the token.

In the calendar

Calendar accepts selectedDates, selectedRange, minDate, maxDate, isDateDisabled, and onSelectDrag in month and year modes, drawn exactly as they are in the picker (fillCellOnSelection applies to the month grid only). So the same selection model works on top of a calendar that also shows events: pick a range to filter a report, block out a holiday, or choose the days a new event should span.
Tap two days, or hold a day and drag across others (press and drag on the web) to sweep the range out in one gesture. On the month grid the drag starts from empty day space, so dragging an event chip still moves the event (see Drag & create); on the year grid any day starts a sweep. Add onCreateEvent alongside onSelectDrag and the same sweep also reports an all-day range on release, which is how you turn a swept selection into an event.