logo
CtrlK
ComponentsTemplates

Components

Accordion
Alert
Avatar
Badge
Banner
Bottom Navigation
Breadcrumb
Button
Call to Action
Card
Date Picker
Divider
Dropdown
Featues
File Upload
Footer
Header
Hero
Loader
Pagination
Popover
Sidebar
Skeleton
Social Share
Tabs
Testimonial
Tooltip

Pages

Error Pages
Blog List
  1. Docs
  2. Components
  3. Date Picker

Date Picker

Date pickers let users select a date from a calendar.

Basic Date Picker

import { useState } from "react";

const DatePicker: React.FC = () => {
  const [date, setDate] = useState("");

  return (
    <div className="w-64">
      <label
        htmlFor="date"
        className="block text-sm font-medium text-gray-800 dark:text-gray-200 mb-2"
      >
        Select a date
      </label>
      <input
        type="date"
        id="date"
        value={date}
        onChange={(e) => setDate(e.target.value)}
        className="block w-full px-4 py-3 text-gray-800 dark:text-gray-200 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl focus:outline-none hover:bg-gray-100 dark:hover:bg-gray-700"
      />
      {date && (
        <p className="mt-3 text-sm text-gray-600 dark:text-gray-400">
          Selected date: {new Date(date).toLocaleDateString()}
        </p>
      )}
    </div>
  );
};

export default DatePicker;

Custom calendar Date Picker

import { useState } from "react";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";

const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const months = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const CalendarPicker: React.FC = () => {
  const [currentDate, setCurrentDate] = useState(new Date());
  const [selectedDate, setSelectedDate] = useState<Date | null>(null);

  const firstDayOfMonth = new Date(
    currentDate.getFullYear(),
    currentDate.getMonth(),
    1
  );
  const lastDayOfMonth = new Date(
    currentDate.getFullYear(),
    currentDate.getMonth() + 1,
    0
  );
  const daysInMonth = lastDayOfMonth.getDate();
  const startingDayOfWeek = firstDayOfMonth.getDay();

  const prevMonth = () => {
    setCurrentDate(
      new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1)
    );
  };

  const nextMonth = () => {
    setCurrentDate(
      new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1)
    );
  };

  const handleDateClick = (day: number) => {
    setSelectedDate(
      new Date(currentDate.getFullYear(), currentDate.getMonth(), day)
    );
  };

  return (
    <div className="w-72 bg-gray-50 dark:bg-gray-800 shadow-lg rounded-2xl overflow-hidden border border-gray-100 dark:border-gray-700">
      <div className="flex justify-between items-center bg-white dark:bg-gray-800 p-4 border-b border-gray-100 dark:border-gray-700">
        <button
          onClick={prevMonth}
          className="p-2 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-full transition-colors"
        >
          <ChevronLeftIcon className="w-5 h-5 text-gray-600 dark:text-gray-400" />
        </button>
        <span className="font-semibold text-gray-800 dark:text-gray-200">
          {months[currentDate.getMonth()]} {currentDate.getFullYear()}
        </span>
        <button
          onClick={nextMonth}
          className="p-2 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-full transition-colors"
        >
          <ChevronRightIcon className="w-5 h-5 text-gray-600 dark:text-gray-400" />
        </button>
      </div>
      <div className="grid grid-cols-7 gap-1 p-4">
        {daysOfWeek.map((day) => (
          <div
            key={day}
            className="text-center text-sm font-medium text-gray-400 dark:text-gray-500 mb-2"
          >
            {day}
          </div>
        ))}
        {Array.from({ length: startingDayOfWeek }).map((_, index) => (
          <div key={`empty-${index}`} className="h-9"></div>
        ))}
        {Array.from({ length: daysInMonth }).map((_, index) => {
          const day = index + 1;
          const isSelected =
            selectedDate?.getDate() === day &&
            selectedDate?.getMonth() === currentDate.getMonth() &&
            selectedDate?.getFullYear() === currentDate.getFullYear();
          return (
            <button
              key={day}
              onClick={() => handleDateClick(day)}
              className={`h-9 w-9 flex items-center justify-center rounded-full text-sm transition-all duration-200
                ${
                  isSelected
                    ? "bg-blue-500 text-white font-semibold shadow-md"
                    : "hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300"
                }`}
            >
              {day}
            </button>
          );
        })}
      </div>
      {selectedDate && (
        <div className="border-t border-gray-100 dark:border-gray-700 bg-white dark:bg-gray-800">
          <p className="text-center p-3 text-sm text-gray-600 dark:text-gray-400">
            Selected: {selectedDate.toLocaleDateString()}
          </p>
        </div>
      )}
    </div>
  );
};

export default CalendarPicker;

Dropdown Date Picker

import { useState } from "react";

