# Calendar range picker

> A stateful two-month range calendar for booking a span of days, with clear and reserve actions.

A shadcn/ui block from the [@quill](https://www.quilldesignsystem.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/quill/calendar-range).

- Page, with a live preview: https://shadcn.exchange/r/quill/calendar-range
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/quill/calendar-range-light-e8636793cbc9f1a2.png
- Registry item: https://www.quilldesignsystem.com/r/calendar-range.json
- Categories: scheduling, form
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.quilldesignsystem.com/r/calendar-range.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `react-day-picker`
- Registry items: `card`, `calendar`, `button`, `badge`

## Notes from the registry

A stateful two-month range calendar for booking a span of days, with clear and reserve actions. Do: Keep the Clear action available whenever a range is selected, separate from Reserve. Don't: Force a user to re-click through the whole range to correct a mis-click — that's what Clear is for. Do: Disable Reserve until both a start and end date are selected. Don't: Let a half-made range (just a start date) submit as if it were a valid booking. Use calendar-page when the user is picking a single day to view, not a multi-day span to reserve. Use checkout when the range is just one field within a larger purchase flow, not the whole card.

## Files

### `registry/blocks/calendar-range.tsx`

```tsx
'use client'
import { useState } from 'react'
import type { DateRange } from 'react-day-picker'
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card'
import { Calendar } from '@/components/ui/calendar'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'

/** A stateful two-month range calendar for booking a span of days, with clear and reserve actions. */
export function CalendarRange() {
  const [range, setRange] = useState<DateRange | undefined>({
    from: new Date(2026, 6, 20),
    to: new Date(2026, 6, 24),
  })
  return (
    <Card className="w-fit">
      <CardHeader>
        <div className="flex items-center justify-between gap-4">
          <CardTitle>Book a session</CardTitle>
          <Badge variant="secondary">5 days selected</Badge>
        </div>
        <CardDescription>Pick the days you want with the product team.</CardDescription>
      </CardHeader>
      <CardContent>
        <Calendar
          mode="range"
          numberOfMonths={2}
          selected={range}
          onSelect={setRange}
          defaultMonth={new Date(2026, 6)}
          className="rounded-lg border border-border"
        />
      </CardContent>
      <CardFooter className="justify-between">
        <span className="text-sm text-muted-foreground">July 20 – 24, 2026</span>
        <div className="flex gap-2">
          <Button variant="ghost" size="sm">
            Clear
          </Button>
          <Button size="sm">Reserve</Button>
        </div>
      </CardFooter>
    </Card>
  )
}
```
