Skip to content
Dethink Components

ComponentsDatePicker

DatePicker

Let users type a date or choose one from a calendar.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
import { DatePicker, type DatePickerValue } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";

Try the examples, then open the code to use them in your app. Tab into a field to edit segments with the arrow keys or by typing, and press the calendar button to open the popover.

Basic

Label, helper description, and a name for native form submission — the uncontrolled default.

Launch date
Announcement goes out at 9:00 AM local time.
Show sourceexamples/date-picker/basic.tsx
examples/date-picker/basic.tsx
"use client";

import { DatePicker } from "@dethink/components";

export function DatePickerBasic() {
  return (
    <div className="mx-auto max-w-xs">
      <DatePicker
        label="Launch date"
        description="Announcement goes out at 9:00 AM local time."
        name="launchDate"
      />
    </div>
  );
}

Controlled and clearable

value and onValueChange pair with React state; clearable adds a clear button whenever a date is set.

Review deadline

Value: 2026-07-14

Show sourceexamples/date-picker/controlled.tsx
examples/date-picker/controlled.tsx
"use client";

import { useState } from "react";
import { Button, DatePicker, type DatePickerValue } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";

export function DatePickerControlled() {
  const [value, setValue] = useState<DatePickerValue | null>(
    new CalendarDate(2026, 7, 14),
  );

  return (
    <div className="mx-auto max-w-xs space-y-3">
      <DatePicker
        label="Review deadline"
        value={value}
        onValueChange={setValue}
        clearable
      />
      <div className="flex items-center justify-between gap-2">
        <p className="text-muted-foreground text-sm">
          Value: {value ? value.toString() : "none"}
        </p>
        <Button
          size="sm"
          variant="outline"
          onClick={() => setValue(new CalendarDate(2026, 7, 14))}
        >
          Reset
        </Button>
      </div>
    </div>
  );
}

Form states

Required, disabled, read-only, and invalid with an error message — each state styles the field, segments, and popover trigger consistently.

Required
Disabled
Read-only
Invalid
Pick a date after today.
Show sourceexamples/date-picker/states.tsx
examples/date-picker/states.tsx
"use client";

import { DatePicker } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";

export function DatePickerStates() {
  return (
    <div className="mx-auto grid max-w-md gap-5 sm:grid-cols-2">
      <DatePicker label="Required" required />
      <DatePicker
        label="Disabled"
        disabled
        defaultValue={new CalendarDate(2026, 7, 14)}
      />
      <DatePicker
        label="Read-only"
        readOnly
        defaultValue={new CalendarDate(2026, 7, 14)}
      />
      <DatePicker
        label="Invalid"
        invalid
        errorMessage="Pick a date after today."
        defaultValue={new CalendarDate(2026, 6, 1)}
      />
    </div>
  );
}

Bounds and unavailable dates

minValue/maxValue clamp selection while isDateUnavailable blocks individual dates in the popover calendar.

Delivery date
Weekday deliveries in July only.
Show sourceexamples/date-picker/bounds.tsx
examples/date-picker/bounds.tsx
"use client";

import { DatePicker } from "@dethink/components";
import { CalendarDate, getDayOfWeek } from "@internationalized/date";

export function DatePickerBounds() {
  return (
    <div className="mx-auto max-w-xs">
      <DatePicker
        label="Delivery date"
        description="Weekday deliveries in July only."
        minValue={new CalendarDate(2026, 7, 6)}
        maxValue={new CalendarDate(2026, 7, 31)}
        isDateUnavailable={(date) => {
          const dayOfWeek = getDayOfWeek(date, "en-US");
          return dayOfWeek === 0 || dayOfWeek === 6;
        }}
      />
    </div>
  );
}

DatePicker owns its field anatomy — pass a label instead of wrapping it in an external one.

DatePicker props
PropWhat it doesDefault
valueDatePickerValue | nullControlled selected date — a CalendarDate from @internationalized/date.Not set
defaultValueDatePickerValue | nullThe starting selection when the component manages its own state.Not set
onValueChange(value: DatePickerValue | null) => voidFires when the selection changes or is cleared.Not set
labelReactNodeField label rendered above the segmented input.Not set
descriptionReactNodeMuted helper text below the field.Not set
errorMessageReactNodeValidation message shown when the field is invalid.Not set
namestringName of the hidden input submitted with the serialized ISO date.Not set
required / disabled / readOnly / invalidbooleanMakes the field required, disabled, read-only, or invalid.false
clearablebooleanShows a clear button when a date is selected.false
minValue / maxValueDateValueInclusive selection bounds enforced in field and calendar.Not set
isDateUnavailable(date: DateValue) => booleanMarks individual dates unavailable in the popover calendar.Not set
localestringBCP 47 tag controlling segment order and formatting.runtime locale
weekStartsOn"sun" | "mon" | … | "sat"First day of the week in the popover calendar.locale default