const DatePicker: React.FC = () => {
  const [day, setDay] = useState("");
  const [month, setMonth] = useState("");
  const [year, setYear] = useState("");

  const currentYear = new Date().getFullYear();
  const years = Array.from({ length: 100 }, (_, i) => currentYear - i);
  const months = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
  ];
  const days = Array.from({ length: 31 }, (_, i) => i + 1);

  const handleChange =
    (setter: React.Dispatch<React.SetStateAction<string>>) =>
    (e: React.ChangeEvent<HTMLSelectElement>) => {
      setter(e.target.value);
    };

  const selectClassName =
    "block w-full px-4 py-3 text-gray-800 dark:text-gray-200 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl focus:outline-none appearance-none cursor-pointer";

  return (
    <div className="w-72 space-y-3">
      <select
        value={month}
        onChange={handleChange(setMonth)}
        className={selectClassName}
      >
        <option value="">Month</option>
        {months.map((m, index) => (
          <option key={m} value={index + 1}>
            {m}
          </option>
        ))}
      </select>
      <select
        value={day}
        onChange={handleChange(setDay)}
        className={selectClassName}
      >
        <option value="">Day</option>
        {days.map((d) => (
          <option key={d} value={d}>
            {d}
          </option>
        ))}
      </select>
      <select
        value={year}
        onChange={handleChange(setYear)}
        className={selectClassName}
      >
        <option value="">Year</option>
        {years.map((y) => (
          <option key={y} value={y}>
            {y}
          </option>
        ))}
      </select>
      {day && month && year && (
        <p className="text-sm text-gray-600 dark:text-gray-400 mt-3">
          Selected date: {`${day}/${month}/${year}`}
        </p>
      )}
    </div>
  );
};

export default DatePicker;

Range Date Picker

import { useState } from "react";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";

const DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
const MONTHS = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

function getDaysInMonth(year: number, month: number): Date[] {
  const date = new Date(year, month, 1);
  const days = [];
  while (date.getMonth() === month) {
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  }
  return days;
}

function isSameDay(date1: Date, date2: Date): boolean {
  return (
    date1.getFullYear() === date2.getFullYear() &&
    date1.getMonth() === date2.getMonth() &&
    date1.getDate() === date2.getDate()
  );
}

function isWithinInterval(date: Date, start: Date, end: Date): boolean {
  return date >= start && date <= end;
}

function formatDate(date: Date): string {
  return `${MONTHS[date.getMonth()].slice(
    0,
    3
  )} ${date.getDate()}, ${date.getFullYear()}`;
}

export const DatePicker: React.FC = () => {
  const [startDate, setStartDate] = useState<Date | null>(null);
  const [endDate, setEndDate] = useState<Date | null>(null);
  const [currentMonth, setCurrentMonth] = useState(new Date());

  const daysInMonth = getDaysInMonth(
    currentMonth.getFullYear(),
    currentMonth.getMonth()
  );

  const handleDateClick = (date: Date) => {
    if (!startDate || (startDate && endDate)) {
      setStartDate(date);
      setEndDate(null);
    } else if (date > startDate) {
      setEndDate(date);
    } else {
      setEndDate(startDate);
      setStartDate(date);
    }
  };

  const isSelected = (date: Date) =>
    (startDate && isSameDay(startDate, date)) ||
    (endDate && isSameDay(endDate, date));

  const isInRange = (date: Date) =>
    startDate && endDate && isWithinInterval(date, startDate, endDate);

  const changeMonth = (increment: number) => {
    setCurrentMonth((prevMonth) => {
      const newMonth = new Date(prevMonth);
      newMonth.setMonth(newMonth.getMonth() + increment);
      return newMonth;
    });
  };

  return (
    <div className="w-80 bg-gray-50 dark:bg-gray-800 shadow-lg rounded-2xl overflow-hidden border border-gray-100 dark:border-gray-700">
      <div className="bg-white dark:bg-gray-800 p-4 flex justify-between items-center border-b border-gray-100 dark:border-gray-700">
        <button
          onClick={() => changeMonth(-1)}
          className="p-2 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-full transition-colors"
        >
          <ChevronLeftIcon className="w-5 h-5 text-gray-600 dark:text-gray-400" />
        </button>
        <h2 className="text-lg font-semibold text-gray-800 dark:text-gray-200">
          {MONTHS[currentMonth.getMonth()]} {currentMonth.getFullYear()}
        </h2>
        <button
          onClick={() => changeMonth(1)}
          className="p-2 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-full transition-colors"
        >
          <ChevronRightIcon className="w-5 h-5 text-gray-600 dark:text-gray-400" />
        </button>
      </div>
      <div className="grid grid-cols-7 gap-1 p-4">
        {DAYS.map((day) => (
          <div
            key={day}
            className="text-center text-sm font-medium text-gray-400 dark:text-gray-500 mb-2"
          >
            {day}
          </div>
        ))}
        {daysInMonth.map((date) => (
          <button
            key={date.toString()}
            onClick={() => handleDateClick(date)}
            className={`h-10 w-10 flex items-center justify-center rounded-full text-sm transition-all duration-200
              ${
                isSelected(date)
                  ? "bg-blue-500 text-white font-semibold shadow-md"
                  : ""
              }
              ${isInRange(date) ? "bg-blue-100 dark:bg-blue-900" : ""}
              ${
                !isSelected(date) && !isInRange(date)
                  ? "hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300"
                  : ""
              }
            `}
          >
            {date.getDate()}
          </button>
        ))}
      </div>
      <div className="border-t border-gray-100 dark:border-gray-700 bg-white dark:bg-gray-800">
        <div className="p-4 space-y-1">
          {startDate && (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              Start: {formatDate(startDate)}
            </p>
          )}
          {endDate && (
            <p className="text-sm text-gray-600 dark:text-gray-400">End: {formatDate(endDate)}</p>
          )}
        </div>
      </div>
    </div>
  );
};

export default DatePicker;

Card

Divider

On this page

Basic Date PickerCustom calendar Date PickerDropdown Date PickerRange Date Picker
logo

Empowering developers with intuitive and efficient UI components.

Created by Abhay Singh Rathore, a passionate Full-Stack Developer & UI/UX designer.

Quick Links

  • Home
  • Components
  • Templates

Connect

© 2025 Business Wish. All rights reserved.