DatePicker

free

DatePicker provides compact calendar-backed date entry for forms and filters.

@floating-ui/reactdayjsmotion
Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

export default function BasicDemo() {
  return <DatePicker placeholder="Pick a date" />;
}

Installation

Add this component with the NateUI CLI.

npx nateui@latest add DatePicker

Examples

Basic

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

export default function BasicExampleDemo() {
  return <DatePicker placeholder="Pick a date" />;
}

Range picker

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

const DatePickerRange = DatePicker.Range;

export default function RangePickerDemo() {
  return <DatePickerRange placeholder="Select dates range" />;
}

Date time picker

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

const DateTimepicker = DatePicker.DateTime;

export default function DateTimePickerDemo() {
  return <DateTimepicker placeholder="Pick date & time" />;
}

Controlled

Preview
Dark
import { useState } from 'react';
import DatePicker from '@/components/ui/DatePicker';

const DatePickerRange = DatePicker.Range;
const DateTimepicker = DatePicker.DateTime;

export default function ControlledDemo() {
  const [date, setDate] = useState<Date | null>(new Date());
  const [dateRange, setDateRange] = useState<[Date | null, Date | null]>([
    new Date(2022, 11, 1),
    new Date(2022, 11, 5),
  ]);
  const [dateTime, setDateTime] = useState<Date | null>(new Date());

  const handleDatePickerChange = (nextDate: Date | null) => {
    console.log('Selected date', nextDate);
    setDate(nextDate);
  };

  const handleRangePickerChange = (nextDate: [Date | null, Date | null]) => {
    console.log('Selected range date', nextDate);
    setDateRange(nextDate);
  };

  const handleDateTimeChange = (nextValue: Date | null) => {
    console.log('Selected date time: ', nextValue);
    setDateTime(nextValue);
  };

  return (
    <div className="flex flex-col gap-4">
      <DatePicker
        placeholder="Pick a date"
        value={date}
        onChange={handleDatePickerChange}
      />
      <DatePickerRange
        placeholder="Select dates range"
        value={dateRange}
        onChange={handleRangePickerChange}
      />
      <DateTimepicker
        placeholder="Pick date & time"
        value={dateTime}
        onChange={handleDateTimeChange}
      />
    </div>
  );
}

Format

Preview
Dark
Input format:
Inner label format:
import DatePicker from '@/components/ui/DatePicker';

export default function FormatDemo() {
  const date = new Date();

  return (
    <div className="flex flex-col gap-4">
      <div>
        <div className="mb-1">Input format:</div>
        <DatePicker inputFormat="MMM, DD YYYY" defaultValue={date} />
      </div>
      <div>
        <div className="mb-1">Inner label format:</div>
        <DatePicker
          labelFormat={{
            month: 'MMMM',
            year: 'YY',
          }}
          defaultValue={date}
        />
      </div>
    </div>
  );
}

Custom Render

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';
import Badge from '@/components/ui/Badge';

export default function CustomRenderDemo() {
  return (
    <DatePicker
      placeholder="Pick date"
      dayClassName={(date, { selected }) => {
        if (date.getDate() === 12 && !selected) {
          return 'text-red-600';
        }

        if (selected) {
          return 'text-white';
        }

        return 'text-gray-700 dark:text-gray-200';
      }}
      dayStyle={(date, { selected, outOfMonth }) => {
        if (date.getDate() === 18 && !selected) {
          return { color: '#15c39a' };
        }

        if (outOfMonth) {
          return {
            opacity: 0,
            pointerEvents: 'none',
            cursor: 'default',
          };
        }

        return {};
      }}
      renderDay={(date) => {
        const day = date.getDate();

        if (day !== 12) {
          return <span>{day}</span>;
        }

        return (
          <span className="relative flex h-full w-full items-center justify-center">
            {day}
            <Badge className="absolute bottom-1" innerClass="h-1 w-1" />
          </span>
        );
      }}
    />
  );
}

Disable out of period date

Preview
Dark
import dayjs from 'dayjs';
import DatePicker from '@/components/ui/DatePicker';

export default function DisableOutOfPeriodDateDemo() {
  const dateGap = 7;

  const minDate = dayjs(new Date())
    .subtract(dateGap, 'day')
    .startOf('day')
    .toDate();
  const maxDate = dayjs(new Date()).add(dateGap, 'day').toDate();

  return (
    <DatePicker
      placeholder="Pick a date"
      minDate={minDate}
      maxDate={maxDate}
    />
  );
}

Disabled certain date

Preview
Dark
import { useState } from 'react';
import DatePicker from '@/components/ui/DatePicker';

export default function DisabledCertainDateDemo() {
  const [dateValue, setDateValue] = useState<Date>(new Date());

  const onCertainPeriodChange = (date: Date) => {
    setDateValue(date);
  };

  const disableCertainDate = (date: Date) => {
    const banDate = [7, 15, 21];
    return banDate.includes(date.getDate());
  };

  return (
    <DatePicker
      value={dateValue}
      placeholder="Pick your date"
      disableDate={disableCertainDate}
      onChange={(date) => onCertainPeriodChange(date as Date)}
    />
  );
}

