Date Picker

A calendar, popover and button composed into an installable single-date picker.

Installation

  1. Install the following dependencies.

    npm install date-fns lucide-react
  2. Copy the following into your project.

    components/date-picker.tsx
    "use client";
    
    import { format } from "date-fns";
    import { CalendarDaysIcon } from "lucide-react";
    import { useCallback, useState } from "react";
    
    import { Button } from "@/registry/terminal/ui/button";
    import { Calendar } from "@/registry/terminal/ui/calendar";
    import {
      Popover,
      PopoverContent,
      PopoverTrigger,
    } from "@/registry/terminal/ui/popover";
    
    const START_MONTH = new Date(1900, 0);
    const END_MONTH = new Date(2100, 11);
    
    function DatePicker() {
      const [date, setDate] = useState<Date>();
      const [open, setOpen] = useState(false);
    
      const selectDate = useCallback((nextDate: Date | undefined) => {
        setDate(nextDate);
        setOpen(false);
      }, []);
    
      return (
        <Popover onOpenChange={setOpen} open={open}>
          <PopoverTrigger
            render={
              <Button
                className="w-64 justify-start data-[empty=true]:text-muted-foreground"
                data-empty={!date}
                variant="outline"
              />
            }
          >
            <CalendarDaysIcon />
            {date ? format(date, "PPP") : "Pick a date"}
          </PopoverTrigger>
          <PopoverContent align="start" className="w-auto p-0">
            <Calendar
              autoFocus
              captionLayout="dropdown"
              endMonth={END_MONTH}
              mode="single"
              onSelect={selectDate}
              selected={date}
              startMonth={START_MONTH}
            />
          </PopoverContent>
        </Popover>
      );
    }
    
    export { DatePicker };
    
  3. Update the import paths to match your project.

API Reference

A date picker is a composition of Popover, Calendar and Button, rather than another UI primitive.

DatePicker

Owns the selected date and open state. Copy the block and adapt that state boundary to the form that uses it.