Skip to main content

Getting Started

Install @gentleduck/calendar, wire up the hook, and render a month grid.

Install


npm install @gentleduck/calendar

npm install @gentleduck/calendar

For compound components (optional):


npm install @gentleduck/primitives

npm install @gentleduck/primitives

Requirements:

  • React 18+
  • TypeScript optional (types are bundled)

Quick start

Create an adapter instance

The adapter tells the engine how to work with dates. The built-in NativeAdapter uses Date + Intl.DateTimeFormat with zero dependencies.

import { NativeAdapter } from '@gentleduck/calendar'
 
const adapter = new NativeAdapter()
import { NativeAdapter } from '@gentleduck/calendar'
 
const adapter = new NativeAdapter()

Wire up the hook

useCalendar returns state, actions, and prop getters you spread onto your elements.

import { NativeAdapter, useCalendar } from '@gentleduck/calendar'
 
const adapter = new NativeAdapter()
 
function MyCalendar() {
  const { state, getDayProps, getGridProps, getHeaderProps, getNavProps } = useCalendar({
    adapter,
    mode: 'single',
  })
 
  return (
    <div>
      <div {...getHeaderProps()}>
        {adapter.format(state.month, { month: 'long', year: 'numeric' })}
      </div>
      <button {...getNavProps('prev')}><-</button>
      <button {...getNavProps('next')}>-></button>
      <div {...getGridProps()}>
        {state.weeks.map(week =>
          week.days.map(day => (
            <button key={day.date.getTime()} {...getDayProps(day)}>
              {day.date.getDate()}
            </button>
          ))
        )}
      </div>
    </div>
  )
}
import { NativeAdapter, useCalendar } from '@gentleduck/calendar'
 
const adapter = new NativeAdapter()
 
function MyCalendar() {
  const { state, getDayProps, getGridProps, getHeaderProps, getNavProps } = useCalendar({
    adapter,
    mode: 'single',
  })
 
  return (
    <div>
      <div {...getHeaderProps()}>
        {adapter.format(state.month, { month: 'long', year: 'numeric' })}
      </div>
      <button {...getNavProps('prev')}><-</button>
      <button {...getNavProps('next')}>-></button>
      <div {...getGridProps()}>
        {state.weeks.map(week =>
          week.days.map(day => (
            <button key={day.date.getTime()} {...getDayProps(day)}>
              {day.date.getDate()}
            </button>
          ))
        )}
      </div>
    </div>
  )
}

Or use compound components

If you prefer a declarative API, use the compound components from @gentleduck/primitives/calendar. They compose useCalendar internally.

import { NativeAdapter } from '@gentleduck/calendar'
import * as CalendarPrimitive from '@gentleduck/primitives/calendar'
 
const adapter = new NativeAdapter()
 
function MyCalendar() {
  return (
    <CalendarPrimitive.Root adapter={adapter} mode="single">
      <CalendarPrimitive.Header />
      <CalendarPrimitive.Nav />
      <CalendarPrimitive.Grid>
        <CalendarPrimitive.Weekdays />
        {/* Render day cells using CalendarPrimitive.Day */}
      </CalendarPrimitive.Grid>
    </CalendarPrimitive.Root>
  )
}
import { NativeAdapter } from '@gentleduck/calendar'
import * as CalendarPrimitive from '@gentleduck/primitives/calendar'
 
const adapter = new NativeAdapter()
 
function MyCalendar() {
  return (
    <CalendarPrimitive.Root adapter={adapter} mode="single">
      <CalendarPrimitive.Header />
      <CalendarPrimitive.Nav />
      <CalendarPrimitive.Grid>
        <CalendarPrimitive.Weekdays />
        {/* Render day cells using CalendarPrimitive.Day */}
      </CalendarPrimitive.Grid>
    </CalendarPrimitive.Root>
  )
}

Next pages