Multiple date view

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

const DatePickerRange = DatePicker.Range;

export default function DateViewCountDemo() {
  return (
    <DatePickerRange dateViewCount={2} placeholder="Multiple date view" />
  );
}

Disabled Input

Preview
Dark
import { useState } from 'react';
import DatePicker from '@/components/ui/DatePicker';

export default function DisabledInputDemo() {
  const [date] = useState(new Date());

  return (
    <div>
      <DatePicker disabled className="mb-4" placeholder="Select a date" />
      <DatePicker disabled className="mb-4" value={date} />
    </div>
  );
}

Inputtable

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

export default function InputtableDemo() {
  return (
    <DatePicker
      inputtable
      inputtableBlurClose={false}
      placeholder="Pick date"
    />
  );
}

Input Size

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';

export default function InputSizeDemo() {
  const date = new Date();

  return (
    <div>
      <DatePicker
        className="mb-4"
        placeholder="Select a date"
        defaultValue={date}
        size="sm"
      />
      <DatePicker
        className="mb-4"
        placeholder="Select a date"
        defaultValue={date}
      />
      <DatePicker
        className="mb-4"
        placeholder="Select a date"
        defaultValue={date}
        size="lg"
      />
    </div>
  );
}

Input Affix

inputSuffix or inputPrefix allow us to customize input affix content.

Preview
Dark
Prefix:
Suffix:
import DatePicker from '@/components/ui/DatePicker';
import { PiCalendar, PiCalendarBlank } from 'react-icons/pi'

export default function InputAffixDemo() {
  return (
    <div className="flex flex-col gap-4">
      <div>
        <div className="mb-1">Prefix:</div>
        <DatePicker
          inputPrefix={<PiCalendarBlank className="text-lg" />}
          inputSuffix={null}
        />
      </div>
      <div>
        <div className="mb-1">Suffix:</div>
        <DatePicker inputSuffix={<PiCalendar className="text-xl" />} />
      </div>
    </div>
  );
}

Clear Button

You can customize the clear button via clearable or clearButton props.

Preview
Dark
No clear button:
Custom clear button:
import DatePicker from '@/components/ui/DatePicker';
import Button from '@/components/ui/Button';

export default function ClearButtonDemo() {
  return (
    <div className="flex flex-col gap-4 wi">
      <div>
        <div className="mb-1">No clear button:</div>
        <DatePicker defaultValue={new Date()} clearable={false} />
      </div>
      <div>
        <div className="mb-1">Custom clear button:</div>
        <DatePicker
          defaultValue={new Date()}
          clearButton={
            <button 
              type="button" 
              className="text-xs px-1 py-2"
            >
              Clear
            </button>
          }
        />
      </div>
    </div>
  );
}

Localization

DatePicker receive locale value from ConfigProvider, but there is also an option to input locale manually.

Preview
Dark
import DatePicker from '@/components/ui/DatePicker';
import 'dayjs/locale/ko';

export default function LocalizationDemo() {
  return <DatePicker locale="ko" defaultValue={new Date()} inputFormat="LL" />;
}

API

DatePicker exports a root picker plus DatePicker.Range and DatePicker.DateTime.

Shared Picker Props

These props are available on DatePicker, DatePicker.Range, and DatePicker.DateTime.

PropDescriptionTypeDefault
clearableWhether the value can be cleared from the input.booleantrue
clearButtonCustom clear control rendered in the input suffix.ReactNode-
disabledDisable the input and prevent opening the picker.booleanfalse
inputPrefixContent rendered before the input text.ReactNode-
inputSuffixContent rendered after the input text when no clear button is shown.ReactNodeCalendar icon
inputtableAllow typing into the input.booleanfalse
nameName passed to the underlying input.stringComponent-specific
onBlurCalled when the input loses focus.PickerFocusHandler-
onDropdownCloseCalled after the floating calendar closes.() => void-
onDropdownOpenCalled after the floating calendar opens.() => void-
onFocusCalled when the input receives focus.PickerFocusHandler-
placeholderPlaceholder shown when no value is selected.string-
sizeControl size for the input.ControlSizeConfig controlSize
typeNative input type forwarded to the input.HTMLInputTypeAttribute'text'

Shared Calendar Props

These props are forwarded from the picker to the calendar grid.

