Skip to main content
Gremorie

Calendar

Date picker grid built on react-day-picker v10 - single date, multiple dates, or a date range, with token-driven theming and lucide chevrons.

Overview

Calendar wraps react-day-picker v10. Three modes via mode:

  • single - one date
  • range - start + end (date range)
  • multiple - several independent dates

Use Calendar standalone in pages with plenty of space (scheduling, planners). For compact forms, wrap it in Popover - that composed pattern is DatePicker. In v10 of react-day-picker the classNames keys were migrated to the UI enum; we call getDefaultClassNames() and merge our semantic tokens on top.

Preview

July 2026
'use client';import { Calendar } from '@gremorie/rx-forms';import { useState } from 'react';export function CalendarPreview() {  const [date, setDate] = useState<Date | undefined>(new Date());  return <Calendar mode="single" selected={date} onSelect={setDate} />;}

Anatomy

Calendar   self-contained DayPicker grid (caption + nav, weekday header, day buttons)

Installation

bash npx gremorie@latest add rx-calendar
bash pnpm dlx gremorie@latest add rx-calendar
bash yarn dlx gremorie@latest add rx-calendar
bash bunx --bun gremorie@latest add rx-calendar

Usage

import { Calendar } from "@gremorie/rx-forms";

export function Example() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());
  return <Calendar mode="single" selected={date} onSelect={setDate} />;
}

The Angular edition of this component ships from source today (see the workbench for the side-by-side); its registry entry is coming next.

API

<Calendar>

Forwards every prop to DayPicker from react-day-picker. The most relevant ones:

PropTypeDefaultDescription
mode"single" | "multiple" | "range""single"Selection model.
selectedDate | Date[] | DateRange-Controlled selection. Shape depends on mode.
onSelectdepends on mode-Fires when the user picks a date.
disabledMatcher | Matcher[]-Disable specific dates (past dates, weekends, custom predicates).
showOutsideDaysbooleantrueShow greyed-out days from neighbouring months.
numberOfMonthsnumber1Show multiple months side by side (useful for range pickers).
defaultMonthDatecurrent monthInitial month displayed when uncontrolled.
localeLocaleen-USdate-fns locale for month / weekday labels.
autoFocusbooleanfalseFocus the first selected (or today's) cell on mount. Used by DatePicker inside Popover.
classNamestring-Classes on the wrapper <div>. Defaults to p-3.
classNamesPartial<ClassNames>-Override any internal class. Merged onto the Gremorie defaults via cn.

For the full list of props, see the react-day-picker docs.

The Gremorie wrapper customizes:

  • button_previous / button_next - use buttonVariants({ variant: "outline" }) so the arrows match the rest of the design system
  • Chevron - swaps the default react-day-picker chevrons for lucide's ChevronLeftIcon / ChevronRightIcon
  • selected - uses bg-primary text-primary-foreground semantic tokens
  • today - uses bg-accent text-accent-foreground
  • outside, disabled, hidden - all token-driven

Composition

  1. <Calendar> is a self-contained widget. Drop it wherever you need a date grid.
  2. For compact UI, wrap it in a Popover + PopoverTrigger - that composition is exported as DatePicker in the overlays bundle.
  3. For range pickers, set mode="range" and numberOfMonths={2} so users see start + end month at once.

Variations

Single date

The default mode. State is Date | undefined.

function SingleDate() {
  const [date, setDate] = React.useState<Date | undefined>(new Date());
  return <Calendar mode="single" selected={date} onSelect={setDate} />;
}

Date range

State is { from?: Date; to?: Date }. Pair with numberOfMonths={2} for the classic side-by-side calendar UX.

import type { DateRange } from 'react-day-picker';

function DateRangeExample() {
  const [range, setRange] = React.useState<DateRange | undefined>();
  return (
    <Calendar
      mode="range"
      selected={range}
      onSelect={setRange}
      numberOfMonths={2}
    />
  );
}

Disable past dates

The disabled prop accepts a matcher. Use { before: today } to block historical dates.

<Calendar
  mode="single"
  selected={date}
  onSelect={setDate}
  disabled={{ before: new Date() }}
/>

Multiple independent dates

mode="multiple" lets users select any number of non-contiguous dates. State is Date[].

function MultipleDates() {
  const [dates, setDates] = React.useState<Date[] | undefined>();
  return <Calendar mode="multiple" selected={dates} onSelect={setDates} />;
}

Accessibility

  • Grid semantics: react-day-picker renders a role="grid" with rows of cells. Each cell is a button.
  • Keyboard:
    • ArrowLeft / ArrowRight move one day at a time.
    • ArrowUp / ArrowDown move one week at a time.
    • Home / End jump to first / last day of the row.
    • PageUp / PageDown move one month; Shift+PageUp / Shift+PageDown move one year.
  • Screen reader announcements: the focused date announces day of week, day number, and month. Disabled and outside days are announced as such.
  • Focus: when wrapped in Popover (the DatePicker pattern), set autoFocus so the active date receives focus on open.
  • Reduced motion: react-day-picker has no motion of its own; the calendar respects user motion preferences automatically.
  • Date Picker - the canonical Popover + Calendar composition
  • Popover - the recommended wrapper for compact UIs
  • Form - wire Calendar into react-hook-form

On this page