PropDescriptionTypeDefault
dateViewCountAmount of date views displayed in the picker.number1
dayClassNameApply class names to days based on the date and modifiers.DatePickerDayClassName-
dayStyleApply inline styles to days based on the date and modifiers.DatePickerDayStyle-
defaultMonthDefault month for the uncontrolled picker view.DateSelected value or new Date()
defaultViewDefault picker view.PickerView'date'
disableDateSpecify dates that cannot be selected.DatePickerDisableDate-
disableOutOfMonthDisable days outside the visible month.booleanfalse
enableHeaderLabelEnable the header label to trigger view changes.booleantrue
firstDayOfWeekFirst day of the week.FirstDayOfWeek'monday'
hideOutOfMonthDatesHide days outside the visible month.booleanfalse
hideWeekdaysHide the weekday row.booleanfalse
labelFormatMonth and year format used by the date view header.DatePickerLabelFormat{ month: 'MMM', year: 'YYYY' }
localeDayjs locale used by the picker.stringConfig locale
lockViewKeep the current view level after selecting a month or year.booleanfalse
maxDateMaximum selectable date.Date-
minDateMinimum selectable date.Date-
renderDayRender custom day content.DatePickerRenderDay-
weekdayLabelFormatWeekday display format.string'dd'
weekendDaysWeekday indexes treated as weekends.DatePickerWeekendDays[0, 6]
yearLabelFormatYear label format.string'YYYY'

DatePicker

PropDescriptionTypeDefault
classNameClass names applied to the picker input.string-
closePickerOnChangeWhether to close the picker after a date is selected.booleantrue
defaultOpenWhether the picker is open on first render.booleanfalse
defaultValueDefault value of DatePicker. Use value for controlled usage.Date | null-
inputFormatDatePicker input display format.string'YYYY-MM-DD'
inputtableBlurCloseWhether to close the picker on input blur when inputtable is enabled.booleanfalse
openPickerOnClearWhether to open DatePicker after clearing the value.booleanfalse
onChangeCallback when a date cell is selected.DatePickerChangeHandler-
refRef forwarded to the underlying input.Ref<HTMLInputElement>-
valueControlled DatePicker value.Date | null-
...nativeDivPropsNative props for the wrapper, excluding onChange and value.NativeDatePickerDivProps-

DatePicker.Range

PropDescriptionTypeDefault
classNameClass names applied to the range picker input.string-
closePickerOnChangeWhether to close the picker after the range is selected.booleantrue
defaultOpenWhether the range picker is open on first render.booleanfalse
defaultValueDefault value of DatePicker.Range. Use value for controlled usage.DateRangeValue[null, null]
inputFormatDatePicker.Range input display format.string'YYYY-MM-DD'
openPickerOnClearCall the open callback after clearing. The range picker always reopens on clear.booleanfalse
onChangeCallback when the date range is selected.DateRangeChangeHandler-
refRef forwarded to the underlying input.Ref<HTMLInputElement>-
separatorSeparator between dates in the input.string'~'
singleDateAllow one date to be selected as both range endpoints.booleanfalse
valueControlled DatePicker.Range value.DateRangeValue-
...nativeDivPropsNative props for the wrapper, excluding owned picker props.NativeDateRangeDivProps-

DatePicker.DateTime

PropDescriptionTypeDefault
amPmWhether to set time input to 12-hour format.booleantrue
classNameClass names applied to the date-time picker input.string-
closePickerOnChangeWhether to close the picker after date or time selection.booleanfalse
defaultOpenWhether the date-time picker is open on first render.booleanfalse
defaultValueDefault value of DatePicker.DateTime. Use value for controlled usage.Date | null-
inputFormatDatePicker.DateTime input display format.string'DD-MMM-YYYY hh:mm a'
okButtonContentOK button content.ReactNode'OK'
openPickerOnClearWhether to open DatePicker.DateTime after clearing the value.booleanfalse
onChangeCallback when the date-time value changes.DatePickerChangeHandler-
refRef forwarded to the underlying input.Ref<HTMLInputElement>-
valueControlled DatePicker.DateTime value.Date | null-
...nativeDivPropsNative props for the wrapper, excluding owned picker props.NativeDateTimeDivProps-

Types

type ControlSize = 'lg' | 'md' | 'sm';
type PickerView = 'date' | 'month' | 'year';
type FirstDayOfWeek = 'sunday' | 'monday';
type DatePickerLabelFormat = { month: string; year: string };
type DatePickerWeekendDays = [number, number];
 
type DatePickerDayProps = {
  disabled: boolean;
  weekend: boolean;
  selectedInRange: boolean;
  selected: boolean;
  inRange: boolean;
  firstInRange: boolean;
  lastInRange: boolean;
  outOfMonth: boolean;
};
 
type DatePickerDayClassName = (
  date: Date,
  modifiers: DatePickerDayProps,
) => string;
type DatePickerDayStyle = (
  date: Date,
  modifiers: DatePickerDayProps,
) => CSSProperties;
type DatePickerDisableDate = (date: Date) => boolean;
type DatePickerRenderDay = (date: Date) => ReactNode;
type PickerFocusHandler = (
  event: FocusEvent<HTMLInputElement, Element>,
) => void;
 
type DatePickerChangeHandler = (value: Date | null) => void;
type DateRangeValue = [Date | null, Date | null];
type DateRangeChangeHandler = (value: DateRangeValue) => void;
 
type NativeDatePickerDivProps = Omit<
  ComponentProps<'div'>,
  'onChange' | 'value'
>;
type NativeDateRangeDivProps = Omit<
  ComponentProps<'div'>,
  'defaultValue' | 'onChange' | 'value'
>;
type NativeDateTimeDivProps = NativeDateRangeDivProps;